@loicngr/kobo 1.11.43 → 1.11.45

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 (166) hide show
  1. package/AGENTS.md +74 -1
  2. package/CHANGELOG.md +11 -0
  3. package/README.md +13 -1
  4. package/dist/mcp-server/kobo-tasks-handlers.js +33 -75
  5. package/dist/mcp-server/kobo-tasks-server.js +82 -9
  6. package/dist/server/db/auto-loop-schema.js +44 -0
  7. package/dist/server/db/migrations.js +18 -0
  8. package/dist/server/db/review-return-schema.js +10 -0
  9. package/dist/server/db/schema.js +8 -1
  10. package/dist/server/db/session-handoff-schema.js +24 -0
  11. package/dist/server/index.js +12 -9
  12. package/dist/server/routes/auto-loop-messages.js +51 -0
  13. package/dist/server/routes/documents.js +1 -1
  14. package/dist/server/routes/workspaces.js +119 -145
  15. package/dist/server/services/agent/engines/claude-code/engine.js +16 -0
  16. package/dist/server/services/agent/engines/codex/engine.js +92 -31
  17. package/dist/server/services/agent/orchestrator.js +298 -96
  18. package/dist/server/services/agent/session-controller.js +42 -2
  19. package/dist/server/services/auto-loop-message-service.js +79 -0
  20. package/dist/server/services/auto-loop-service.js +225 -86
  21. package/dist/server/services/auto-loop-state-service.js +30 -0
  22. package/dist/server/services/cron-service.js +30 -16
  23. package/dist/server/services/engine-handoff-service.js +5 -5
  24. package/dist/server/services/quota-backoff-service.js +42 -10
  25. package/dist/server/services/review-return-service.js +64 -0
  26. package/dist/server/services/review-service.js +187 -0
  27. package/dist/server/services/session-activity-service.js +17 -0
  28. package/dist/server/services/session-handoff-runtime.js +26 -0
  29. package/dist/server/services/session-handoff-service.js +479 -0
  30. package/dist/server/services/settings-service.js +3 -3
  31. package/dist/server/services/task-mutations.js +186 -0
  32. package/dist/server/services/wakeup-service.js +24 -1
  33. package/dist/server/services/workspace-message-service.js +16 -2
  34. package/dist/server/services/workspace-service.js +28 -36
  35. package/dist/server/utils/workspace-lifecycle-guard.js +35 -20
  36. package/dist/shared/auto-loop-prompts.js +22 -11
  37. package/dist/shared/auto-loop-types.js +1 -0
  38. package/dist/shared/document-roots.js +2 -0
  39. package/dist/shared/review.js +6 -0
  40. package/dist/shared/session-handoff.js +4 -0
  41. package/dist/shared/task-verification.js +11 -0
  42. package/package.json +12 -12
  43. package/src/client/dist/pwa/assets/ActivityFeed-CLXjdqS8.js +8 -0
  44. package/src/client/dist/pwa/assets/{ChangelogPage-DX1WGFea.js → ChangelogPage-CnXTnFhe.js} +1 -1
  45. package/src/client/dist/pwa/assets/{ClosePopup-BqW5dy-O.js → ClosePopup-CWjIRHxu.js} +1 -1
  46. package/src/client/dist/pwa/assets/{ComparisonPanel-B4ne55Xj.js → ComparisonPanel-CKylN45q.js} +2 -2
  47. package/src/client/dist/pwa/assets/CreatePage-SoCcvxuD.js +2 -0
  48. package/src/client/dist/pwa/assets/{DashboardPage-Cv6HJEcO.js → DashboardPage-CZQLfoV1.js} +1 -1
  49. package/src/client/dist/pwa/assets/{DiffViewer-COwGxPt6.js → DiffViewer-Csf3WmLc.js} +4 -4
  50. package/src/client/dist/pwa/assets/{DocumentsPanel-DCXpLLb7.js → DocumentsPanel-BeCttB-x.js} +1 -1
  51. package/src/client/dist/pwa/assets/{DrawerToggleButton-DRL3RCkM.js → DrawerToggleButton-BJBBYeOc.js} +1 -1
  52. package/src/client/dist/pwa/assets/GitPanel-B-ZHgghQ.js +3 -0
  53. package/src/client/dist/pwa/assets/{HealthPage-XrOuMoDJ.js → HealthPage-l88TEk-k.js} +1 -1
  54. package/src/client/dist/pwa/assets/MainLayout-BAAQLq95.css +1 -0
  55. package/src/client/dist/pwa/assets/MainLayout-Cf4Q9x1u.js +2 -0
  56. package/src/client/dist/pwa/assets/{QBadge-DbkxGtht.js → QBadge-FWC1zDCq.js} +1 -1
  57. package/src/client/dist/pwa/assets/{QBanner-DhqH95GW.js → QBanner-CcRI_QIy.js} +1 -1
  58. package/src/client/dist/pwa/assets/QBtn-DEdx_Y1V.js +1 -0
  59. package/src/client/dist/pwa/assets/{QBtnDropdown-163oM6T_.js → QBtnDropdown-44Mj-y_1.js} +1 -1
  60. package/src/client/dist/pwa/assets/{QBtnGroup-DELKYo3u.js → QBtnGroup-CAoD6G0Q.js} +1 -1
  61. package/src/client/dist/pwa/assets/{QBtnToggle-BI3k3Ch2.js → QBtnToggle-C_hQ2UCQ.js} +1 -1
  62. package/src/client/dist/pwa/assets/{QChip-owciRuZu.js → QChip-DCPUhqXX.js} +1 -1
  63. package/src/client/dist/pwa/assets/QDrawer-B4qHw8wt.js +1 -0
  64. package/src/client/dist/pwa/assets/QExpansionItem-Bok1m8Wi.js +1 -0
  65. package/src/client/dist/pwa/assets/{QItemSection-D_5_0UrX.js → QItemSection-BhqphaH6.js} +1 -1
  66. package/src/client/dist/pwa/assets/{QList-qupzuEqO.js → QList-CHm4JNP0.js} +1 -1
  67. package/src/client/dist/pwa/assets/{QMarkupTable-B9QuKtK_.js → QMarkupTable-CNpiA9oq.js} +1 -1
  68. package/src/client/dist/pwa/assets/{QPage-DaX9sMQC.js → QPage-BXBw2Alx.js} +1 -1
  69. package/src/client/dist/pwa/assets/QSelect-BbtD5Iks.js +1 -0
  70. package/src/client/dist/pwa/assets/{QSpinnerDots-DnCV3VzI.js → QSpinnerDots-BkFiCsH3.js} +1 -1
  71. package/src/client/dist/pwa/assets/{QTooltip-BQWY7aeM.js → QTooltip-BDihn2aY.js} +1 -1
  72. package/src/client/dist/pwa/assets/SchedulePanel-DiWCDNZ8.js +1 -0
  73. package/src/client/dist/pwa/assets/{SearchPage-DOHkP5lj.js → SearchPage-BwZ2TX1G.js} +1 -1
  74. package/src/client/dist/pwa/assets/SettingsPage-BUh0WfNf.js +9 -0
  75. package/src/client/dist/pwa/assets/{SplitWorkspacePage-DL4kp9Ah.js → SplitWorkspacePage-Bg6nKBcA.js} +1 -1
  76. package/src/client/dist/pwa/assets/{TerminalPanel-DHDnyiYh.js → TerminalPanel-Cq-FR7A7.js} +9 -9
  77. package/src/client/dist/pwa/assets/{TouchPan-BnHXDR6F.js → TouchPan-BQ1cvzRC.js} +1 -1
  78. package/src/client/dist/pwa/assets/{TourReplayButton-ClVcB6mO.js → TourReplayButton-Dz1yEz_z.js} +1 -1
  79. package/src/client/dist/pwa/assets/{WorkspaceAttentionLabels-Bxe6oIJI.js → WorkspaceAttentionLabels-BCVOP8vp.js} +1 -1
  80. package/src/client/dist/pwa/assets/WorkspacePage-BbUvR1Vf.css +1 -0
  81. package/src/client/dist/pwa/assets/WorkspacePage-Cl8gap4b.js +4 -0
  82. package/src/client/dist/pwa/assets/{browser-Bkx4fbxl.js → browser-BmWgBx9M.js} +1 -1
  83. package/src/client/dist/pwa/assets/build-path-tree-6EjBmYYY.js +1 -0
  84. package/src/client/dist/pwa/assets/de-COObokpu.js +17 -0
  85. package/src/client/dist/pwa/assets/documents-BZ8bwcjr.js +1 -0
  86. package/src/client/dist/pwa/assets/{editor.api-DreEG0If.js → editor.api-CK7--ckY.js} +1 -1
  87. package/src/client/dist/pwa/assets/editor.worker-iO5iN0DB.js +33 -0
  88. package/src/client/dist/pwa/assets/efforts-Bw0o2Bud.js +9 -0
  89. package/src/client/dist/pwa/assets/engineFeatures-B-9jHocY.css +1 -0
  90. package/src/client/dist/pwa/assets/engineFeatures-DQO9HHXI.js +1 -0
  91. package/src/client/dist/pwa/assets/es-By2Q9Tca.js +17 -0
  92. package/src/client/dist/pwa/assets/expand-template-C8VyjASo.js +1 -0
  93. package/src/client/dist/pwa/assets/{format-B7z3F-Mw.js → format-LtTLLitJ.js} +3 -3
  94. package/src/client/dist/pwa/assets/{formatters-BTBiU0v3.js → formatters-Bl9zA7Ai.js} +1 -1
  95. package/src/client/dist/pwa/assets/fr-D-sd0ddn.js +17 -0
  96. package/src/client/dist/pwa/assets/{freemarker2-BZNTVQ3K.js → freemarker2-DxezMaje.js} +1 -1
  97. package/src/client/dist/pwa/assets/{handlebars-k8tN0dI3.js → handlebars-DK_Bj6Rx.js} +1 -1
  98. package/src/client/dist/pwa/assets/{html-iZL3bbXq.js → html-DFfsfStD.js} +1 -1
  99. package/src/client/dist/pwa/assets/i18n-aDWy4KHt.js +1 -0
  100. package/src/client/dist/pwa/assets/index-0wtBh1Xt.css +1 -0
  101. package/src/client/dist/pwa/assets/index-BLd8DAzg.js +20 -0
  102. package/src/client/dist/pwa/assets/it-CeK5lyIA.js +17 -0
  103. package/src/client/dist/pwa/assets/{javascript-TV6gg0MO.js → javascript-DuNbcaL7.js} +1 -1
  104. package/src/client/dist/pwa/assets/{liquid-Cifa5ujF.js → liquid-CM3JKyhv.js} +1 -1
  105. package/src/client/dist/pwa/assets/{mdx-Bnj_8yGE.js → mdx-BG3zYwNF.js} +1 -1
  106. package/src/client/dist/pwa/assets/{monaco-contributions-pEh0n9Wk.js → monaco-contributions-DLscZGH-.js} +1 -1
  107. package/src/client/dist/pwa/assets/monaco.contribution-DnhZHwXT.js +2 -0
  108. package/src/client/dist/pwa/assets/{network-auth-3_5p4fdc.js → network-auth-BJiPbO5l.js} +1 -1
  109. package/src/client/dist/pwa/assets/{notify-theme-D_nf9AeF.js → notify-theme-D4p3qPkp.js} +1 -1
  110. package/src/client/dist/pwa/assets/{pending-diff-open-CUnxC1xw.js → pending-diff-open-dYIFdS4r.js} +1 -1
  111. package/src/client/dist/pwa/assets/permissionModes-B7fuUegU.js +36 -0
  112. package/src/client/dist/pwa/assets/{pinia-BKqmoVru.js → pinia-CTJ3OfP3.js} +1 -1
  113. package/src/client/dist/pwa/assets/{private.use-form-C7umbGO-.js → private.use-form-Bk8ti264.js} +1 -1
  114. package/src/client/dist/pwa/assets/{project-color-CihwpDAA.js → project-color-R_1je4vW.js} +1 -1
  115. package/src/client/dist/pwa/assets/{python-DOoNBSNL.js → python-COs6pHk2.js} +1 -1
  116. package/src/client/dist/pwa/assets/{razor-Bvq5vVpJ.js → razor-Jl1VqMsk.js} +1 -1
  117. package/src/client/dist/pwa/assets/reactivity.esm-bundler-Bo9anJjg.js +1 -0
  118. package/src/client/dist/pwa/assets/render-chat-markdown-AaOo0Tgq.js +67 -0
  119. package/src/client/dist/pwa/assets/{runtime-core.esm-bundler-CDnVUfeZ.js → runtime-core.esm-bundler-CNFKm4ij.js} +1 -1
  120. package/src/client/dist/pwa/assets/{typescript-VVzxoeyM.js → typescript-BU_TUuAM.js} +1 -1
  121. package/src/client/dist/pwa/assets/{use-checkbox-FnauAgTp.js → use-checkbox-CnvHBhSK.js} +1 -1
  122. package/src/client/dist/pwa/assets/{use-id-BIuaWKkB.js → use-id-wXd4c8FA.js} +1 -1
  123. package/src/client/dist/pwa/assets/use-is-mobile-DpKI3XMy.js +1 -0
  124. package/src/client/dist/pwa/assets/{use-search-index-status-DtLzygcy.js → use-search-index-status-Bluf9L99.js} +1 -1
  125. package/src/client/dist/pwa/assets/use-slide-transition-CiaDm-tR.js +1 -0
  126. package/src/client/dist/pwa/assets/use-tours-CVn874kD.js +2 -0
  127. package/src/client/dist/pwa/assets/{workspace-templates-1ui80Kqo.js → workspace-templates-BCKR8TXr.js} +1 -1
  128. package/src/client/dist/pwa/assets/{xml-CzGFIxQa.js → xml-gFFsobxE.js} +1 -1
  129. package/src/client/dist/pwa/assets/{yaml-Bl7nDJeC.js → yaml-DaXaqaGD.js} +1 -1
  130. package/src/client/dist/pwa/index.html +10 -10
  131. package/src/client/dist/pwa/sw.js +1 -1
  132. package/src/mcp-server/README.md +8 -1
  133. package/src/mcp-server/kobo-tasks-handlers.ts +72 -105
  134. package/src/mcp-server/kobo-tasks-server.ts +94 -9
  135. package/src/client/dist/pwa/assets/ActivityFeed-D1e-zV3O.js +0 -8
  136. package/src/client/dist/pwa/assets/CreatePage-Bx_GpUni.js +0 -2
  137. package/src/client/dist/pwa/assets/GitPanel-C9mz4GXF.js +0 -3
  138. package/src/client/dist/pwa/assets/MainLayout-BwV89R-l.css +0 -1
  139. package/src/client/dist/pwa/assets/MainLayout-CwWavQjV.js +0 -2
  140. package/src/client/dist/pwa/assets/QBtn-CZaBclNw.js +0 -1
  141. package/src/client/dist/pwa/assets/QDrawer-DNEj8wLZ.js +0 -1
  142. package/src/client/dist/pwa/assets/QSelect-BUlOQe5k.js +0 -1
  143. package/src/client/dist/pwa/assets/SchedulePanel-Bos94OyR.js +0 -1
  144. package/src/client/dist/pwa/assets/SettingsPage-DtGsd0XH.js +0 -9
  145. package/src/client/dist/pwa/assets/WorkspacePage-Clc4Fl3B.js +0 -4
  146. package/src/client/dist/pwa/assets/WorkspacePage-DCg9zSxz.css +0 -1
  147. package/src/client/dist/pwa/assets/build-path-tree-BpSY7N5O.js +0 -1
  148. package/src/client/dist/pwa/assets/de-BU0dILBs.js +0 -17
  149. package/src/client/dist/pwa/assets/documents-BIlWh3o-.js +0 -1
  150. package/src/client/dist/pwa/assets/editor.worker-CwQAd_xr.js +0 -30
  151. package/src/client/dist/pwa/assets/efforts-D_yTzymv.js +0 -9
  152. package/src/client/dist/pwa/assets/engineFeatures-C33LTVkK.js +0 -1
  153. package/src/client/dist/pwa/assets/es-CNp0s9na.js +0 -17
  154. package/src/client/dist/pwa/assets/expand-template-wRhAXT-1.js +0 -1
  155. package/src/client/dist/pwa/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff +0 -0
  156. package/src/client/dist/pwa/assets/fr-RqJyWSdm.js +0 -17
  157. package/src/client/dist/pwa/assets/i18n--PCet00a.js +0 -1
  158. package/src/client/dist/pwa/assets/index-CPfrY38K.js +0 -20
  159. package/src/client/dist/pwa/assets/index-CUoUy6tH.css +0 -1
  160. package/src/client/dist/pwa/assets/it-DSxNuCwL.js +0 -17
  161. package/src/client/dist/pwa/assets/monaco.contribution-D7NmJUJH.js +0 -2
  162. package/src/client/dist/pwa/assets/permissionModes-DC51Pz84.js +0 -36
  163. package/src/client/dist/pwa/assets/reactivity.esm-bundler-DEJj9cFv.js +0 -1
  164. package/src/client/dist/pwa/assets/render-chat-markdown-BQ_saiy5.js +0 -67
  165. package/src/client/dist/pwa/assets/use-is-mobile-CWjqe8gC.js +0 -1
  166. package/src/client/dist/pwa/assets/use-tours-BKeYrJaQ.js +0 -2
@@ -1 +1 @@
1
- if(!self.define){let s,e={};const a=(a,r)=>(a=new URL(a+".js",r).href,e[a]||new Promise(e=>{if("document"in self){const s=document.createElement("script");s.src=a,s.onload=e,document.head.appendChild(s)}else s=a,importScripts(a),e()}).then(()=>{let s=e[a];if(!s)throw new Error(`Module ${a} didn’t register its module`);return s}));self.define=(r,i)=>{const c=s||("document"in self?document.currentScript.src:"")||location.href;if(e[c])return;let d={};const f=s=>a(s,c),b={module:{uri:c},exports:d,require:f};e[c]=Promise.all(r.map(s=>b[s]||f(s))).then(s=>(i(...s),d))}}define(["./workbox-778a14ff"],function(s){"use strict";s.setCacheNameDetails({prefix:"kobo-client"}),self.addEventListener("message",s=>{s.data&&"SKIP_WAITING"===s.data.type&&self.skipWaiting()}),s.clientsClaim(),s.precacheAndRoute([{url:"manifest.json",revision:"73f02ba4eb4414fb70bbe5ca76cc9580"},{url:"index.html",revision:"cf903d34e7b7a6991d7a7a6d836103e5"},{url:"favicon.svg",revision:"9d89ef10d49f14d08c25cfca9bd4ea75"},{url:"sounds/yaaa.mp3",revision:"2161c5eb77ac61349f6fe573f62d8404"},{url:"sounds/warcraft-3-humain-travail.mp3",revision:"0b8bd1b9be23803c3ac84eaf0d1b5287"},{url:"sounds/tu-vas-la-fermer.mp3",revision:"1688aaa18b0a307a3016c3fd39321f59"},{url:"sounds/travail_termine.mp3",revision:"a194c4cc479b59ba13746b08bca634b9"},{url:"sounds/ta-gueule.mp3",revision:"44aa9b15c9abe9a846f8034a23482b24"},{url:"sounds/pas-ca-zinedine.mp3",revision:"57ec46faf5b7d1c2f370d7167e284f04"},{url:"sounds/ouais-cest-greg.mp3",revision:"55624f422636b19422b3bc700aa8da9e"},{url:"sounds/nan-wallah-pardon.mp3",revision:"16edfe0a39fde73db0f30a7a067a77ff"},{url:"sounds/nan-tu-degages.mp3",revision:"282678eceb54e09eb8a7edf4f9fb0e21"},{url:"sounds/mais-laisse-moi-dormir-zebi.mp3",revision:"05d8419f91effcf56a6d09ed35544d06"},{url:"sounds/hey.mp3",revision:"e68017c8f32b3e815e339dad099dc830"},{url:"sounds/gta-v-death.mp3",revision:"72eaa8958882d5f2040f4b9b4f3ba620"},{url:"sounds/for-shure.mp3",revision:"71dd2a2c874a04e67613d49045d926e7"},{url:"sounds/faaah.mp3",revision:"a0220dd11038add054573c26d2f0b6ac"},{url:"sounds/dry-fart.mp3",revision:"afdf096e4a705d908392ed9b4f827bc9"},{url:"sounds/ca_va_peter.mp3",revision:"004452d7682a043e1c13e213a1a56766"},{url:"sounds/basic-notification.mp3",revision:"3f6df726a5e85560dfecf4bb592d2fda"},{url:"sounds/bah-alors-on-est-nul.mp3",revision:"b30241371b49465f62997213bcdfe4b2"},{url:"sounds/arretez-les-messages.mp3",revision:"26f667dccdfddb8c534a5482475b729a"},{url:"sounds/arrete-de-mentir.mp3",revision:"1a9b5157f362dd3e0acc479da4fea708"},{url:"sounds/aller-ftg.mp3",revision:"bcc00bd838e61eb9571c8fdc0f400d19"},{url:"sounds/7eme-compagnie-03.mp3",revision:"49ee08dd595e0e9659042e4e854b0141"},{url:"fonts/GeistMono-Variable.woff2",revision:"308360d8a547331fd40bc09a7145d59a"},{url:"fonts/Geist-Variable.woff2",revision:"dfa48d5a853753289194436953e3f202"},{url:"fonts/GEIST-LICENSE.txt",revision:"563d13575f813953c3151e1ecce3b76f"},{url:"assets/yaml-Bl7nDJeC.js",revision:"f70e125cdee8f18bf05c2075805e5711"},{url:"assets/xml-CzGFIxQa.js",revision:"969be3afde15151ffa7a2cb8a541e903"},{url:"assets/workspace-templates-1ui80Kqo.js",revision:"7021d9c7254e6d54d7bc0bdeba30d180"},{url:"assets/workspace-page-layout-Dw9NhZsL.js",revision:"0c933f7b6c6bf3c90ea1875abad85392"},{url:"assets/wgsl-DpFanUEy.js",revision:"4cf32279d7c6a601611a6e32a14f3b1e"},{url:"assets/vb-DV3o63ZY.js",revision:"a5b3a756d667f5e4a5da6da4013d7341"},{url:"assets/use-tours-CTZuBZOi.css",revision:"2f6d79046e1409f0472f65179eaa76f3"},{url:"assets/use-tours-BKeYrJaQ.js",revision:"861ec32e0668dca3532057da7912b3fc"},{url:"assets/use-search-index-status-DtLzygcy.js",revision:"d6952aee8e5013273ceeb533b4bb822a"},{url:"assets/use-is-mobile-CWjqe8gC.js",revision:"d1c4af193dfd98b8d775c51ddcbd45a0"},{url:"assets/use-id-BIuaWKkB.js",revision:"515b4eadf57c35d0e2b42311ccc01993"},{url:"assets/use-checkbox-FnauAgTp.js",revision:"298e92c55534c2c194c6fa1ef7a9ea6f"},{url:"assets/typespec-B8J7ngcE.js",revision:"6c28560625f59db6a5897aa92de81033"},{url:"assets/typescript-VVzxoeyM.js",revision:"9927a09292dbcf6d5ebdc653ecb532c9"},{url:"assets/twig-De2hgUGE.js",revision:"dfb4c76c8ec0d822070abac68d2bd473"},{url:"assets/tcl-DISqw1ZD.js",revision:"6d0ddaebd76ad41c47c96d484af119f8"},{url:"assets/systemverilog-Bz4Y3fRF.js",revision:"18e6d6e82eeb1107458d8d5531f82246"},{url:"assets/swift-Bxkupp3x.js",revision:"65b88f49188974d7c12e1a6cd12a9de5"},{url:"assets/st-DbInun42.js",revision:"d7294c4d47351db4e5edd4d91e445a21"},{url:"assets/sql-NEE52Syq.js",revision:"48352e15fff2141c7deaaab4e51e9565"},{url:"assets/sparql-D_Lu-MrJ.js",revision:"65390637b1a24614803db6844a0db77b"},{url:"assets/sophia-CRfGWb83.js",revision:"a330db913fee26a14679bed631a59043"},{url:"assets/solidity-BEEn4gHE.js",revision:"c2cd02221ec3d86f9a6bb09bfb1f8978"},{url:"assets/shell-CC2rA5mh.js",revision:"8362d325cda511ef760335e0847d3910"},{url:"assets/scss-gp-XZpBa.js",revision:"bf0805dd5cd80d90fef58c9866a7751e"},{url:"assets/scheme-BeGwcela.js",revision:"55c990715708ea012165486d065b3e2c"},{url:"assets/scala-DHpiXF5c.js",revision:"4eeea167d27954255e39d91412b62f87"},{url:"assets/sb-CcwsVR0C.js",revision:"93fc05f23a9cbb96d4f72dbc73e2e53b"},{url:"assets/rust-DdL9SqIa.js",revision:"356bac76300c8d83e8e9d76becf3c9ea"},{url:"assets/runtime-core.esm-bundler-CDnVUfeZ.js",revision:"958c358bc7005237e86c709b3248ae06"},{url:"assets/ruby-DezsRK8O.js",revision:"95c3294c6d6cead3cccd7e4e973ab964"},{url:"assets/restructuredtext-BYgofb2h.js",revision:"f75377ae694f4e8f0bcccd05b5b9e65c"},{url:"assets/render-chat-markdown-BQ_saiy5.js",revision:"e5e74a6b71f05501b95b04d7d388237d"},{url:"assets/redshift-DT7zqm-g.js",revision:"44e23f67b6a02e60d28c9947cd025207"},{url:"assets/redis-ClamHrr6.js",revision:"e3141183a6756253db43e10f8a305787"},{url:"assets/reactivity.esm-bundler-DEJj9cFv.js",revision:"202b2fcc10c0494e359dc0181e4d28e8"},{url:"assets/razor-Bvq5vVpJ.js",revision:"b080d7007d8b28d28f024be5f5e67d08"},{url:"assets/r-BwWrilGY.js",revision:"f18d3e790ef07bc993539322d29548e4"},{url:"assets/qsharp-DkqhCAOL.js",revision:"c53fe08a83f8fcbcd81723105136a691"},{url:"assets/python-DOoNBSNL.js",revision:"465779d6674dc597ea7f62dbeb7f04ff"},{url:"assets/pug-Z5eAx3Zn.js",revision:"6e3de6d5214d2cf61b90949e1d383b49"},{url:"assets/protobuf-C531GsRP.js",revision:"04e688a7fef2bde8cef525653497371f"},{url:"assets/project-color-CihwpDAA.js",revision:"d35b1287bfc8b09c86c83f44f804ac7b"},{url:"assets/private.use-form-C7umbGO-.js",revision:"115ec085187459512189754b7325cea5"},{url:"assets/powershell-DmHpPYUd.js",revision:"ff476e9c4398edc9dfd2eb0ee9356352"},{url:"assets/powerquery-D3hlyOfw.js",revision:"0cacccadbe7cd4415f9a3112763c89f3"},{url:"assets/postiats-43DmfD33.js",revision:"b5dbce3331b7ccb325853328702b4bd9"},{url:"assets/pla-CopQ2nXW.js",revision:"b31678678d642accba98d7e7249a20b2"},{url:"assets/pinia-BKqmoVru.js",revision:"309cc3e9d7688b550c4490f51a28959f"},{url:"assets/php-nr791fC2.js",revision:"ee487693840b66c2abf7c2da872dd6a8"},{url:"assets/pgsql-DTj74zXo.js",revision:"75375029d157fc5e789a13718eed9da7"},{url:"assets/permissionModes-DC51Pz84.js",revision:"3d17a1fac9d142434ec6e71a31c8ee75"},{url:"assets/perl-oz_6vUea.js",revision:"fee6d319d328db438b336b52ac07a46a"},{url:"assets/pending-diff-open-CUnxC1xw.js",revision:"95dce7ed9c86be3db18543811f57198c"},{url:"assets/pascaligo-D-ptJ9y-.js",revision:"88be4e81a252f44f049ac92f7b6ea518"},{url:"assets/pascal-DrH0SRf2.js",revision:"0d81121099a69b47e10701bf075fe3cd"},{url:"assets/objective-c-FvmIjYaQ.js",revision:"6d64543dd4430fb71bcd7a5347a0398c"},{url:"assets/notify-theme-D_nf9AeF.js",revision:"4b06a7314fea68d0d92d93b3d6b2e1fb"},{url:"assets/network-auth-3_5p4fdc.js",revision:"77f4250805772a30fffbef62e8ba3391"},{url:"assets/mysql-SOo6toE5.js",revision:"677c089d979324385539e96bd2eb11e4"},{url:"assets/msdax-DauUninz.js",revision:"a63bfea2dd041755a34fe3e307159413"},{url:"assets/monaco.contribution-D7NmJUJH.js",revision:"d8121ac7b6b5355a9181fe8c569aa3de"},{url:"assets/monaco-contributions-pEh0n9Wk.js",revision:"f1c4458390762b3a0fee764c03d4b8bc"},{url:"assets/monaco-contributions-Cb0afGfW.css",revision:"9c8dff3575c2e943e7ad49f78bbdb6d2"},{url:"assets/mips-CIPQ_RoX.js",revision:"b22614ddc8855670a3f76290908877f5"},{url:"assets/mdx-Bnj_8yGE.js",revision:"972947ca27a8346736a217d473b312d1"},{url:"assets/markdown-Cimd5fb3.js",revision:"38eaa88ca7719b9da2894b7c26f2f65b"},{url:"assets/m3-D-oSqn_W.js",revision:"624c73b0332fe1ddfef6013306c5998d"},{url:"assets/lua-CsQS60Ue.js",revision:"5568edf60b64f912bd17561f26e03d44"},{url:"assets/liquid-Cifa5ujF.js",revision:"b4026cda10275650212d5ed6c03f4629"},{url:"assets/lexon-CfSJPG6W.js",revision:"32b224ffe991474a4cfcbed19971a98d"},{url:"assets/less-B9JPFI3C.js",revision:"c80573ae2313727c545a585d90d3ff36"},{url:"assets/kotlin-BOotOW0E.js",revision:"7c2a31b16b6ddc97b60891b09afa11b1"},{url:"assets/julia-Bri6UV-V.js",revision:"bb5062cdf870c17c7c9be635c1a8a3be"},{url:"assets/javascript-TV6gg0MO.js",revision:"4c921a92215ca1880d11c791bd9a4173"},{url:"assets/java-BEtHBSE6.js",revision:"987edcd2170749acca47ea184dd9ab25"},{url:"assets/it-DSxNuCwL.js",revision:"7fee49ac38f41ffe7cd9208951c486e7"},{url:"assets/ini-sBoK_t0W.js",revision:"35f8ec10844ea4f62c2712d3f5c1e129"},{url:"assets/index-CUoUy6tH.css",revision:"a8c1e129e4ca8531dff2ac89ad0d6778"},{url:"assets/index-CPfrY38K.js",revision:"24175678b5172b8806d891bb51810e5f"},{url:"assets/i18n--PCet00a.js",revision:"72c69d3ecef43e3d8533628611802e2e"},{url:"assets/html-iZL3bbXq.js",revision:"e24cf2d14a5c899ab54a890c35e827d6"},{url:"assets/hcl-CpzslTdj.js",revision:"f9ef1004e908957ec1c3bbea2049a0e9"},{url:"assets/handlebars-k8tN0dI3.js",revision:"904848a6ae953b41812601833411565b"},{url:"assets/graphql-fmXr3nnJ.js",revision:"a51df1d5dca011f5d85dd09a2ffbe1e5"},{url:"assets/go-C-y9NEjX.js",revision:"9213c8381eb32996b86ca9600ca6a07e"},{url:"assets/fsharp-C8Ef5oNN.js",revision:"72f3de59be781f8a4ec49d16bac02119"},{url:"assets/freemarker2-BZNTVQ3K.js",revision:"1a66cc17ed48e3c363c94a44eb220bc2"},{url:"assets/fr-RqJyWSdm.js",revision:"7e72b1855c10b9a0635f96db638b4dcb"},{url:"assets/fouet-ahh-DdxrUXRj.mp3",revision:"c6e52ed22d70fa8ca9b4cc57490a463d"},{url:"assets/formatters-BTBiU0v3.js",revision:"c1a18e659b63e9164c05c3edcf877a83"},{url:"assets/format-CX6Cv1cD.css",revision:"b9d78ee715ac97d3260f2d90f4481817"},{url:"assets/flow9-C5_-GSwl.js",revision:"0e60dc6453d9684c059f20c846ae0ec4"},{url:"assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ-D-x-0Q06.woff2",revision:"a4160421d2605545f69a4cd6cd642902"},{url:"assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff",revision:"3e1afe59fa075c9e04c436606b77f640"},{url:"assets/expand-template-wRhAXT-1.js",revision:"5fc5c3b9a79c90c9835547cd5112f1e6"},{url:"assets/expand-template-CTUNyJrv.css",revision:"a4033bbc7a564e856b2b0c42816a24f7"},{url:"assets/es-CNp0s9na.js",revision:"168167fd7c156360d9e6d68fa61e2ac4"},{url:"assets/engineFeatures-C33LTVkK.js",revision:"c38cf3edd4cac5b86bc66944509fbdc0"},{url:"assets/elixir-6RTg0lbw.js",revision:"fb736f7429d9c6a596ed7905653dbf14"},{url:"assets/efforts-D_yTzymv.js",revision:"14a83b3c7423931fe8d08b3d637fe70d"},{url:"assets/editor.worker-CwQAd_xr.js",revision:"9e590290a972dd493b8050a29cedd37e"},{url:"assets/editor.api-DreEG0If.js",revision:"20e196609a038db8a491188ca17e3907"},{url:"assets/editor-BJU3Xb3h.css",revision:"86feeac14ca8286ed4671fb1321a79ca"},{url:"assets/ecl-D05T4iGw.js",revision:"496ceca3c8bae12c563a8a781cf639f3"},{url:"assets/documents-BIlWh3o-.js",revision:"9248b1a127f016aa51c7520ba6a7b9ff"},{url:"assets/dockerfile-DZFCIeNp.js",revision:"6af03903b1e51179ae2120866bb68acd"},{url:"assets/de-BU0dILBs.js",revision:"4985f379aab6751ea54d6bee2df83704"},{url:"assets/dart-onAF5SnQ.js",revision:"4fc14a4d2b7e030db6af8025d8fe831b"},{url:"assets/cypher-CVaqCwHa.js",revision:"75a568a8c6b29818b6a6c8675841ebf7"},{url:"assets/css-DIMkf-bt.js",revision:"368cd7c0ef4cdeca015fe9fe40ed1b2c"},{url:"assets/csp-bTuwJoIa.js",revision:"d13f525ef224dae69f8bde261bb48507"},{url:"assets/csharp-BKxtCVv1.js",revision:"e5831c8275e73409bc73a3991ceb194e"},{url:"assets/cpp-C7h46wYY.js",revision:"7fa3a56badaae54657cda12c403da2c7"},{url:"assets/coffee-Ba7i2nA0.js",revision:"1a1012b2a9bd329b3b1794297125c9a9"},{url:"assets/codicon-Brq4_Ui5.ttf",revision:"74c2693fe9bc669ca29eb633486e1813"},{url:"assets/clojure-Cm7r79vr.js",revision:"e3307e92ae8965ebb29ec9c9097774cd"},{url:"assets/clipboard-t9qe6lK7.js",revision:"04f746e11f1ac85a8652dff1abde80f4"},{url:"assets/cameligo-DMUM7wLl.js",revision:"ad01c48b3bff95a5fb691c7cd8427122"},{url:"assets/build-path-tree-BpSY7N5O.js",revision:"57b01efbb4a8486d3052a11323f5cbac"},{url:"assets/browser-Bkx4fbxl.js",revision:"d0a0a8ceb6fd5288f11e2ec2c30a8ae7"},{url:"assets/bicep-B5-_aFwp.js",revision:"b2c3f814c02ba6e4672b16282c0a1376"},{url:"assets/bat-i0X4ZdIN.js",revision:"914960f9abae1bfe5a2189a174a1e1c1"},{url:"assets/azcli-Bc_sGQ0U.js",revision:"c1dfc1889c57d0712d6415ecb14b66ed"},{url:"assets/apex-BWPQTe0t.js",revision:"eee56c5abf95c2575e288f36fdbb8737"},{url:"assets/abap-08VXUWAP.js",revision:"08897cd48182b5410786802ea9af6fa2"},{url:"assets/WorkspacePage-DCg9zSxz.css",revision:"8dfcb28752c95d1c4113ff305af2437d"},{url:"assets/WorkspacePage-Clc4Fl3B.js",revision:"bb03317230f2666de1aa1308b39fba5e"},{url:"assets/WorkspaceAttentionLabels-CrLP_I5S.css",revision:"99be445535bc9833b842f72d9e03ee5e"},{url:"assets/WorkspaceAttentionLabels-Bxe6oIJI.js",revision:"a624e64f70fcd39a40d8ff3d4edbc01e"},{url:"assets/TourReplayButton-ClVcB6mO.js",revision:"53b1b6c3b5983c74dc85b68afc932fe3"},{url:"assets/TouchPan-BnHXDR6F.js",revision:"1ba413f49fb29e36586117c7869a8857"},{url:"assets/TerminalPanel-DbVZk0vD.css",revision:"2ff0ce9e84f1f42b50827288880add0a"},{url:"assets/TerminalPanel-DHDnyiYh.js",revision:"3faacfc92d759d41ff4f70822f14a2d0"},{url:"assets/SplitWorkspacePage-lWQO8xro.css",revision:"cabea8d2cabbc3e1012ffa88225e04d3"},{url:"assets/SplitWorkspacePage-DL4kp9Ah.js",revision:"5f35bf4fb9e60f31eb6285d1f07c55d6"},{url:"assets/SettingsPage-W6N01tGz.css",revision:"a2deb1daabf3373d92dc252ef891102c"},{url:"assets/SettingsPage-DtGsd0XH.js",revision:"d5f143c0f28f4ad6be686637ba05c445"},{url:"assets/SearchPage-DOHkP5lj.js",revision:"a719653f5a047d44dba81ad79780d20f"},{url:"assets/SearchPage-BGc1oQSM.css",revision:"d988bd3c7ed5458189b7225097e4cdeb"},{url:"assets/SchedulePanel-Bos94OyR.js",revision:"2bfa4d768abbc3a4a1e8ad21181a9c12"},{url:"assets/SchedulePanel-BAA4Aajn.css",revision:"d35bda7ebb0fa9cb2bfea45d77156611"},{url:"assets/QTooltip-BQWY7aeM.js",revision:"b8dfb72c331c8ccf28a951a230432f4f"},{url:"assets/QSpinnerDots-DnCV3VzI.js",revision:"ba39c5e74830e254c54f4f5d2d46ff13"},{url:"assets/QSelect-BUlOQe5k.js",revision:"bcd170ea7d69bcca03b2def842162136"},{url:"assets/QPage-DaX9sMQC.js",revision:"0cd8a797c8ea611956a676655a407ab1"},{url:"assets/QMarkupTable-B9QuKtK_.js",revision:"160920fce69f9b52cee2a90cc4f8279d"},{url:"assets/QList-qupzuEqO.js",revision:"eae772de88e93c272b6c8d80d6067ee7"},{url:"assets/QItemSection-D_5_0UrX.js",revision:"e279fe3c67bf73bd85268799420d7616"},{url:"assets/QDrawer-DNEj8wLZ.js",revision:"9215af009cab2c3c5c94c31e4472d4f2"},{url:"assets/QChip-owciRuZu.js",revision:"35fc915f5a427228ea6550737619734e"},{url:"assets/QBtnToggle-BI3k3Ch2.js",revision:"e624fc03b2eb479a25ec72d9f94eb180"},{url:"assets/QBtnGroup-DELKYo3u.js",revision:"26b8a09eebac7031c601caf508e51076"},{url:"assets/QBtnDropdown-163oM6T_.js",revision:"4e9697c46c5ceef72bc833b923719c1c"},{url:"assets/QBtn-CZaBclNw.js",revision:"c13288d664c03c0519fb5f5744f5e179"},{url:"assets/QBanner-DhqH95GW.js",revision:"90a5f93c977406c288a5d8581e96c9c8"},{url:"assets/QBadge-DbkxGtht.js",revision:"a1d932f64e2db71082894e3fb5a4846b"},{url:"assets/MainLayout-CwWavQjV.js",revision:"0a19f3476b356fac467d42a9790fda1d"},{url:"assets/MainLayout-BwV89R-l.css",revision:"361f23b2fdc3e3b7dd2f468de1642650"},{url:"assets/HealthPage-XrOuMoDJ.js",revision:"65ceb2fb8bc6411a6f7e7f9000e3274e"},{url:"assets/HealthPage-CFZ-tdKK.css",revision:"0e6bfb66fa0c3d07a1afa39370e89ec8"},{url:"assets/GitPanel-C9mz4GXF.js",revision:"0e77756fe440d6ed78afeec013f5a5a9"},{url:"assets/GitPanel-BFCnyhE2.css",revision:"bb8c4ad153abd46e8f9ce31d85dc6edf"},{url:"assets/DrawerToggleButton-DRL3RCkM.js",revision:"64b32fcaaac5fe20968ed4488dadc2a0"},{url:"assets/DocumentsPanel-DCXpLLb7.js",revision:"6c72ead8781fc72a990e7ad2181f1cd1"},{url:"assets/DocumentsPanel-B8QY7FTj.css",revision:"676a3a838b07224f48fdd99e0cb6bbc8"},{url:"assets/DiffViewer-DEPOa3D7.css",revision:"7a2be47c13fe02cd2158e94eb0d320c5"},{url:"assets/DiffViewer-COwGxPt6.js",revision:"f7a8751a0c644427c7475648c545e0ad"},{url:"assets/DashboardPage-D8g7_r4S.css",revision:"eebdeb183365fe34ed04a5870b839fa4"},{url:"assets/DashboardPage-Cv6HJEcO.js",revision:"6d860cb46f55dfdd170584be9b4e8bcd"},{url:"assets/CreatePage-TY9g3hZb.css",revision:"56774ba6e4e8410866732639e4c4e146"},{url:"assets/CreatePage-Bx_GpUni.js",revision:"4232570e83fa79b83bdb6952db0312a9"},{url:"assets/ComparisonPanel-CRRaDs2D.css",revision:"5cf89d70490a6b89a13a2c81360ed983"},{url:"assets/ComparisonPanel-B4ne55Xj.js",revision:"44e53301f0ea722a79496629eb7e9176"},{url:"assets/ClosePopup-BqW5dy-O.js",revision:"c06137af89cb48374856dc5b805c6d36"},{url:"assets/ChangelogPage-DX1WGFea.js",revision:"26fa19f709906a9444435a68b0b4f534"},{url:"assets/ChangelogPage-DKJkFiU_.css",revision:"6ba32a05b43494414258cbdd88c16e36"},{url:"assets/ActivityFeed-D1e-zV3O.js",revision:"cc6b76d1059bc58b75ae46f00306c9f2"},{url:"assets/ActivityFeed-BYR5x7aa.css",revision:"8fa009894fba587d5602d5a5659f9f0d"}],{}),s.cleanupOutdatedCaches(),s.registerRoute(new s.NavigationRoute(s.createHandlerBoundToURL("index.html"),{denylist:[/sw\.js$/,/workbox-(.)*\.js$/]}))});
1
+ if(!self.define){let s,e={};const a=(a,r)=>(a=new URL(a+".js",r).href,e[a]||new Promise(e=>{if("document"in self){const s=document.createElement("script");s.src=a,s.onload=e,document.head.appendChild(s)}else s=a,importScripts(a),e()}).then(()=>{let s=e[a];if(!s)throw new Error(`Module ${a} didn’t register its module`);return s}));self.define=(r,i)=>{const d=s||("document"in self?document.currentScript.src:"")||location.href;if(e[d])return;let c={};const f=s=>a(s,d),b={module:{uri:d},exports:c,require:f};e[d]=Promise.all(r.map(s=>b[s]||f(s))).then(s=>(i(...s),c))}}define(["./workbox-778a14ff"],function(s){"use strict";s.setCacheNameDetails({prefix:"kobo-client"}),self.addEventListener("message",s=>{s.data&&"SKIP_WAITING"===s.data.type&&self.skipWaiting()}),s.clientsClaim(),s.precacheAndRoute([{url:"manifest.json",revision:"73f02ba4eb4414fb70bbe5ca76cc9580"},{url:"index.html",revision:"1128bc0d2baefd44cdfa4a07ce3c2836"},{url:"favicon.svg",revision:"9d89ef10d49f14d08c25cfca9bd4ea75"},{url:"sounds/yaaa.mp3",revision:"2161c5eb77ac61349f6fe573f62d8404"},{url:"sounds/warcraft-3-humain-travail.mp3",revision:"0b8bd1b9be23803c3ac84eaf0d1b5287"},{url:"sounds/tu-vas-la-fermer.mp3",revision:"1688aaa18b0a307a3016c3fd39321f59"},{url:"sounds/travail_termine.mp3",revision:"a194c4cc479b59ba13746b08bca634b9"},{url:"sounds/ta-gueule.mp3",revision:"44aa9b15c9abe9a846f8034a23482b24"},{url:"sounds/pas-ca-zinedine.mp3",revision:"57ec46faf5b7d1c2f370d7167e284f04"},{url:"sounds/ouais-cest-greg.mp3",revision:"55624f422636b19422b3bc700aa8da9e"},{url:"sounds/nan-wallah-pardon.mp3",revision:"16edfe0a39fde73db0f30a7a067a77ff"},{url:"sounds/nan-tu-degages.mp3",revision:"282678eceb54e09eb8a7edf4f9fb0e21"},{url:"sounds/mais-laisse-moi-dormir-zebi.mp3",revision:"05d8419f91effcf56a6d09ed35544d06"},{url:"sounds/hey.mp3",revision:"e68017c8f32b3e815e339dad099dc830"},{url:"sounds/gta-v-death.mp3",revision:"72eaa8958882d5f2040f4b9b4f3ba620"},{url:"sounds/for-shure.mp3",revision:"71dd2a2c874a04e67613d49045d926e7"},{url:"sounds/faaah.mp3",revision:"a0220dd11038add054573c26d2f0b6ac"},{url:"sounds/dry-fart.mp3",revision:"afdf096e4a705d908392ed9b4f827bc9"},{url:"sounds/ca_va_peter.mp3",revision:"004452d7682a043e1c13e213a1a56766"},{url:"sounds/basic-notification.mp3",revision:"3f6df726a5e85560dfecf4bb592d2fda"},{url:"sounds/bah-alors-on-est-nul.mp3",revision:"b30241371b49465f62997213bcdfe4b2"},{url:"sounds/arretez-les-messages.mp3",revision:"26f667dccdfddb8c534a5482475b729a"},{url:"sounds/arrete-de-mentir.mp3",revision:"1a9b5157f362dd3e0acc479da4fea708"},{url:"sounds/aller-ftg.mp3",revision:"bcc00bd838e61eb9571c8fdc0f400d19"},{url:"sounds/7eme-compagnie-03.mp3",revision:"49ee08dd595e0e9659042e4e854b0141"},{url:"fonts/GeistMono-Variable.woff2",revision:"308360d8a547331fd40bc09a7145d59a"},{url:"fonts/Geist-Variable.woff2",revision:"dfa48d5a853753289194436953e3f202"},{url:"fonts/GEIST-LICENSE.txt",revision:"563d13575f813953c3151e1ecce3b76f"},{url:"assets/yaml-DaXaqaGD.js",revision:"e515a02a9f0361bf6655612f98174a63"},{url:"assets/xml-gFFsobxE.js",revision:"79d57d25e272e52dc4ae8c870362bc6f"},{url:"assets/workspace-templates-BCKR8TXr.js",revision:"558ef980a7dddfda594cf9d993ec2923"},{url:"assets/workspace-page-layout-Dw9NhZsL.js",revision:"0c933f7b6c6bf3c90ea1875abad85392"},{url:"assets/wgsl-DpFanUEy.js",revision:"4cf32279d7c6a601611a6e32a14f3b1e"},{url:"assets/vb-DV3o63ZY.js",revision:"a5b3a756d667f5e4a5da6da4013d7341"},{url:"assets/use-tours-CVn874kD.js",revision:"a9183667b28b079415d89c5644cd5717"},{url:"assets/use-tours-CTZuBZOi.css",revision:"2f6d79046e1409f0472f65179eaa76f3"},{url:"assets/use-slide-transition-CiaDm-tR.js",revision:"61e1925f1339dd885d2c028c3637eff4"},{url:"assets/use-search-index-status-Bluf9L99.js",revision:"a4f06ea760cd94dc03166100898824cb"},{url:"assets/use-is-mobile-DpKI3XMy.js",revision:"416727a203a84e393ad3c10188249ee5"},{url:"assets/use-id-wXd4c8FA.js",revision:"48ab7450bfc0bb2f9465c9aba7e2b2cc"},{url:"assets/use-checkbox-CnvHBhSK.js",revision:"2535412c5757330cc518661ed80dc207"},{url:"assets/typespec-B8J7ngcE.js",revision:"6c28560625f59db6a5897aa92de81033"},{url:"assets/typescript-BU_TUuAM.js",revision:"11d7b72331d369763a3f191e40c1b5d5"},{url:"assets/twig-De2hgUGE.js",revision:"dfb4c76c8ec0d822070abac68d2bd473"},{url:"assets/tcl-DISqw1ZD.js",revision:"6d0ddaebd76ad41c47c96d484af119f8"},{url:"assets/systemverilog-Bz4Y3fRF.js",revision:"18e6d6e82eeb1107458d8d5531f82246"},{url:"assets/swift-Bxkupp3x.js",revision:"65b88f49188974d7c12e1a6cd12a9de5"},{url:"assets/st-DbInun42.js",revision:"d7294c4d47351db4e5edd4d91e445a21"},{url:"assets/sql-NEE52Syq.js",revision:"48352e15fff2141c7deaaab4e51e9565"},{url:"assets/sparql-D_Lu-MrJ.js",revision:"65390637b1a24614803db6844a0db77b"},{url:"assets/sophia-CRfGWb83.js",revision:"a330db913fee26a14679bed631a59043"},{url:"assets/solidity-BEEn4gHE.js",revision:"c2cd02221ec3d86f9a6bb09bfb1f8978"},{url:"assets/shell-CC2rA5mh.js",revision:"8362d325cda511ef760335e0847d3910"},{url:"assets/scss-gp-XZpBa.js",revision:"bf0805dd5cd80d90fef58c9866a7751e"},{url:"assets/scheme-BeGwcela.js",revision:"55c990715708ea012165486d065b3e2c"},{url:"assets/scala-DHpiXF5c.js",revision:"4eeea167d27954255e39d91412b62f87"},{url:"assets/sb-CcwsVR0C.js",revision:"93fc05f23a9cbb96d4f72dbc73e2e53b"},{url:"assets/rust-DdL9SqIa.js",revision:"356bac76300c8d83e8e9d76becf3c9ea"},{url:"assets/runtime-core.esm-bundler-CNFKm4ij.js",revision:"ad1f7761331de112f31a4ab7240994ca"},{url:"assets/ruby-DezsRK8O.js",revision:"95c3294c6d6cead3cccd7e4e973ab964"},{url:"assets/restructuredtext-BYgofb2h.js",revision:"f75377ae694f4e8f0bcccd05b5b9e65c"},{url:"assets/render-chat-markdown-AaOo0Tgq.js",revision:"dc3708d6bd578b085a58276fa13271e0"},{url:"assets/redshift-DT7zqm-g.js",revision:"44e23f67b6a02e60d28c9947cd025207"},{url:"assets/redis-ClamHrr6.js",revision:"e3141183a6756253db43e10f8a305787"},{url:"assets/reactivity.esm-bundler-Bo9anJjg.js",revision:"0b323e9851ecfc7c2e862da9dc0e4710"},{url:"assets/razor-Jl1VqMsk.js",revision:"895d4ce46af19e6fdb6df2ed15fb2911"},{url:"assets/r-BwWrilGY.js",revision:"f18d3e790ef07bc993539322d29548e4"},{url:"assets/qsharp-DkqhCAOL.js",revision:"c53fe08a83f8fcbcd81723105136a691"},{url:"assets/python-COs6pHk2.js",revision:"90e0a1249bd457aee2d77a0d89bc8c7b"},{url:"assets/pug-Z5eAx3Zn.js",revision:"6e3de6d5214d2cf61b90949e1d383b49"},{url:"assets/protobuf-C531GsRP.js",revision:"04e688a7fef2bde8cef525653497371f"},{url:"assets/project-color-R_1je4vW.js",revision:"8a0e3ec95c9423d7f31700ada6eef157"},{url:"assets/private.use-form-Bk8ti264.js",revision:"7442e263bb4518c066fbf2637cf18969"},{url:"assets/powershell-DmHpPYUd.js",revision:"ff476e9c4398edc9dfd2eb0ee9356352"},{url:"assets/powerquery-D3hlyOfw.js",revision:"0cacccadbe7cd4415f9a3112763c89f3"},{url:"assets/postiats-43DmfD33.js",revision:"b5dbce3331b7ccb325853328702b4bd9"},{url:"assets/pla-CopQ2nXW.js",revision:"b31678678d642accba98d7e7249a20b2"},{url:"assets/pinia-CTJ3OfP3.js",revision:"ae0f74c0db685ce05434746ad5f830e8"},{url:"assets/php-nr791fC2.js",revision:"ee487693840b66c2abf7c2da872dd6a8"},{url:"assets/pgsql-DTj74zXo.js",revision:"75375029d157fc5e789a13718eed9da7"},{url:"assets/permissionModes-B7fuUegU.js",revision:"5226255dd4a76354cb128fad1f3d189c"},{url:"assets/perl-oz_6vUea.js",revision:"fee6d319d328db438b336b52ac07a46a"},{url:"assets/pending-diff-open-dYIFdS4r.js",revision:"9bfd0fbb7adbdb17bd30d088aeaa1242"},{url:"assets/pascaligo-D-ptJ9y-.js",revision:"88be4e81a252f44f049ac92f7b6ea518"},{url:"assets/pascal-DrH0SRf2.js",revision:"0d81121099a69b47e10701bf075fe3cd"},{url:"assets/objective-c-FvmIjYaQ.js",revision:"6d64543dd4430fb71bcd7a5347a0398c"},{url:"assets/notify-theme-D4p3qPkp.js",revision:"4feb891e6efd7b25d64f8bc5884bbfc5"},{url:"assets/network-auth-BJiPbO5l.js",revision:"17c05820566ddf5f6ca40f932693250b"},{url:"assets/mysql-SOo6toE5.js",revision:"677c089d979324385539e96bd2eb11e4"},{url:"assets/msdax-DauUninz.js",revision:"a63bfea2dd041755a34fe3e307159413"},{url:"assets/monaco.contribution-DnhZHwXT.js",revision:"940820a814b42cec904ab400b3fd4892"},{url:"assets/monaco-contributions-DLscZGH-.js",revision:"a8c7c38d89d8a43e6c15449ad03fafdb"},{url:"assets/monaco-contributions-Cb0afGfW.css",revision:"9c8dff3575c2e943e7ad49f78bbdb6d2"},{url:"assets/mips-CIPQ_RoX.js",revision:"b22614ddc8855670a3f76290908877f5"},{url:"assets/mdx-BG3zYwNF.js",revision:"4812f1e1bac932e77c7d9f9bb0348cd3"},{url:"assets/markdown-Cimd5fb3.js",revision:"38eaa88ca7719b9da2894b7c26f2f65b"},{url:"assets/m3-D-oSqn_W.js",revision:"624c73b0332fe1ddfef6013306c5998d"},{url:"assets/lua-CsQS60Ue.js",revision:"5568edf60b64f912bd17561f26e03d44"},{url:"assets/liquid-CM3JKyhv.js",revision:"2f14efa00eb8c4cc46a1d18d4ac96210"},{url:"assets/lexon-CfSJPG6W.js",revision:"32b224ffe991474a4cfcbed19971a98d"},{url:"assets/less-B9JPFI3C.js",revision:"c80573ae2313727c545a585d90d3ff36"},{url:"assets/kotlin-BOotOW0E.js",revision:"7c2a31b16b6ddc97b60891b09afa11b1"},{url:"assets/julia-Bri6UV-V.js",revision:"bb5062cdf870c17c7c9be635c1a8a3be"},{url:"assets/javascript-DuNbcaL7.js",revision:"33a6a093941855436dcb40bd0185413b"},{url:"assets/java-BEtHBSE6.js",revision:"987edcd2170749acca47ea184dd9ab25"},{url:"assets/it-CeK5lyIA.js",revision:"ad1cf8920afb96bc45634e48ac9ccf68"},{url:"assets/ini-sBoK_t0W.js",revision:"35f8ec10844ea4f62c2712d3f5c1e129"},{url:"assets/index-BLd8DAzg.js",revision:"138fd031d69fa1fc0b3f4641a4f48497"},{url:"assets/index-0wtBh1Xt.css",revision:"37027b41660d76816385314e0dac9d60"},{url:"assets/i18n-aDWy4KHt.js",revision:"8ed5ca353e8d8157d5ad376e3b03e15e"},{url:"assets/html-DFfsfStD.js",revision:"2e7197bee7e61bfd7b7eb500d9ca4121"},{url:"assets/hcl-CpzslTdj.js",revision:"f9ef1004e908957ec1c3bbea2049a0e9"},{url:"assets/handlebars-DK_Bj6Rx.js",revision:"668235f26836c69a5ec98fc7378b308c"},{url:"assets/graphql-fmXr3nnJ.js",revision:"a51df1d5dca011f5d85dd09a2ffbe1e5"},{url:"assets/go-C-y9NEjX.js",revision:"9213c8381eb32996b86ca9600ca6a07e"},{url:"assets/fsharp-C8Ef5oNN.js",revision:"72f3de59be781f8a4ec49d16bac02119"},{url:"assets/freemarker2-DxezMaje.js",revision:"0a20db979fc1424f1cb1654d719b1fa8"},{url:"assets/fr-D-sd0ddn.js",revision:"ce0f713a8bd83c6773768b474e50500f"},{url:"assets/fouet-ahh-DdxrUXRj.mp3",revision:"c6e52ed22d70fa8ca9b4cc57490a463d"},{url:"assets/formatters-Bl9zA7Ai.js",revision:"3f0c03557c1d4f7485f5aa55f1c4ef3a"},{url:"assets/format-CX6Cv1cD.css",revision:"b9d78ee715ac97d3260f2d90f4481817"},{url:"assets/flow9-C5_-GSwl.js",revision:"0e60dc6453d9684c059f20c846ae0ec4"},{url:"assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ-D-x-0Q06.woff2",revision:"a4160421d2605545f69a4cd6cd642902"},{url:"assets/expand-template-CTUNyJrv.css",revision:"a4033bbc7a564e856b2b0c42816a24f7"},{url:"assets/expand-template-C8VyjASo.js",revision:"27b4856c91c68b904354a325b7f521ef"},{url:"assets/es-By2Q9Tca.js",revision:"af00c756abd7a7a5139f36d714a35aec"},{url:"assets/engineFeatures-DQO9HHXI.js",revision:"b25951382d2d48f9fe638ccef093f42c"},{url:"assets/engineFeatures-B-9jHocY.css",revision:"54449cd3d2d5c88b0bd7d88f53f581c3"},{url:"assets/elixir-6RTg0lbw.js",revision:"fb736f7429d9c6a596ed7905653dbf14"},{url:"assets/efforts-Bw0o2Bud.js",revision:"dd1ac129212cd8f6de30f709f3a496e6"},{url:"assets/editor.worker-iO5iN0DB.js",revision:"240735dda51130c7b909d0d76b52c30b"},{url:"assets/editor.api-CK7--ckY.js",revision:"1182fac1a196571b531f1b1b2f5fb433"},{url:"assets/editor-BJU3Xb3h.css",revision:"86feeac14ca8286ed4671fb1321a79ca"},{url:"assets/ecl-D05T4iGw.js",revision:"496ceca3c8bae12c563a8a781cf639f3"},{url:"assets/documents-BZ8bwcjr.js",revision:"cbe4095ef0e043600531f02bf2fb0cbb"},{url:"assets/dockerfile-DZFCIeNp.js",revision:"6af03903b1e51179ae2120866bb68acd"},{url:"assets/de-COObokpu.js",revision:"39649a7664fd9a67772c454f78864499"},{url:"assets/dart-onAF5SnQ.js",revision:"4fc14a4d2b7e030db6af8025d8fe831b"},{url:"assets/cypher-CVaqCwHa.js",revision:"75a568a8c6b29818b6a6c8675841ebf7"},{url:"assets/css-DIMkf-bt.js",revision:"368cd7c0ef4cdeca015fe9fe40ed1b2c"},{url:"assets/csp-bTuwJoIa.js",revision:"d13f525ef224dae69f8bde261bb48507"},{url:"assets/csharp-BKxtCVv1.js",revision:"e5831c8275e73409bc73a3991ceb194e"},{url:"assets/cpp-C7h46wYY.js",revision:"7fa3a56badaae54657cda12c403da2c7"},{url:"assets/coffee-Ba7i2nA0.js",revision:"1a1012b2a9bd329b3b1794297125c9a9"},{url:"assets/codicon-Brq4_Ui5.ttf",revision:"74c2693fe9bc669ca29eb633486e1813"},{url:"assets/clojure-Cm7r79vr.js",revision:"e3307e92ae8965ebb29ec9c9097774cd"},{url:"assets/clipboard-t9qe6lK7.js",revision:"04f746e11f1ac85a8652dff1abde80f4"},{url:"assets/cameligo-DMUM7wLl.js",revision:"ad01c48b3bff95a5fb691c7cd8427122"},{url:"assets/build-path-tree-6EjBmYYY.js",revision:"19434e38c9bc0e0f7177e7af8879a2e2"},{url:"assets/browser-BmWgBx9M.js",revision:"77d20e1a88db05cab9f5bdf2473536c4"},{url:"assets/bicep-B5-_aFwp.js",revision:"b2c3f814c02ba6e4672b16282c0a1376"},{url:"assets/bat-i0X4ZdIN.js",revision:"914960f9abae1bfe5a2189a174a1e1c1"},{url:"assets/azcli-Bc_sGQ0U.js",revision:"c1dfc1889c57d0712d6415ecb14b66ed"},{url:"assets/apex-BWPQTe0t.js",revision:"eee56c5abf95c2575e288f36fdbb8737"},{url:"assets/abap-08VXUWAP.js",revision:"08897cd48182b5410786802ea9af6fa2"},{url:"assets/WorkspacePage-Cl8gap4b.js",revision:"a79950756cf30f8a918ac45fd209d88e"},{url:"assets/WorkspacePage-BbUvR1Vf.css",revision:"1754bb1bfaf7f76b0ec6bfc505e57618"},{url:"assets/WorkspaceAttentionLabels-CrLP_I5S.css",revision:"99be445535bc9833b842f72d9e03ee5e"},{url:"assets/WorkspaceAttentionLabels-BCVOP8vp.js",revision:"cdb03cec7f5f09e1668f3506d032dfbf"},{url:"assets/TourReplayButton-Dz1yEz_z.js",revision:"cc692b1b6b8c0dd5959837a014aa9fce"},{url:"assets/TouchPan-BQ1cvzRC.js",revision:"a72f99154dcd24f4b169617a5007c676"},{url:"assets/TerminalPanel-DbVZk0vD.css",revision:"2ff0ce9e84f1f42b50827288880add0a"},{url:"assets/TerminalPanel-Cq-FR7A7.js",revision:"c921063f9c67d3ecb5a6e0fade74792a"},{url:"assets/SplitWorkspacePage-lWQO8xro.css",revision:"cabea8d2cabbc3e1012ffa88225e04d3"},{url:"assets/SplitWorkspacePage-Bg6nKBcA.js",revision:"69427706af9fee8407a63c32a1b9c747"},{url:"assets/SettingsPage-W6N01tGz.css",revision:"a2deb1daabf3373d92dc252ef891102c"},{url:"assets/SettingsPage-BUh0WfNf.js",revision:"d002a97b184e4aeac42bb6d986b34e2f"},{url:"assets/SearchPage-BwZ2TX1G.js",revision:"b5f36194db624d20e40da491d48e6b7d"},{url:"assets/SearchPage-BGc1oQSM.css",revision:"d988bd3c7ed5458189b7225097e4cdeb"},{url:"assets/SchedulePanel-DiWCDNZ8.js",revision:"7f930ba385363997b66b429e231cf7a3"},{url:"assets/SchedulePanel-BAA4Aajn.css",revision:"d35bda7ebb0fa9cb2bfea45d77156611"},{url:"assets/QTooltip-BDihn2aY.js",revision:"644f8feb97a5486e64d55efb4c527168"},{url:"assets/QSpinnerDots-BkFiCsH3.js",revision:"bc6a08841e63f44bf348d5f56d6e8780"},{url:"assets/QSelect-BbtD5Iks.js",revision:"f78033915e41d0a40d0efd930d23f7fa"},{url:"assets/QPage-BXBw2Alx.js",revision:"b39af3063ac7b0c0a192fc74550c1179"},{url:"assets/QMarkupTable-CNpiA9oq.js",revision:"a21ec35b83ac3e2e6a3fd0dba47714b0"},{url:"assets/QList-CHm4JNP0.js",revision:"8f1b0c0cd330ddf100c4e66990dd25d3"},{url:"assets/QItemSection-BhqphaH6.js",revision:"7fac7f4622b613551de13aa64e710468"},{url:"assets/QExpansionItem-Bok1m8Wi.js",revision:"7b0249c53bd14372bafd4b74e9127d7a"},{url:"assets/QDrawer-B4qHw8wt.js",revision:"bf5fda6b7e436c2ca7bef7683caf4d03"},{url:"assets/QChip-DCPUhqXX.js",revision:"e6c7c2a8b659617868c6311812d575cf"},{url:"assets/QBtnToggle-C_hQ2UCQ.js",revision:"adb36508db34f1cce6726d8b54095f83"},{url:"assets/QBtnGroup-CAoD6G0Q.js",revision:"4d0da11fe567ac02c981ef289e0ae287"},{url:"assets/QBtnDropdown-44Mj-y_1.js",revision:"a260476ce15dbd7934795293f9744308"},{url:"assets/QBtn-DEdx_Y1V.js",revision:"2499c9babb490d28b308abea85270b79"},{url:"assets/QBanner-CcRI_QIy.js",revision:"291bb0942a58ba2749d6e1a82cc80ba6"},{url:"assets/QBadge-FWC1zDCq.js",revision:"eada076dd3e0fd430d1d849fa67f2b32"},{url:"assets/MainLayout-Cf4Q9x1u.js",revision:"da80c2f47fdd4bb7dffba0cc39f1955a"},{url:"assets/MainLayout-BAAQLq95.css",revision:"9792f0dc31723cdb72a5146477b837c6"},{url:"assets/HealthPage-l88TEk-k.js",revision:"fde906c708f8567034d0dd2a6957f7bf"},{url:"assets/HealthPage-CFZ-tdKK.css",revision:"0e6bfb66fa0c3d07a1afa39370e89ec8"},{url:"assets/GitPanel-BFCnyhE2.css",revision:"bb8c4ad153abd46e8f9ce31d85dc6edf"},{url:"assets/GitPanel-B-ZHgghQ.js",revision:"eee7dfb37aa3a75e942cfec3b5fc079d"},{url:"assets/DrawerToggleButton-BJBBYeOc.js",revision:"17b93911b861eaf8f05e10e5cef86737"},{url:"assets/DocumentsPanel-BeCttB-x.js",revision:"9789c958dbd4a71df0728375b8f73e72"},{url:"assets/DocumentsPanel-B8QY7FTj.css",revision:"676a3a838b07224f48fdd99e0cb6bbc8"},{url:"assets/DiffViewer-DEPOa3D7.css",revision:"7a2be47c13fe02cd2158e94eb0d320c5"},{url:"assets/DiffViewer-Csf3WmLc.js",revision:"539fe09d01e340484f332ae89119dca8"},{url:"assets/DashboardPage-D8g7_r4S.css",revision:"eebdeb183365fe34ed04a5870b839fa4"},{url:"assets/DashboardPage-CZQLfoV1.js",revision:"7d88376af8e64e3bbfc1b1f3daedd2dd"},{url:"assets/CreatePage-TY9g3hZb.css",revision:"56774ba6e4e8410866732639e4c4e146"},{url:"assets/CreatePage-SoCcvxuD.js",revision:"23bc1748c91a70ab22cdfd3ce3733d45"},{url:"assets/ComparisonPanel-CRRaDs2D.css",revision:"5cf89d70490a6b89a13a2c81360ed983"},{url:"assets/ComparisonPanel-CKylN45q.js",revision:"d6e15bbbb135e20bd266c7982d7a41e0"},{url:"assets/ClosePopup-CWjIRHxu.js",revision:"1a94c8536ec772fc2a3f327ed6164dd2"},{url:"assets/ChangelogPage-DKJkFiU_.css",revision:"6ba32a05b43494414258cbdd88c16e36"},{url:"assets/ChangelogPage-CnXTnFhe.js",revision:"783bcb77bfafcba05bf112e0dfbc3e4c"},{url:"assets/ActivityFeed-CLXjdqS8.js",revision:"1ef2c4417aae3490abb9737f96104510"},{url:"assets/ActivityFeed-BYR5x7aa.css",revision:"8fa009894fba587d5602d5a5659f9f0d"}],{}),s.cleanupOutdatedCaches(),s.registerRoute(new s.NavigationRoute(s.createHandlerBoundToURL("index.html"),{denylist:[/sw\.js$/,/workbox-(.)*\.js$/]}))});
@@ -167,13 +167,20 @@ conversation tools are described separately. The registration schemas in
167
167
  | Tool | Input | Purpose |
168
168
  |---|---|---|
169
169
  | `get_ticket` | None | Read the workspace's Notion or Sentry source context. |
170
- | `list_documents` | None | List Markdown under `docs/plans/`, `docs/superpowers/`, and `.ai/thoughts/`. |
170
+ | `list_documents` | None | List Markdown under `docs/plans/`, `docs/superpowers/`, `.ai/thoughts/`, and `.ai/handoffs/`. |
171
171
  | `read_document` | `path` | Read a worktree-relative document within those roots. |
172
172
  | `log_thought` | `title`, `content`, optional `tag` | Write a uniquely named decision note under `.ai/thoughts/logs/`. |
173
+ | `submit_session_handoff` | `report` | Submit up to 24,000 characters of Markdown during a backend-requested handoff generation turn. The invocation supplies the operation identity; the agent cannot select another transfer. |
173
174
  | `search_codebase` | `query`, optional `include_archived`, `scope`, `limit` | Search conversations, not repository source. Scope defaults to `workspace`; `all` searches across workspaces. Limit defaults to 30, maximum 100. |
174
175
  | `get_session_usage` | None | Read workspace and active-session usage totals. |
175
176
  | `read_workspace_events_csv` | Optional `session_id`, `offset`, `limit` | Read this workspace's conversation as paginated CSV; limit defaults to 100, maximum 500. |
176
177
 
178
+ `submit_session_handoff` is advertised only to the MCP invocation preparing a
179
+ session transfer. That invocation exposes read tools and report submission only.
180
+ After submitting, the agent ends its turn; the backend waits for confirmed engine
181
+ closure before launching the fresh conversation. Ordinary workspace and global
182
+ MCP clients cannot submit handoff reports or control this transition.
183
+
177
184
  ### Tasks
178
185
 
179
186
  #### `list_tasks`
@@ -1,13 +1,24 @@
1
+ import { DOCUMENT_DIRS } from '../shared/document-roots.js'
2
+
3
+ export { DOCUMENT_DIRS } from '../shared/document-roots.js'
4
+
1
5
  import fs from 'node:fs'
2
6
  import path from 'node:path'
3
7
  import type Database from 'better-sqlite3'
4
8
  import { nanoid } from 'nanoid'
5
9
  import * as cronService from '../server/services/cron-service.js'
6
10
  import * as settingsService from '../server/services/settings-service.js'
11
+ import {
12
+ createTaskRecord,
13
+ deleteTaskRecord,
14
+ type TaskRecord,
15
+ updateTaskRecord,
16
+ } from '../server/services/task-mutations.js'
7
17
  import { slugifyProjectName } from '../server/utils/project-slug.js'
8
18
  import { ensureDirectoryInside, resolveExistingPathInside } from '../server/utils/safe-path.js'
9
19
  import { resolveWorkspaceWorktreePath } from '../server/utils/worktree-paths.js'
10
20
  import { MASKED_SECRET, SECRET_GLOBAL_KEYS } from '../shared/consts.js'
21
+ import { parseTaskVerification, type TaskRole, type TaskVerification } from '../shared/task-verification.js'
11
22
 
12
23
  /** Allowed task status values. */
13
24
  export const VALID_TASK_STATUSES = ['pending', 'in_progress', 'done'] as const
@@ -21,6 +32,9 @@ export interface TaskDto {
21
32
  title: string
22
33
  status: string
23
34
  is_acceptance_criterion: boolean
35
+ sort_order: number
36
+ role: TaskRole
37
+ verification: TaskVerification | null
24
38
  }
25
39
 
26
40
  /** Result returned when a task is marked as done. */
@@ -35,12 +49,7 @@ export interface DevServerStatusDto {
35
49
  status: string
36
50
  }
37
51
 
38
- interface TaskRow {
39
- id: string
40
- title: string
41
- status: string
42
- is_acceptance_criterion: number
43
- }
52
+ type TaskRow = TaskRecord
44
53
 
45
54
  function rowToDto(row: TaskRow): TaskDto {
46
55
  return {
@@ -48,15 +57,16 @@ function rowToDto(row: TaskRow): TaskDto {
48
57
  title: row.title,
49
58
  status: row.status,
50
59
  is_acceptance_criterion: row.is_acceptance_criterion === 1,
60
+ sort_order: row.sort_order,
61
+ role: row.role,
62
+ verification: parseTaskVerification(row.verification),
51
63
  }
52
64
  }
53
65
 
54
66
  /** Return all tasks for a workspace, ordered by sort_order. */
55
67
  export function listTasksHandler(db: Database.Database, workspaceId: string): TaskDto[] {
56
68
  const rows = db
57
- .prepare(
58
- 'SELECT id, title, status, is_acceptance_criterion FROM tasks WHERE workspace_id = ? ORDER BY sort_order ASC',
59
- )
69
+ .prepare('SELECT * FROM tasks WHERE workspace_id = ? ORDER BY sort_order ASC, rowid ASC')
60
70
  .all(workspaceId) as TaskRow[]
61
71
  return rows.map(rowToDto)
62
72
  }
@@ -143,118 +153,76 @@ export function setWorkspaceAgentDescriptionHandler(
143
153
  return { ok: true, description: stored }
144
154
  }
145
155
 
146
- /** Set a task's status to "done" and return the updated task. */
147
- export function markTaskDoneHandler(db: Database.Database, workspaceId: string, taskId: string): MarkDoneResult {
148
- const now = new Date().toISOString()
149
- const result = db
150
- .prepare('UPDATE tasks SET status = ?, updated_at = ? WHERE id = ? AND workspace_id = ?')
151
- .run('done', now, taskId, workspaceId)
152
-
153
- if (result.changes === 0) {
154
- throw new Error(`Task '${taskId}' not found in workspace '${workspaceId}'`)
155
- }
156
-
157
- const row = db
158
- .prepare('SELECT id, title, status, is_acceptance_criterion FROM tasks WHERE id = ?')
159
- .get(taskId) as TaskRow
156
+ /** Set a task's status to done; auto-loop tasks require successful evidence. */
157
+ export function markTaskDoneHandler(
158
+ db: Database.Database,
159
+ workspaceId: string,
160
+ taskId: string,
161
+ verification?: unknown,
162
+ ): MarkDoneResult {
163
+ const row = updateTaskRecord(db, workspaceId, taskId, {
164
+ status: 'done',
165
+ ...(verification !== undefined ? { verification } : {}),
166
+ })
160
167
  return { success: true, task: rowToDto(row) }
161
168
  }
162
169
 
163
- /** Create a new task appended at the end of the workspace's task list. */
170
+ /** Create a task at an explicit position or append it to the list. */
164
171
  export function createTaskHandler(
165
172
  db: Database.Database,
166
173
  workspaceId: string,
167
- data: { title: string; is_acceptance_criterion?: boolean },
174
+ data: {
175
+ title: string
176
+ is_acceptance_criterion?: boolean
177
+ sort_order?: number
178
+ after_task_id?: string
179
+ role?: TaskRole
180
+ },
168
181
  ): TaskDto {
169
- if (!data.title?.trim()) {
170
- throw new Error('title is required')
171
- }
172
-
173
- // Verify workspace exists
174
- const ws = db.prepare('SELECT id FROM workspaces WHERE id = ?').get(workspaceId) as { id: string } | undefined
175
- if (!ws) {
176
- throw new Error(`Workspace '${workspaceId}' not found`)
177
- }
178
-
179
- const id = nanoid()
180
- const now = new Date().toISOString()
181
- const isAC = data.is_acceptance_criterion ? 1 : 0
182
-
183
- // Append at the end: max(sort_order) + 1
184
- const maxRow = db
185
- .prepare('SELECT COALESCE(MAX(sort_order), -1) AS max FROM tasks WHERE workspace_id = ?')
186
- .get(workspaceId) as { max: number }
187
- const sortOrder = maxRow.max + 1
188
-
189
- db.prepare(
190
- 'INSERT INTO tasks (id, workspace_id, title, status, is_acceptance_criterion, sort_order, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
191
- ).run(id, workspaceId, data.title.trim(), 'pending', isAC, sortOrder, now, now)
192
-
193
- const row = db.prepare('SELECT id, title, status, is_acceptance_criterion FROM tasks WHERE id = ?').get(id) as TaskRow
194
- return rowToDto(row)
195
- }
196
-
197
- /** Update one or more fields of an existing task (title, status, or acceptance criterion flag). */
182
+ return rowToDto(
183
+ createTaskRecord(db, workspaceId, {
184
+ title: data.title,
185
+ isAcceptanceCriterion: data.is_acceptance_criterion,
186
+ sortOrder: data.sort_order,
187
+ afterTaskId: data.after_task_id,
188
+ role: data.role,
189
+ }),
190
+ )
191
+ }
192
+
193
+ /** Update task fields atomically, including insertion order and verification. */
198
194
  export function updateTaskHandler(
199
195
  db: Database.Database,
200
196
  workspaceId: string,
201
197
  taskId: string,
202
- data: { title?: string; status?: string; is_acceptance_criterion?: boolean },
198
+ data: {
199
+ title?: string
200
+ status?: string
201
+ is_acceptance_criterion?: boolean
202
+ sort_order?: number
203
+ after_task_id?: string
204
+ verification?: unknown
205
+ },
203
206
  ): TaskDto {
204
- // Verify task belongs to workspace
205
- const existing = db.prepare('SELECT id FROM tasks WHERE id = ? AND workspace_id = ?').get(taskId, workspaceId) as
206
- | { id: string }
207
- | undefined
208
- if (!existing) {
209
- throw new Error(`Task '${taskId}' not found in workspace '${workspaceId}'`)
210
- }
211
-
212
- const sets: string[] = []
213
- const values: unknown[] = []
214
-
215
- if (data.title !== undefined) {
216
- if (!data.title.trim()) throw new Error('title cannot be empty')
217
- sets.push('title = ?')
218
- values.push(data.title.trim())
219
- }
220
- if (data.status !== undefined) {
221
- if (!(VALID_TASK_STATUSES as readonly string[]).includes(data.status)) {
222
- throw new Error(`Invalid status '${data.status}'. Must be one of: ${VALID_TASK_STATUSES.join(', ')}`)
223
- }
224
- sets.push('status = ?')
225
- values.push(data.status)
226
- }
227
- if (data.is_acceptance_criterion !== undefined) {
228
- sets.push('is_acceptance_criterion = ?')
229
- values.push(data.is_acceptance_criterion ? 1 : 0)
230
- }
231
-
232
- if (sets.length === 0) {
233
- throw new Error('No fields to update (provide title, status, or is_acceptance_criterion)')
234
- }
235
-
236
- sets.push('updated_at = ?')
237
- values.push(new Date().toISOString())
238
- values.push(taskId)
239
-
240
- db.prepare(`UPDATE tasks SET ${sets.join(', ')} WHERE id = ?`).run(...values)
241
-
242
- const row = db
243
- .prepare('SELECT id, title, status, is_acceptance_criterion FROM tasks WHERE id = ?')
244
- .get(taskId) as TaskRow
245
- return rowToDto(row)
246
- }
247
-
248
- /** Permanently delete a task from a workspace. */
207
+ return rowToDto(
208
+ updateTaskRecord(db, workspaceId, taskId, {
209
+ title: data.title,
210
+ status: data.status,
211
+ isAcceptanceCriterion: data.is_acceptance_criterion,
212
+ sortOrder: data.sort_order,
213
+ afterTaskId: data.after_task_id,
214
+ verification: data.verification,
215
+ }),
216
+ )
217
+ }
218
+
219
+ /** Permanently delete a task from a workspace and invalidate its final review. */
249
220
  export function deleteTaskHandler(
250
221
  db: Database.Database,
251
222
  workspaceId: string,
252
223
  taskId: string,
253
224
  ): { success: true; task_id: string } {
254
- const result = db.prepare('DELETE FROM tasks WHERE id = ? AND workspace_id = ?').run(taskId, workspaceId)
255
- if (result.changes === 0) {
256
- throw new Error(`Task '${taskId}' not found in workspace '${workspaceId}'`)
257
- }
225
+ deleteTaskRecord(db, workspaceId, taskId)
258
226
  return { success: true, task_id: taskId }
259
227
  }
260
228
 
@@ -479,7 +447,6 @@ export function getTicketSourcesHandler(worktreePath: string): TicketSource[] {
479
447
  // ── Documents ────────────────────────────────────────────────────────────────
480
448
 
481
449
  /** Directories (relative to the worktree root) scanned for AI-generated docs. */
482
- export const DOCUMENT_DIRS = ['docs/plans', 'docs/superpowers', '.ai/thoughts'] as const
483
450
 
484
451
  /** Depth cap to keep recursion bounded even on pathological symlink loops. */
485
452
  const DOC_MAX_DEPTH = 8
@@ -28,6 +28,8 @@ import {
28
28
  } from './kobo-tasks-handlers.js'
29
29
  import { callWorkspaceDialogueTool } from './workspace-dialogue-client.js'
30
30
 
31
+ const handoffId = process.env.KOBO_HANDOFF_ID
32
+ const handoffToken = process.env.KOBO_HANDOFF_TOKEN
31
33
  const workspaceId = process.env.KOBO_WORKSPACE_ID
32
34
  const dbPath = process.env.KOBO_DB_PATH
33
35
  const settingsPath = process.env.KOBO_SETTINGS_PATH
@@ -143,22 +145,70 @@ async function backendRequest(
143
145
 
144
146
  const server = new Server({ name: 'kobo-tasks', version: '1.0.0' }, { capabilities: { tools: {} } })
145
147
 
148
+ const TASK_VERIFICATION_SCHEMA = {
149
+ type: 'object',
150
+ description:
151
+ 'Required to complete an auto-loop task. Describe checks actually performed; every check must be passed for done. Record failed/not_run checks only on an unfinished task.',
152
+ properties: {
153
+ method: { type: 'string', minLength: 1 },
154
+ summary: { type: 'string', minLength: 1 },
155
+ checks: {
156
+ type: 'array',
157
+ minItems: 1,
158
+ items: {
159
+ type: 'object',
160
+ properties: {
161
+ name: { type: 'string', minLength: 1 },
162
+ status: { type: 'string', enum: ['passed', 'failed', 'not_run'] },
163
+ },
164
+ required: ['name', 'status'],
165
+ },
166
+ },
167
+ },
168
+ required: ['method', 'summary', 'checks'],
169
+ }
170
+
171
+ const TASK_ORDER_PROPERTIES = {
172
+ sort_order: {
173
+ type: 'integer',
174
+ minimum: 0,
175
+ description:
176
+ 'Insert/move at this order, shifting siblings. Omit to append on creation. Mutually exclusive with after_task_id.',
177
+ },
178
+ after_task_id: {
179
+ type: 'string',
180
+ description: 'Insert/move immediately after this task in the same workspace, preserving the remaining order.',
181
+ },
182
+ }
183
+
146
184
  const WORKSPACE_SCOPED_TOOLS: Tool[] = [
185
+ {
186
+ name: 'submit_session_handoff',
187
+ description:
188
+ 'Submit the final Markdown handoff requested by Kōbō for this generation turn, then end your turn. Only available during a backend-owned session transfer; does not launch or stop sessions.',
189
+ inputSchema: {
190
+ type: 'object',
191
+ properties: { report: { type: 'string', minLength: 1, maxLength: 24000 } },
192
+ required: ['report'],
193
+ },
194
+ annotations: { destructiveHint: false, openWorldHint: false },
195
+ },
147
196
  {
148
197
  name: 'list_tasks',
149
198
  description:
150
- 'CALL FIRST on any non-trivial turn to know what the user wants done and what is already completed. Returns every task and acceptance criterion for the current workspace with its id and status. Re-call periodically (before marking something done, or after the user asks for a status) to stay in sync with user-added or external updates.',
199
+ 'CALL FIRST on any non-trivial turn to know what the user wants done and what is already completed. Returns every task and acceptance criterion for the current workspace with its id, status, sort_order, role, and verification evidence. Re-call periodically (before marking something done, or after the user asks for a status) to stay in sync with user-added or external updates.',
151
200
  inputSchema: { type: 'object', properties: {}, required: [] },
152
201
  annotations: { readOnlyHint: true, openWorldHint: false },
153
202
  },
154
203
  {
155
204
  name: 'mark_task_done',
156
205
  description:
157
- 'CALL AS SOON AS a task or acceptance criterion is finished AND verified (tests pass, feature works, diff committed). Do not wait for the end of the turn — the user watches progress live and marking each item as it completes is the primary signal Kōbō uses to track you.',
206
+ 'CALL AS SOON AS a task or acceptance criterion is finished AND verified by checks actually performed. Auto-loop requires structured verification evidence with all checks passed. Never mark done if required checks failed or were not run. Finalization also requires all work tasks and criteria done. Do not wait for the end of the turn — the user watches progress live and marking each item as it completes is the primary signal Kōbō uses to track you.',
158
207
  inputSchema: {
159
208
  type: 'object',
160
209
  properties: {
161
210
  task_id: { type: 'string', description: 'Task id from list_tasks.' },
211
+ verification: TASK_VERIFICATION_SCHEMA,
162
212
  },
163
213
  required: ['task_id'],
164
214
  },
@@ -174,10 +224,17 @@ const WORKSPACE_SCOPED_TOOLS: Tool[] = [
174
224
  {
175
225
  name: 'create_task',
176
226
  description:
177
- 'CALL WHEN you discover follow-up work that was not in the original list and needs to stick around (e.g. "refactor this helper later", "add a test for edge case"). Appends at the end of the list. Do not use it for ephemeral internal notes — prefer log_thought for those.',
227
+ 'CALL WHEN you discover follow-up work that was not in the original list and needs to stick around (e.g. "refactor this helper later", "add a test for edge case"). Appends by default; use after_task_id for a dependent check immediately after its parent. Use role finalization for the final verification gate. Do not use it for ephemeral internal notes — prefer log_thought for those.',
178
228
  inputSchema: {
179
229
  type: 'object',
180
230
  properties: {
231
+ ...TASK_ORDER_PROPERTIES,
232
+ role: {
233
+ type: 'string',
234
+ enum: ['work', 'finalization'],
235
+ description:
236
+ 'Default work. Finalization is the final verification gate and cannot finish while work/criteria remain open.',
237
+ },
181
238
  title: { type: 'string', description: 'Short, imperative title (e.g. "Add retry to fetchUser").' },
182
239
  is_acceptance_criterion: {
183
240
  type: 'boolean',
@@ -196,6 +253,8 @@ const WORKSPACE_SCOPED_TOOLS: Tool[] = [
196
253
  type: 'object',
197
254
  properties: {
198
255
  task_id: { type: 'string', description: 'Task id from list_tasks.' },
256
+ ...TASK_ORDER_PROPERTIES,
257
+ verification: TASK_VERIFICATION_SCHEMA,
199
258
  title: { type: 'string', description: 'New title (optional).' },
200
259
  status: {
201
260
  type: 'string',
@@ -425,14 +484,14 @@ const WORKSPACE_SCOPED_TOOLS: Tool[] = [
425
484
  {
426
485
  name: 'list_documents',
427
486
  description:
428
- 'CALL EARLY on a new session to discover plans, specs, and thoughts previously written for this workspace. Recursively lists every .md under docs/plans/, docs/superpowers/, and .ai/thoughts/. Before writing a new plan, check if one already exists.',
487
+ 'CALL EARLY on a new session to discover plans, specs, and thoughts previously written for this workspace. Recursively lists every .md under docs/plans/, docs/superpowers/, .ai/thoughts/, and .ai/handoffs/. Before writing a new plan, check if one already exists.',
429
488
  inputSchema: { type: 'object', properties: {}, required: [] },
430
489
  annotations: { readOnlyHint: true, openWorldHint: false },
431
490
  },
432
491
  {
433
492
  name: 'read_document',
434
493
  description:
435
- 'CALL AFTER list_documents when a file title looks relevant to the current task. Returns the full markdown content. Scoped to docs/plans/, docs/superpowers/, .ai/thoughts/ — reject anything else.',
494
+ 'CALL AFTER list_documents when a file title looks relevant to the current task. Returns the full markdown content. Scoped to docs/plans/, docs/superpowers/, .ai/thoughts/, .ai/handoffs/ — reject anything else.',
436
495
  inputSchema: {
437
496
  type: 'object',
438
497
  properties: {
@@ -636,9 +695,15 @@ const GLOBAL_TOOLS: typeof WORKSPACE_SCOPED_TOOLS = [
636
695
  */
637
696
  const GLOBAL_TOOL_NAMES = new Set(GLOBAL_TOOLS.map((t) => t.name))
638
697
 
639
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
640
- tools: workspaceId ? [...WORKSPACE_SCOPED_TOOLS, ...GLOBAL_TOOLS] : GLOBAL_TOOLS,
641
- }))
698
+ function availableTools(): Tool[] {
699
+ const tools = workspaceId ? [...WORKSPACE_SCOPED_TOOLS, ...GLOBAL_TOOLS] : GLOBAL_TOOLS
700
+ return tools.filter((tool) =>
701
+ handoffId && handoffToken
702
+ ? tool.name === 'submit_session_handoff' || tool.annotations?.readOnlyHint === true
703
+ : tool.name !== 'submit_session_handoff',
704
+ )
705
+ }
706
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: availableTools() }))
642
707
 
643
708
  /** Wrap a successful result as an MCP tool response with JSON text content. */
644
709
  function ok(data: unknown) {
@@ -674,6 +739,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
674
739
  }
675
740
 
676
741
  try {
742
+ if (handoffId && handoffToken && !availableTools().some((tool) => tool.name === name))
743
+ return fail(
744
+ 'This turn is reserved for a handoff report. Only read tools and submit_session_handoff are available.',
745
+ )
746
+ if (name === 'submit_session_handoff') {
747
+ if (!workspaceId || !handoffId || !handoffToken)
748
+ return fail('No handoff generation is active for this MCP invocation.')
749
+ return ok(
750
+ await backendRequest('POST', `/api/workspaces/${workspaceId}/session-handoffs/${handoffId}/report`, {
751
+ token: handoffToken,
752
+ report: a.report,
753
+ }),
754
+ )
755
+ }
677
756
  if (WORKSPACE_DIALOGUE_TOOLS.some((tool) => tool.name === name)) {
678
757
  if (workspaceId && a.workspace_id === workspaceId && name === 'send_workspace_message')
679
758
  return fail('Use the normal conversation to communicate in your own workspace.')
@@ -692,7 +771,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
692
771
  if (name === 'mark_task_done') {
693
772
  const taskId = a.task_id as string | undefined
694
773
  if (!taskId) return fail('task_id parameter is required')
695
- const result = markTaskDoneHandler(db, workspaceId!, taskId)
774
+ const result = markTaskDoneHandler(db, workspaceId!, taskId, a.verification)
696
775
  void notifyBackend(taskId)
697
776
  return ok(result)
698
777
  }
@@ -708,7 +787,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
708
787
  if (!title) return fail('title parameter is required')
709
788
  const task = createTaskHandler(db, workspaceId!, {
710
789
  title,
790
+ role: a.role as 'work' | 'finalization' | undefined,
711
791
  is_acceptance_criterion: a.is_acceptance_criterion as boolean | undefined,
792
+ sort_order: a.sort_order as number | undefined,
793
+ after_task_id: a.after_task_id as string | undefined,
712
794
  })
713
795
  void notifyTasksUpdated()
714
796
  return ok(task)
@@ -720,7 +802,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
720
802
  const task = updateTaskHandler(db, workspaceId!, taskId, {
721
803
  title: a.title as string | undefined,
722
804
  status: a.status as string | undefined,
805
+ verification: a.verification,
723
806
  is_acceptance_criterion: a.is_acceptance_criterion as boolean | undefined,
807
+ sort_order: a.sort_order as number | undefined,
808
+ after_task_id: a.after_task_id as string | undefined,
724
809
  })
725
810
  void notifyTasksUpdated()
726
811
  return ok(task)