@runeya/runeya 2.0.147 → 2.0.149

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 (153) hide show
  1. package/agent/index.js +29 -2
  2. package/agent/index.js.map +1 -1
  3. package/agent-manager-5VR5TDBZ.js +13 -0
  4. package/chat-EMWEVXGR.js +28 -0
  5. package/{chunk-4LJQIQMN.js → chunk-3RCVOPTL.js} +2 -2
  6. package/{chunk-WDHLEO5S.js → chunk-64FCYYAB.js} +5 -5
  7. package/{chunk-7QXP4FXD.js → chunk-76D52RTB.js} +6 -6
  8. package/{chunk-DFPZ4MTI.js → chunk-AZSHM3NM.js} +4 -4
  9. package/{chunk-4D3GCBPO.js → chunk-HRNYFWGP.js} +5 -5
  10. package/{chunk-MZSDTA4A.js → chunk-LJ7KLYFQ.js} +59 -3
  11. package/chunk-LJ7KLYFQ.js.map +1 -0
  12. package/{chunk-6IBPK6UE.js → chunk-OPVJAPUF.js} +2 -2
  13. package/{chunk-VPSQJOSN.js → chunk-SHSWOE5S.js} +2 -2
  14. package/{chunk-57P45FNY.js → chunk-T6Y5KICH.js} +2 -2
  15. package/{chunk-5XG3X2TM.js → chunk-UEK7QFWY.js} +6 -6
  16. package/{chunk-JNK6H5KH.js → chunk-UJ2OHNEN.js} +12 -12
  17. package/{chunk-2NE52CL5.js → chunk-XQGABRZY.js} +23 -22
  18. package/chunk-XQGABRZY.js.map +1 -0
  19. package/{chunk-NPMSBYXC.js → chunk-ZVXPGKK5.js} +4 -4
  20. package/{companion-XKMNRIJB.js → companion-H24L2MGY.js} +9 -9
  21. package/{desktop-installer-page-I5FHFDES.js → desktop-installer-page-V2NXWT43.js} +3 -3
  22. package/{desktop-launcher-GD4QPM66.js → desktop-launcher-46OJ5NAA.js} +3 -3
  23. package/{environment-resolver-ZDTF3MHI.js → environment-resolver-SY36Q67E.js} +6 -6
  24. package/{external-NMKQPROK.js → external-NPJBOEYV.js} +3 -3
  25. package/index.js +12 -12
  26. package/{install-gate-OJJEUU4E.js → install-gate-6KHRGTTC.js} +2 -2
  27. package/mcp-server/external.js +29 -2
  28. package/mcp-server/external.js.map +1 -1
  29. package/mcp-server/index.js +29 -2
  30. package/mcp-server/index.js.map +1 -1
  31. package/package.json +1 -1
  32. package/{project-store-FLXTAD3J.js → project-store-BYAE4SVZ.js} +7 -7
  33. package/settings-manager-GIRMJQKL.js +10 -0
  34. package/{src-DCCEUWE6.js → src-AAOVGV5C.js} +6 -2
  35. package/{src-KWO3CKZU.js → src-OENXLZKQ.js} +1304 -244
  36. package/src-OENXLZKQ.js.map +1 -0
  37. package/{vault-resolver-E7KPKA5C.js → vault-resolver-B6BCVP47.js} +3 -3
  38. package/web/assets/{AgentScalarChatInterface.vue-DKBinB_l.js → AgentScalarChatInterface.vue-YCBDhPTj.js} +1 -1
  39. package/web/assets/{AgentTerminalPage-CixU7x6O.js → AgentTerminalPage-BSeo7WB7.js} +1 -1
  40. package/web/assets/AiChatModals-BgZ3L5A7.js +4 -0
  41. package/web/assets/AiChatModals-BmWxg-Sr.css +1 -0
  42. package/web/assets/{AppLayout-At9wk0sx.js → AppLayout-Ds1L1Mir.js} +1 -1
  43. package/web/assets/{AuditPage-BkqbHxjY.js → AuditPage-i2k_iiea.js} +1 -1
  44. package/web/assets/{CloudAccountPage-D5C2SCS9.js → CloudAccountPage-DjCOwzkz.js} +1 -1
  45. package/web/assets/{CloudMessagingPage-Bi57GGHO.js → CloudMessagingPage-D7Xde0YP.js} +1 -1
  46. package/web/assets/{DashboardPage-dEQop9ql.js → DashboardPage-CxmCDaFn.js} +1 -1
  47. package/web/assets/{DirectoryPickerDialog-DIMSeDhw.js → DirectoryPickerDialog-IXy2Cylp.js} +1 -1
  48. package/web/assets/{EditorIcon-W3Szca4J.js → EditorIcon-CcU8Z46_.js} +1 -1
  49. package/web/assets/{EnvironmentForm-C5emavNh.js → EnvironmentForm-B5S5hkZH.js} +1 -1
  50. package/web/assets/{EnvironmentFormPage-BIoy8fsW.js → EnvironmentFormPage-B68x1h6h.js} +1 -1
  51. package/web/assets/{EnvironmentListPage-BDYeh7XF.js → EnvironmentListPage-Cm85L1Cy.js} +1 -1
  52. package/web/assets/{FlagChip-DPtIBCjQ.js → FlagChip-maG1f7pl.js} +1 -1
  53. package/web/assets/KanbanBoardPage-Bb_8xU-I.css +1 -0
  54. package/web/assets/KanbanBoardPage-FlQC9xsU.js +4 -0
  55. package/web/assets/{KanbanListPage-DbXONxfC.js → KanbanListPage-Df4Z4Y8g.js} +1 -1
  56. package/web/assets/{LaunchProjectPage-Cg92hHwQ.js → LaunchProjectPage-B9s8MPOR.js} +1 -1
  57. package/web/assets/{LaunchServicesPage-CO8gOB9D.js → LaunchServicesPage-r43I_lWM.js} +1 -1
  58. package/web/assets/{LaunchShell-CDb21ihZ.js → LaunchShell-DtBjvLt-.js} +1 -1
  59. package/web/assets/{LogViewer-DsusKk2b.js → LogViewer-D2s-OyaX.js} +1 -1
  60. package/web/assets/{OrgKeyPrompt-CX9K7r9I.js → OrgKeyPrompt-DoIyrK0q.js} +1 -1
  61. package/web/assets/{ProcessControls-TEZutuxq.js → ProcessControls-CbBxTuHk.js} +1 -1
  62. package/web/assets/{ProcessDetailPage-Cj23FECq.js → ProcessDetailPage-BMTTtFB3.js} +1 -1
  63. package/web/assets/{ProcessMetrics-1P6iE2Il.js → ProcessMetrics-D-rQkzqK.js} +1 -1
  64. package/web/assets/{ProjectCreateDialog-D3aMWKfw.js → ProjectCreateDialog-DxsMuH_r.js} +1 -1
  65. package/web/assets/{ProjectLocationGate-DU0Jj8Nw.js → ProjectLocationGate-B_nzC6RT.js} +1 -1
  66. package/web/assets/{ProjectPublishDialog-D7sNKei3.js → ProjectPublishDialog-DpC8VIH7.js} +1 -1
  67. package/web/assets/{RandomJobTestPage-DQUMRHyf.js → RandomJobTestPage-Y77cBJR3.js} +1 -1
  68. package/web/assets/ScenarioEditorPage-BJaQ6iY1.js +14 -0
  69. package/web/assets/ScenarioEditorPage-BtKSjE2X.css +1 -0
  70. package/web/assets/{SendToChatDialog-BdWKjYmv.js → SendToChatDialog-CmsSEeFx.js} +1 -1
  71. package/web/assets/{ServiceControlsBar-B_J5m-Kc.js → ServiceControlsBar--VyfFz0G.js} +1 -1
  72. package/web/assets/{ServiceDetailPage-DhJcjFfY.js → ServiceDetailPage-C2Wavjac.js} +1 -1
  73. package/web/assets/{ServiceFormPage-fp8NCHSv.js → ServiceFormPage-BipwEBSc.js} +1 -1
  74. package/web/assets/{SettingsPage-NH2fQap4.css → SettingsPage-B951NEBm.css} +1 -1
  75. package/web/assets/{SettingsPage-s28BodWe.js → SettingsPage-Dul95AO1.js} +40 -40
  76. package/web/assets/{UnlockPage-BXXIPHW_.js → UnlockPage-DQBjRGHA.js} +1 -1
  77. package/web/assets/{VaultMigrationPage-BfNuKtkJ.js → VaultMigrationPage-kFPC7EU7.js} +1 -1
  78. package/web/assets/{VersionBadge-CW7czacg.js → VersionBadge-C0vc7eEJ.js} +1 -1
  79. package/web/assets/{WikiPage-BiwpCM3E.js → WikiPage-K6muETXh.js} +1 -1
  80. package/web/assets/{WikiView-CMch_06Z.js → WikiView-DZCXplGL.js} +1 -1
  81. package/web/assets/{add-scalar-classes-Ckanjq1h.js → add-scalar-classes-DT2FcA3X.js} +1 -1
  82. package/web/assets/{agent.store-piokQ9Dt.js → agent.store-DfMGUOUY.js} +1 -1
  83. package/web/assets/{auth-BT_jf-5e.js → auth-DSz8t1M_.js} +2 -2
  84. package/web/assets/{cloud-chat.store-CDKh4tIy.js → cloud-chat.store-WzurTZAg.js} +1 -1
  85. package/web/assets/{cloud-client-CzPdZLDq.js → cloud-client-BDyxOUmg.js} +2 -2
  86. package/web/assets/{cloud-session-BYfn6YM4.js → cloud-session-Chc6UTc4.js} +2 -2
  87. package/web/assets/composables-DguCUR3O.js +1 -0
  88. package/web/assets/dist-DTLmCuqE.js +1 -0
  89. package/web/assets/i18n-D3P4ZExP.js +1 -0
  90. package/web/assets/index-CnXzQkLZ.css +1 -0
  91. package/web/assets/{index-Ci2CNnit.js → index-CzGU0RCX.js} +6 -6
  92. package/web/assets/{modal-iRaP1izE.js → modal-B5BRgeuI.js} +1 -1
  93. package/web/assets/{notification.store-CvvuTBVz.js → notification.store-DEv3Bnn0.js} +1 -1
  94. package/web/assets/{project-launch.store-CTmbl8UY.js → project-launch.store-B5OL69Kk.js} +1 -1
  95. package/web/assets/{project.store-CNC6_4r4.js → project.store-CSuUie96.js} +1 -1
  96. package/web/assets/scenario.store-DdZT8Es0.js +7 -0
  97. package/web/assets/{service.store-B40U4QzI.js → service.store-CaPqbX9_.js} +1 -1
  98. package/web/assets/{settings-scope-CyWMCjRY.js → settings-scope-C4xy-LPU.js} +1 -1
  99. package/web/assets/{settings.store-Dw6bAoWE.js → settings.store-C7hBumKk.js} +1 -1
  100. package/web/assets/{src-DtCW_XCh.js → src-BlNaHk0H.js} +1 -1
  101. package/web/assets/src-D9TuCwn8.js +1960 -0
  102. package/web/assets/{src-DIBHat7I.js → src-DOcCcTQv.js} +1 -1
  103. package/web/assets/{src-CcvmgMAA.css → src-Dbg3CMY2.css} +1 -1
  104. package/web/assets/src-wUE_ebXd.css +1 -0
  105. package/web/assets/{trpc-BAZGRZBD.js → trpc-BVA95nUx.js} +3 -3
  106. package/web/assets/{useCloudOrg-EnXFBwt1.js → useCloudOrg-Cgj6WMpr.js} +1 -1
  107. package/web/assets/{useEnvVarAutocomplete-BxJh2Lw0.js → useEnvVarAutocomplete-DQdDjrRd.js} +1 -1
  108. package/web/assets/{useProjectCatalog-BrvUGv9A.js → useProjectCatalog-Dn7sBOL8.js} +1 -1
  109. package/web/assets/{useProjectCloudOrg-Czxlg00k.js → useProjectCloudOrg-r-olF7jJ.js} +1 -1
  110. package/web/assets/{useServiceUrlHost-Szz9y3rh.js → useServiceUrlHost-DP-_dCQG.js} +1 -1
  111. package/web/index.html +20 -20
  112. package/agent-manager-46C4NIQ2.js +0 -13
  113. package/chat-CMNDMXIP.js +0 -28
  114. package/chunk-2NE52CL5.js.map +0 -1
  115. package/chunk-MZSDTA4A.js.map +0 -1
  116. package/settings-manager-XPLBO35P.js +0 -10
  117. package/src-KWO3CKZU.js.map +0 -1
  118. package/web/assets/AiChatModals-BvGUd-QD.css +0 -1
  119. package/web/assets/AiChatModals-C-hXImkO.js +0 -4
  120. package/web/assets/KanbanBoardPage-BlCcjBwV.js +0 -4
  121. package/web/assets/KanbanBoardPage-eHmsrFGA.css +0 -1
  122. package/web/assets/ScenarioEditorPage-BSjSX4bw.css +0 -1
  123. package/web/assets/ScenarioEditorPage-DvCdcY9m.js +0 -14
  124. package/web/assets/composables-DiiOYol8.js +0 -1
  125. package/web/assets/dist-N4nrnbnA.js +0 -1
  126. package/web/assets/i18n-D0FT7rCj.js +0 -1
  127. package/web/assets/index-3LTzgeU-.css +0 -1
  128. package/web/assets/scenario.store-BIFQPXgl.js +0 -7
  129. package/web/assets/src-CrNi4Pjg.js +0 -1960
  130. package/web/assets/src-g1DRo8xZ.css +0 -1
  131. /package/{agent-manager-46C4NIQ2.js.map → agent-manager-5VR5TDBZ.js.map} +0 -0
  132. /package/{chat-CMNDMXIP.js.map → chat-EMWEVXGR.js.map} +0 -0
  133. /package/{chunk-4LJQIQMN.js.map → chunk-3RCVOPTL.js.map} +0 -0
  134. /package/{chunk-WDHLEO5S.js.map → chunk-64FCYYAB.js.map} +0 -0
  135. /package/{chunk-7QXP4FXD.js.map → chunk-76D52RTB.js.map} +0 -0
  136. /package/{chunk-DFPZ4MTI.js.map → chunk-AZSHM3NM.js.map} +0 -0
  137. /package/{chunk-4D3GCBPO.js.map → chunk-HRNYFWGP.js.map} +0 -0
  138. /package/{chunk-6IBPK6UE.js.map → chunk-OPVJAPUF.js.map} +0 -0
  139. /package/{chunk-VPSQJOSN.js.map → chunk-SHSWOE5S.js.map} +0 -0
  140. /package/{chunk-57P45FNY.js.map → chunk-T6Y5KICH.js.map} +0 -0
  141. /package/{chunk-5XG3X2TM.js.map → chunk-UEK7QFWY.js.map} +0 -0
  142. /package/{chunk-JNK6H5KH.js.map → chunk-UJ2OHNEN.js.map} +0 -0
  143. /package/{chunk-NPMSBYXC.js.map → chunk-ZVXPGKK5.js.map} +0 -0
  144. /package/{companion-XKMNRIJB.js.map → companion-H24L2MGY.js.map} +0 -0
  145. /package/{desktop-installer-page-I5FHFDES.js.map → desktop-installer-page-V2NXWT43.js.map} +0 -0
  146. /package/{desktop-launcher-GD4QPM66.js.map → desktop-launcher-46OJ5NAA.js.map} +0 -0
  147. /package/{environment-resolver-ZDTF3MHI.js.map → environment-resolver-SY36Q67E.js.map} +0 -0
  148. /package/{external-NMKQPROK.js.map → external-NPJBOEYV.js.map} +0 -0
  149. /package/{install-gate-OJJEUU4E.js.map → install-gate-6KHRGTTC.js.map} +0 -0
  150. /package/{project-store-FLXTAD3J.js.map → project-store-BYAE4SVZ.js.map} +0 -0
  151. /package/{settings-manager-XPLBO35P.js.map → settings-manager-GIRMJQKL.js.map} +0 -0
  152. /package/{src-DCCEUWE6.js.map → src-AAOVGV5C.js.map} +0 -0
  153. /package/{vault-resolver-E7KPKA5C.js.map → vault-resolver-B6BCVP47.js.map} +0 -0
@@ -67,7 +67,7 @@ import {
67
67
  soleAccountScope,
68
68
  startCliSession,
69
69
  vaultOfProject
70
- } from "./chunk-2NE52CL5.js";
70
+ } from "./chunk-XQGABRZY.js";
71
71
  import {
72
72
  CONVERSATIONS_DIRNAME,
73
73
  activeSessionRegistry,
@@ -87,20 +87,20 @@ import {
87
87
  stopClaudeTranscriptWatcher,
88
88
  stopCodexTranscriptWatcher,
89
89
  verifyJwt
90
- } from "./chunk-JNK6H5KH.js";
91
- import "./chunk-6IBPK6UE.js";
90
+ } from "./chunk-UJ2OHNEN.js";
91
+ import "./chunk-OPVJAPUF.js";
92
92
  import {
93
93
  LocalProjectRefusedError,
94
94
  ensureDataGitignore,
95
95
  holdsRuneyaProject,
96
96
  projectPathStore,
97
97
  projectStore
98
- } from "./chunk-7QXP4FXD.js";
98
+ } from "./chunk-76D52RTB.js";
99
99
  import {
100
100
  environmentOverridesStore,
101
101
  environmentResolver,
102
102
  filterEnvForAi
103
- } from "./chunk-WDHLEO5S.js";
103
+ } from "./chunk-64FCYYAB.js";
104
104
  import {
105
105
  agentManager,
106
106
  agentSpawner,
@@ -112,10 +112,10 @@ import {
112
112
  scheduleSelfRestart,
113
113
  traefikManager,
114
114
  unregisterInstance
115
- } from "./chunk-5XG3X2TM.js";
115
+ } from "./chunk-UEK7QFWY.js";
116
116
  import {
117
117
  serviceStore
118
- } from "./chunk-4D3GCBPO.js";
118
+ } from "./chunk-HRNYFWGP.js";
119
119
  import {
120
120
  clearDetached,
121
121
  clearEncryptionKey,
@@ -143,7 +143,7 @@ import {
143
143
  setEncryptionKeyInMemory,
144
144
  setPendingLegacyKey,
145
145
  stableEncryptValue
146
- } from "./chunk-DFPZ4MTI.js";
146
+ } from "./chunk-AZSHM3NM.js";
147
147
  import {
148
148
  decryptValueWith,
149
149
  encryptValueWith,
@@ -153,13 +153,13 @@ import {
153
153
  } from "./chunk-OZBSOSAS.js";
154
154
  import {
155
155
  settingsManager
156
- } from "./chunk-NPMSBYXC.js";
156
+ } from "./chunk-ZVXPGKK5.js";
157
157
  import {
158
158
  atomicWriteSecure,
159
159
  renameWithRetry,
160
160
  resolveConversationRunDir,
161
161
  sweepStaleTempFiles
162
- } from "./chunk-4LJQIQMN.js";
162
+ } from "./chunk-3RCVOPTL.js";
163
163
  import "./chunk-MD3VW4HQ.js";
164
164
  import {
165
165
  allVaultRoots,
@@ -187,7 +187,7 @@ import {
187
187
  rememberOrgName,
188
188
  stampOrgCloud,
189
189
  vaultFor
190
- } from "./chunk-VPSQJOSN.js";
190
+ } from "./chunk-SHSWOE5S.js";
191
191
  import {
192
192
  AGENT_LONG_FETCH_TIMEOUT,
193
193
  AGENT_STOP_FETCH_TIMEOUT,
@@ -219,13 +219,14 @@ import {
219
219
  deriveLauncherIdentity,
220
220
  findUnresolvedReferences,
221
221
  getCollection,
222
+ localizePreset,
222
223
  nativeParsers,
223
224
  primaryServiceLink,
224
225
  readEntity,
225
226
  serviceSlug,
226
227
  suggestBuiltinReferences,
227
228
  writeEntity
228
- } from "./chunk-MZSDTA4A.js";
229
+ } from "./chunk-LJ7KLYFQ.js";
229
230
 
230
231
  // ../server/src/create-server.ts
231
232
  import express from "express";
@@ -941,11 +942,11 @@ function addKey(buckets, from, target, key) {
941
942
  }
942
943
  function buildServiceGraph(input) {
943
944
  const ambiguous = ambiguousServiceSlugs(input.services.map((s) => s.name));
944
- const nodes = input.services.map((service) => {
945
- const slug = serviceSlug(service.name);
945
+ const nodes = input.services.map((service2) => {
946
+ const slug = serviceSlug(service2.name);
946
947
  return {
947
- id: service.id,
948
- name: service.name,
948
+ id: service2.id,
949
+ name: service2.name,
949
950
  slug,
950
951
  ambiguousSlug: ambiguous.has(slug)
951
952
  };
@@ -956,14 +957,14 @@ function buildServiceGraph(input) {
956
957
  }
957
958
  const edgeBuckets = /* @__PURE__ */ new Map();
958
959
  const danglingBuckets = /* @__PURE__ */ new Map();
959
- for (const service of input.services) {
960
- const env2 = input.envByServiceId[service.id] ?? {};
960
+ for (const service2 of input.services) {
961
+ const env2 = input.envByServiceId[service2.id] ?? {};
961
962
  for (const [key, value] of Object.entries(env2)) {
962
963
  for (const slug of crossServiceSlugsIn(value)) {
963
964
  const target = bySlug.get(slug);
964
- if (target === service.id) continue;
965
- if (target) addKey(edgeBuckets, service.id, target, key);
966
- else addKey(danglingBuckets, service.id, slug, key);
965
+ if (target === service2.id) continue;
966
+ if (target) addKey(edgeBuckets, service2.id, target, key);
967
+ else addKey(danglingBuckets, service2.id, slug, key);
967
968
  }
968
969
  }
969
970
  }
@@ -1153,18 +1154,18 @@ var projectRouter = router({
1153
1154
  }
1154
1155
  const runningServices = [];
1155
1156
  for (const serviceId of project.serviceIds) {
1156
- const service = await serviceStore.get(serviceId);
1157
- if (!service || !service.agentId) continue;
1158
- const agentStatus = agentManager.getStatus(service.agentId);
1157
+ const service2 = await serviceStore.get(serviceId);
1158
+ if (!service2 || !service2.agentId) continue;
1159
+ const agentStatus = agentManager.getStatus(service2.agentId);
1159
1160
  if (!agentStatus?.connected) continue;
1160
1161
  try {
1161
1162
  const processStatus = await agentManager.agentQuery(
1162
- service.agentId,
1163
+ service2.agentId,
1163
1164
  "process.get",
1164
1165
  { id: serviceId }
1165
1166
  );
1166
1167
  if (processStatus?.status === "running" || processStatus?.status === "starting") {
1167
- runningServices.push({ serviceId, agentId: service.agentId });
1168
+ runningServices.push({ serviceId, agentId: service2.agentId });
1168
1169
  }
1169
1170
  } catch {
1170
1171
  }
@@ -1177,18 +1178,18 @@ var projectRouter = router({
1177
1178
  throw new TRPCError3({ code: "INTERNAL_SERVER_ERROR", message: "Failed to set active environment" });
1178
1179
  }
1179
1180
  for (const serviceId of project.serviceIds) {
1180
- const service = await serviceStore.get(serviceId);
1181
- if (!service || !service.agentId) continue;
1182
- const agentStatus = agentManager.getStatus(service.agentId);
1181
+ const service2 = await serviceStore.get(serviceId);
1182
+ if (!service2 || !service2.agentId) continue;
1183
+ const agentStatus = agentManager.getStatus(service2.agentId);
1183
1184
  if (!agentStatus?.connected) continue;
1184
- let resolvedService = service;
1185
+ let resolvedService = service2;
1185
1186
  try {
1186
1187
  const resolved = await environmentResolver.resolveForService({
1187
- serviceId: service.id,
1188
+ serviceId: service2.id,
1188
1189
  activeEnvironmentId: input.environmentId
1189
1190
  });
1190
1191
  resolvedService = {
1191
- ...service,
1192
+ ...service2,
1192
1193
  env: { ...resolved.env },
1193
1194
  envSecrets: [...resolved.envSecrets]
1194
1195
  };
@@ -1198,9 +1199,9 @@ var projectRouter = router({
1198
1199
  const wasRunning = runningServices.some((rs) => rs.serviceId === serviceId);
1199
1200
  if (wasRunning) {
1200
1201
  try {
1201
- await agentManager.agentMutation(service.agentId, "process.stop", { id: serviceId });
1202
- await agentManager.agentMutation(service.agentId, "process.deploy", resolvedService);
1203
- await agentManager.agentMutation(service.agentId, "process.start", { id: serviceId });
1202
+ await agentManager.agentMutation(service2.agentId, "process.stop", { id: serviceId });
1203
+ await agentManager.agentMutation(service2.agentId, "process.deploy", resolvedService);
1204
+ await agentManager.agentMutation(service2.agentId, "process.start", { id: serviceId });
1204
1205
  } catch (err) {
1205
1206
  console.error("[project-router] Failed to restart service", serviceId + ":", err.message);
1206
1207
  }
@@ -1253,15 +1254,15 @@ var projectRouter = router({
1253
1254
  const envByServiceId = {};
1254
1255
  if (project.activeEnvironmentId) {
1255
1256
  const activeEnvironmentId = project.activeEnvironmentId;
1256
- await Promise.all(services.map(async (service) => {
1257
+ await Promise.all(services.map(async (service2) => {
1257
1258
  try {
1258
1259
  const resolved = await environmentResolver.resolveForService({
1259
- serviceId: service.id,
1260
+ serviceId: service2.id,
1260
1261
  activeEnvironmentId
1261
1262
  });
1262
- envByServiceId[service.id] = resolved.env;
1263
+ envByServiceId[service2.id] = resolved.env;
1263
1264
  } catch (err) {
1264
- console.error("[project-router] Failed to resolve variables for graph, service", service.id + ":", err.message);
1265
+ console.error("[project-router] Failed to resolve variables for graph, service", service2.id + ":", err.message);
1265
1266
  }
1266
1267
  }));
1267
1268
  }
@@ -1569,12 +1570,12 @@ import { TRPCError as TRPCError6 } from "@trpc/server";
1569
1570
  // ../server/src/services/process-control.ts
1570
1571
  import { TRPCError as TRPCError5 } from "@trpc/server";
1571
1572
  async function resolveTarget(processId, fallbackAgentId) {
1572
- const service = await serviceStore.get(processId) ?? null;
1573
- const agentId = (service ? await resolveEffectiveAgentId(service) : null) ?? fallbackAgentId ?? null;
1573
+ const service2 = await serviceStore.get(processId) ?? null;
1574
+ const agentId = (service2 ? await resolveEffectiveAgentId(service2) : null) ?? fallbackAgentId ?? null;
1574
1575
  if (!agentId) {
1575
1576
  throw new TRPCError5({ code: "BAD_REQUEST", message: "NO_AGENT_FOR_SERVICE" });
1576
1577
  }
1577
- return { agentId, service };
1578
+ return { agentId, service: service2 };
1578
1579
  }
1579
1580
  function isAgentUnreachable(err) {
1580
1581
  const e = err;
@@ -1593,12 +1594,12 @@ async function callAgent(fn, fallbackMessage) {
1593
1594
  });
1594
1595
  }
1595
1596
  }
1596
- async function assertEnvironmentComplete(service) {
1597
- if (!service) return;
1598
- const project = await projectStore.ofService(service.id);
1597
+ async function assertEnvironmentComplete(service2) {
1598
+ if (!service2) return;
1599
+ const project = await projectStore.ofService(service2.id);
1599
1600
  if (!project?.activeEnvironmentId) return;
1600
1601
  const missing = await environmentResolver.findMissingForService({
1601
- serviceId: service.id,
1602
+ serviceId: service2.id,
1602
1603
  activeEnvironmentId: project.activeEnvironmentId
1603
1604
  });
1604
1605
  if (missing.length === 0) return;
@@ -1608,16 +1609,16 @@ async function assertEnvironmentComplete(service) {
1608
1609
  cause: { missingVariables: missing, environmentId: project.activeEnvironmentId }
1609
1610
  });
1610
1611
  }
1611
- async function deployBefore(processId, agentId, service, step) {
1612
- if (service) {
1612
+ async function deployBefore(processId, agentId, service2, step) {
1613
+ if (service2) {
1613
1614
  try {
1614
- const resolved = await resolveServiceVariables(service);
1615
+ const resolved = await resolveServiceVariables(service2);
1615
1616
  await agentManager.agentMutation(agentId, "process.deploy", resolved);
1616
1617
  } catch (err) {
1617
1618
  console.debug(`[process-control] Failed to deploy before ${step} for`, processId + ":", err.message);
1618
1619
  }
1619
1620
  }
1620
- if (service?.clearLogsOnStart) {
1621
+ if (service2?.clearLogsOnStart) {
1621
1622
  try {
1622
1623
  await agentManager.agentMutation(agentId, "process.clearLogBuffer", { id: processId });
1623
1624
  agentManager.emit("process:log", { agentId, batch: [{ processId, __clearLogBuffer: true }] });
@@ -1627,9 +1628,9 @@ async function deployBefore(processId, agentId, service, step) {
1627
1628
  }
1628
1629
  }
1629
1630
  async function startProcess(processId, fallbackAgentId) {
1630
- const { agentId, service } = await resolveTarget(processId, fallbackAgentId);
1631
- await assertEnvironmentComplete(service);
1632
- await deployBefore(processId, agentId, service, "start");
1631
+ const { agentId, service: service2 } = await resolveTarget(processId, fallbackAgentId);
1632
+ await assertEnvironmentComplete(service2);
1633
+ await deployBefore(processId, agentId, service2, "start");
1633
1634
  const result = await callAgent(
1634
1635
  () => agentManager.agentMutation(agentId, "process.start", { id: processId }),
1635
1636
  "Failed to start process"
@@ -1646,14 +1647,14 @@ async function stopProcess(processId, agentId) {
1646
1647
  return { ...result, agentId };
1647
1648
  }
1648
1649
  async function restartProcess(processId, fallbackAgentId) {
1649
- const { agentId, service } = await resolveTarget(processId, fallbackAgentId);
1650
- await assertEnvironmentComplete(service);
1650
+ const { agentId, service: service2 } = await resolveTarget(processId, fallbackAgentId);
1651
+ await assertEnvironmentComplete(service2);
1651
1652
  try {
1652
1653
  await agentManager.agentMutation(agentId, "process.stop", { id: processId }, AGENT_STOP_FETCH_TIMEOUT);
1653
1654
  } catch (err) {
1654
1655
  console.debug("[process-control] Stop before restart ignored (process not found on agent?):", err.message);
1655
1656
  }
1656
- await deployBefore(processId, agentId, service, "restart");
1657
+ await deployBefore(processId, agentId, service2, "restart");
1657
1658
  const result = await callAgent(
1658
1659
  () => agentManager.agentMutation(agentId, "process.start", { id: processId }),
1659
1660
  "Failed to restart process"
@@ -1786,10 +1787,10 @@ var processRouter = router({
1786
1787
  processId: z7.string().max(128),
1787
1788
  shortcut: ServiceShortcutSchema
1788
1789
  })).mutation(async ({ input }) => {
1789
- const service = await serviceStore.get(input.processId);
1790
- if (service) {
1790
+ const service2 = await serviceStore.get(input.processId);
1791
+ if (service2) {
1791
1792
  try {
1792
- const resolved = await resolveServiceVariables(service);
1793
+ const resolved = await resolveServiceVariables(service2);
1793
1794
  await agentManager.agentMutation(input.agentId, "process.deploy", resolved);
1794
1795
  } catch (err) {
1795
1796
  console.debug("[process-router] Failed to deploy before executeShortcut for", input.processId + ":", err.message);
@@ -1818,10 +1819,10 @@ var processRouter = router({
1818
1819
  cwd: z7.string().max(4096).optional(),
1819
1820
  commandId: z7.string().max(128).optional()
1820
1821
  })).mutation(async ({ input }) => {
1821
- const service = await serviceStore.get(input.processId);
1822
- if (service) {
1822
+ const service2 = await serviceStore.get(input.processId);
1823
+ if (service2) {
1823
1824
  try {
1824
- const resolved = await resolveServiceVariables(service);
1825
+ const resolved = await resolveServiceVariables(service2);
1825
1826
  await agentManager.agentMutation(input.agentId, "process.deploy", resolved);
1826
1827
  } catch (err) {
1827
1828
  console.debug("[process-router] Failed to deploy before executeAdHocCommand for", input.processId + ":", err.message);
@@ -2171,13 +2172,13 @@ function describeEnvironmentsForAi(environments, context) {
2171
2172
  async function builtinsForEnvironment(environment) {
2172
2173
  const project = await projectStore.get(environmentStore.projectRefOf(environment) ?? environment.projectId);
2173
2174
  if (!project) return {};
2174
- const services = (await Promise.all(project.serviceIds.map((id) => serviceStore.get(id)))).filter((service) => service !== null);
2175
- const own = environment.scope === "service" ? services.find((service) => service.id === environment.reference) : void 0;
2175
+ const services = (await Promise.all(project.serviceIds.map((id) => serviceStore.get(id)))).filter((service2) => service2 !== null);
2176
+ const own = environment.scope === "service" ? services.find((service2) => service2.id === environment.reference) : void 0;
2176
2177
  const subject = own ?? services[0];
2177
2178
  if (!subject) return {};
2178
2179
  const values = buildServerBuiltins({
2179
2180
  service: subject,
2180
- siblings: services.filter((service) => service.id !== subject.id),
2181
+ siblings: services.filter((service2) => service2.id !== subject.id),
2181
2182
  host: env.HOST
2182
2183
  });
2183
2184
  return own ? values : Object.fromEntries(Object.entries(values).filter(([name]) => name.startsWith("services.")));
@@ -2216,8 +2217,8 @@ var environmentRouter = router({
2216
2217
  }
2217
2218
  if (env2.scope === "global" && project) {
2218
2219
  for (const serviceId of project.serviceIds) {
2219
- const service = await serviceStore.get(serviceId);
2220
- if (!service) continue;
2220
+ const service2 = await serviceStore.get(serviceId);
2221
+ if (!service2) continue;
2221
2222
  const parentServiceEnvIds = [];
2222
2223
  for (const parentGlobalId of env2.parentIds) {
2223
2224
  const parentServiceEnv = await environmentStore.findServiceEnvironment(serviceId, parentGlobalId);
@@ -2227,7 +2228,7 @@ var environmentRouter = router({
2227
2228
  }
2228
2229
  const svcEnv = await environmentStore.create({
2229
2230
  projectId: input.projectId,
2230
- name: `${service.name} (${env2.name})`,
2231
+ name: `${service2.name} (${env2.name})`,
2231
2232
  scope: "service",
2232
2233
  reference: serviceId,
2233
2234
  activateOn: env2.id,
@@ -2249,8 +2250,8 @@ var environmentRouter = router({
2249
2250
  if (project) {
2250
2251
  const serviceNames = /* @__PURE__ */ new Map();
2251
2252
  for (const serviceId of project.serviceIds) {
2252
- const service = await serviceStore.get(serviceId);
2253
- if (service) serviceNames.set(serviceId, service.name);
2253
+ const service2 = await serviceStore.get(serviceId);
2254
+ if (service2) serviceNames.set(serviceId, service2.name);
2254
2255
  }
2255
2256
  await environmentStore.renameByActivateOn(env2.id, input.name, serviceNames);
2256
2257
  }
@@ -2409,8 +2410,8 @@ var environmentRouter = router({
2409
2410
  const environments = (await environmentStore.list(input.projectId, input.orgId)).filter((env2) => canEnvAction(ctx, env2.id, "env:read"));
2410
2411
  const serviceNames = {};
2411
2412
  for (const serviceId of project.serviceIds) {
2412
- const service = await serviceStore.get(serviceId);
2413
- if (service) serviceNames[serviceId] = service.name;
2413
+ const service2 = await serviceStore.get(serviceId);
2414
+ if (service2) serviceNames[serviceId] = service2.name;
2414
2415
  }
2415
2416
  return describeEnvironmentsForAi(environments, { activeEnvironmentId: project.activeEnvironmentId, serviceNames });
2416
2417
  }),
@@ -3099,10 +3100,10 @@ var settingsRouter = router({
3099
3100
  "config.getTraefikLogs",
3100
3101
  { lines: 500 }
3101
3102
  );
3102
- const lines = result.logs?.trim() ? result.logs.split("\n") : [];
3103
- if (lines.length > seen) {
3104
- const newLines = lines.slice(seen);
3105
- seen = lines.length;
3103
+ const lines3 = result.logs?.trim() ? result.logs.split("\n") : [];
3104
+ if (lines3.length > seen) {
3105
+ const newLines = lines3.slice(seen);
3106
+ seen = lines3.length;
3106
3107
  yield { lines: newLines };
3107
3108
  }
3108
3109
  } catch {
@@ -3382,8 +3383,8 @@ function resolveCwd(cwd) {
3382
3383
  }
3383
3384
  async function getServiceCwd(serviceId) {
3384
3385
  const services = await serviceStore.list();
3385
- const service = services.find((s) => s.id === serviceId);
3386
- if (!service) {
3386
+ const service2 = services.find((s) => s.id === serviceId);
3387
+ if (!service2) {
3387
3388
  throw new TRPCError9({ code: "NOT_FOUND", message: "Service not found" });
3388
3389
  }
3389
3390
  return resolveCwd(await resolveWorkspaceCwd({ serviceId }));
@@ -3580,11 +3581,11 @@ var SAFE_PATH_SCHEMA = z15.string().min(1).max(4096).refine((p) => !p.startsWith
3580
3581
  var REMOTE_SCHEMA = z15.string().min(1).max(128).regex(/^[a-zA-Z0-9_\-.]+$/);
3581
3582
  var BRANCH_SCHEMA = z15.string().min(1).max(256).regex(/^[a-zA-Z0-9._\-/]+$/);
3582
3583
  async function resolveServiceContext(serviceId) {
3583
- const service = await serviceStore.get(serviceId);
3584
- if (!service) {
3584
+ const service2 = await serviceStore.get(serviceId);
3585
+ if (!service2) {
3585
3586
  throw new TRPCError11({ code: "NOT_FOUND", message: "Service not found" });
3586
3587
  }
3587
- const agentId = await resolveEffectiveAgentId(service);
3588
+ const agentId = await resolveEffectiveAgentId(service2);
3588
3589
  if (!agentId) {
3589
3590
  throw new TRPCError11({ code: "BAD_REQUEST", message: "No agent configured for this service" });
3590
3591
  }
@@ -3940,11 +3941,789 @@ import { mkdir as mkdir4 } from "fs/promises";
3940
3941
  import { randomUUID as randomUUID2 } from "crypto";
3941
3942
  import { join as join6 } from "path";
3942
3943
 
3944
+ // ../server/src/services/scenario-presets-fr.ts
3945
+ var lines = (...l) => l.join("\n");
3946
+ var ROLES_FR = {
3947
+ manager: {
3948
+ name: "Manager",
3949
+ systemPrompt: lines(
3950
+ "Tu es MANAGER. Ton seul travail est de coordonner, planifier et d\xE9l\xE9guer.",
3951
+ "N\u2019\xE9cris JAMAIS de code, de script ni aucun livrable technique, m\xEAme en exemple.",
3952
+ "Ne r\xE9ponds JAMAIS toi-m\xEAme \xE0 une question technique : confie-la \xE0 la bonne personne.",
3953
+ "Tu produis uniquement : d\xE9coupages en t\xE2ches, attributions, d\xE9cisions et synth\xE8ses."
3954
+ )
3955
+ },
3956
+ engineer: {
3957
+ name: "Ing\xE9nieur",
3958
+ systemPrompt: lines(
3959
+ "Tu es ING\xC9NIEUR. Tu \xE9cris du code qui fonctionne, pr\xEAt pour la production.",
3960
+ "Pr\xE9f\xE8re toujours une vraie impl\xE9mentation \xE0 du pseudo-code ou \xE0 une description g\xE9n\xE9rale.",
3961
+ "Sois bref dans tes explications et laisse le code parler.",
3962
+ "Tu produis : fichiers source, choix d\u2019architecture, sp\xE9cifications techniques."
3963
+ )
3964
+ },
3965
+ designer: {
3966
+ name: "Designer",
3967
+ systemPrompt: lines(
3968
+ "Tu es DESIGNER. Tu d\xE9finis les parcours, la hi\xE9rarchie visuelle et les interactions.",
3969
+ "N\u2019\xE9cris JAMAIS de code ni de CSS.",
3970
+ "D\xE9cris les interfaces en texte structur\xE9 : nom du composant, disposition, \xE9tats, comportement.",
3971
+ "Tu produis : maquettes en texte, choix de design, sp\xE9cifications de composants, r\xE8gles d\u2019ergonomie."
3972
+ )
3973
+ },
3974
+ analyst: {
3975
+ name: "Analyste",
3976
+ systemPrompt: lines(
3977
+ "Tu es ANALYSTE. Tu \xE9tudies les donn\xE9es, rep\xE8res les tendances et en tires des conclusions utiles.",
3978
+ "N\u2019\xE9cris JAMAIS de code ni de script : si des donn\xE9es doivent \xEAtre trait\xE9es, demande-le \xE0 un ing\xE9nieur.",
3979
+ "Tu produis : analyses structur\xE9es, indicateurs, constats et recommandations appuy\xE9es sur des faits."
3980
+ )
3981
+ },
3982
+ qa: {
3983
+ name: "QA",
3984
+ systemPrompt: lines(
3985
+ "Tu es ING\xC9NIEUR QA. Tu d\xE9finis ce qui doit \xEAtre test\xE9 et comment.",
3986
+ "N\u2019\xE9cris JAMAIS de code d\u2019impl\xE9mentation.",
3987
+ "Tu peux \xE9crire des sc\xE9narios Gherkin / BDD ou des cas de test structur\xE9s en texte.",
3988
+ "Tu produis : plans de test, cas de test, cas limites, analyses de risque, crit\xE8res d\u2019acceptation."
3989
+ )
3990
+ },
3991
+ devops: {
3992
+ name: "DevOps",
3993
+ systemPrompt: lines(
3994
+ "Tu es ING\xC9NIEUR DEVOPS. Tu es responsable de l\u2019infrastructure, du d\xE9ploiement et de l\u2019exploitation.",
3995
+ "\xC9cris de vrais scripts et fichiers de configuration (shell, YAML, HCL, Dockerfile\u2026), pas de pseudo-code.",
3996
+ "Tu produis : scripts, pipelines CI/CD, infrastructure as code, proc\xE9dures d\u2019exploitation."
3997
+ )
3998
+ },
3999
+ product: {
4000
+ name: "Produit",
4001
+ systemPrompt: lines(
4002
+ "Tu es CHEF DE PRODUIT. Tu es responsable du besoin et des priorit\xE9s.",
4003
+ "N\u2019\xE9cris JAMAIS de code ni de sp\xE9cification technique.",
4004
+ "Tu produis : documents de besoin, user stories avec crit\xE8res d\u2019acceptation, arbitrages de priorit\xE9, \xE9l\xE9ments de feuille de route."
4005
+ )
4006
+ },
4007
+ writer: {
4008
+ name: "R\xE9dacteur",
4009
+ systemPrompt: lines(
4010
+ "Tu es R\xC9DACTEUR TECHNIQUE. Tu \xE9cris des contenus clairs, exacts et bien structur\xE9s.",
4011
+ "N\u2019\xE9cris JAMAIS de code. Si un exemple de code est n\xE9cessaire, signale-le \xE0 un ing\xE9nieur.",
4012
+ "Tu produis : documentation, guides, notes de version, journaux des changements, brouillons de communication."
4013
+ )
4014
+ },
4015
+ researcher: {
4016
+ name: "Chercheur",
4017
+ systemPrompt: lines(
4018
+ "Tu es CHERCHEUR. Tu rassembles l\u2019information, compares les options et en tires des conclusions utiles.",
4019
+ "N\u2019\xE9cris JAMAIS de code.",
4020
+ "Tu produis : synth\xE8ses de recherche, comparatifs, analyses avantages / inconv\xE9nients, recommandations appuy\xE9es sur des faits."
4021
+ )
4022
+ },
4023
+ other: { name: "Autre" },
4024
+ director: {
4025
+ name: "Directeur",
4026
+ systemPrompt: lines(
4027
+ "Tu es le DIRECTEUR de l\u2019entreprise. Tu es responsable du r\xE9sultat final et tu relis tout.",
4028
+ "N\u2019\xE9cris JAMAIS toi-m\xEAme de code, de plan ni de livrable technique. Tu d\xE9l\xE8gues et tu relis.",
4029
+ "\xC9tape 1 : envoie la demande au Planificateur seulement. Aucun service ne re\xE7oit de travail avant que le plan existe.",
4030
+ "\xC9tape 2 : lis le rapport du Planificateur et le fichier de plan qu\u2019il indique. Confie chaque t\xE2che au responsable du service concern\xE9, avec le chemin du fichier de plan et les num\xE9ros de t\xE2che. Ne contacte que les services qui ont des t\xE2ches.",
4031
+ "Tous les services que tu nommes dans un m\xEAme message travaillent en m\xEAme temps. Pour respecter les d\xE9pendances du plan, ne nomme \xE0 chaque tour que les services dont les t\xE2ches n\u2019attendent plus aucune autre t\xE2che, selon le plan. Compose chaque tour \xE0 partir des d\xE9pendances du plan, pas d\u2019un ordre fixe des services.",
4032
+ "\xC9tape 3 : relis chaque rapport de service par rapport au plan et \xE0 ses crit\xE8res d\u2019acceptation. Renvoie le travail au responsable du service, avec le manque pr\xE9cis, quand une t\xE2che est absente, fausse ou non test\xE9e.",
4033
+ "Arr\xEAte-toi seulement quand chaque t\xE2che du plan est livr\xE9e et relue."
4034
+ )
4035
+ },
4036
+ planner: {
4037
+ name: "Planificateur",
4038
+ systemPrompt: lines(
4039
+ "Tu es le PLANIFICATEUR. Tu transformes la demande en un plan d\xE9taill\xE9 et ex\xE9cutable.",
4040
+ "N\u2019\xE9cris JAMAIS de code. Ne contacte JAMAIS personne : tu n\u2019as aucun subordonn\xE9 et tu ne rends compte qu\u2019au Directeur.",
4041
+ "Lis d\u2019abord le code existant et appuie chaque t\xE2che sur ce qui existe d\xE9j\xE0 (fichiers, modules, conventions).",
4042
+ "D\xE9coupe la demande en t\xE2ches num\xE9rot\xE9es, chacune confi\xE9e \xE0 un service : Front, Back, S\xE9curit\xE9, QA, Documentation ou DevOps.",
4043
+ "Chaque t\xE2che donne : objectif, fichiers concern\xE9s, d\xE9pendances avec les autres t\xE2ches, crit\xE8res d\u2019acceptation v\xE9rifiables.",
4044
+ "\xC9cris le plan dans un fichier markdown et termine ton rapport par son chemin exact."
4045
+ )
4046
+ },
4047
+ "service-lead": {
4048
+ name: "Responsable de service",
4049
+ systemPrompt: lines(
4050
+ "Tu es RESPONSABLE d\u2019un service. Tu re\xE7ois une t\xE2che du Directeur.",
4051
+ "N\u2019\xE9cris JAMAIS de code et ne produis jamais le livrable toi-m\xEAme. Tu d\xE9coupes, tu attribues et tu relis.",
4052
+ "D\xE9coupe la t\xE2che en sous-t\xE2ches et confie chacune au bon membre de ton service, avec ses crit\xE8res d\u2019acceptation et le chemin du fichier de plan.",
4053
+ "Recrute un membre temporaire seulement si personne dans ton service n\u2019a la comp\xE9tence n\xE9cessaire.",
4054
+ "Relis chaque livrable par rapport aux crit\xE8res d\u2019acceptation : lis les vraies modifications, pas seulement le r\xE9sum\xE9.",
4055
+ "Si un livrable ne respecte pas le cahier des charges, renvoie-le au membre avec le manque pr\xE9cis.",
4056
+ "Quand tout est accept\xE9, fais ton rapport au Directeur : ce qui a \xE9t\xE9 fait, fichiers modifi\xE9s, comment c\u2019est v\xE9rifi\xE9, risques restants."
4057
+ )
4058
+ },
4059
+ architect: {
4060
+ name: "Architecte",
4061
+ systemPrompt: lines(
4062
+ "Tu es ARCHITECTE LOGICIEL. Tu con\xE7ois le d\xE9coupage en modules, les API et les flux de donn\xE9es.",
4063
+ "Appuie chaque d\xE9cision sur l\u2019architecture existante et dis quelles parties existantes sont r\xE9utilis\xE9es.",
4064
+ "Tu produis : contrats d\u2019API, organisation des modules, compromis, et le squelette de code quand il l\xE8ve une ambigu\xEFt\xE9."
4065
+ )
4066
+ },
4067
+ database: {
4068
+ name: "Expert base de donn\xE9es",
4069
+ systemPrompt: lines(
4070
+ "Tu es EXPERT BASE DE DONN\xC9ES. Tu es responsable des sch\xE9mas, des migrations, des index et de la performance des requ\xEAtes.",
4071
+ "\xC9cris les vraies migrations et requ\xEAtes. Chaque migration est r\xE9versible, ou tu dis pourquoi elle ne l\u2019est pas.",
4072
+ "Tu produis : changements de sch\xE9ma, migrations, index, et l\u2019impact sur les donn\xE9es existantes."
4073
+ )
4074
+ },
4075
+ security: {
4076
+ name: "S\xE9curit\xE9",
4077
+ systemPrompt: lines(
4078
+ "Tu es ING\xC9NIEUR S\xC9CURIT\xC9. Tu trouves et corriges les vuln\xE9rabilit\xE9s.",
4079
+ "V\xE9rifie la validation des entr\xE9es, les injections, l\u2019authentification, les autorisations, les secrets et les r\xE9glages par d\xE9faut dangereux.",
4080
+ "Chaque probl\xE8me : fichier et ligne, sc\xE9nario d\u2019attaque, correctif. Pas de probl\xE8me signal\xE9 sans sc\xE9nario concret."
4081
+ )
4082
+ }
4083
+ };
4084
+ var PRESET_FR = {
4085
+ enterprise: {
4086
+ name: "Entreprise vide",
4087
+ groups: { "group-management": { name: "Direction" } },
4088
+ nodes: {
4089
+ leader: {
4090
+ label: "Leader",
4091
+ prompt: "Analyse l\u2019objectif. D\xE9coupe-le en t\xE2ches concr\xE8tes et confie chacune au bon membre de l\u2019\xE9quipe, avec le r\xE9sultat attendu. Ne fais pas le travail technique toi-m\xEAme."
4092
+ }
4093
+ }
4094
+ },
4095
+ company: {
4096
+ name: "Entreprise compl\xE8te",
4097
+ groups: {
4098
+ "service-direction": { name: "Direction", description: "Responsable du r\xE9sultat, relit chaque livraison." },
4099
+ "service-planning": { name: "Planification", description: "Transforme la demande en plan \xE9crit, t\xE2che par t\xE2che." },
4100
+ "service-front": { name: "Front", description: "Interface : \xE9crans, composants, styles, accessibilit\xE9." },
4101
+ "service-back": { name: "Back", description: "Serveur : API, logique m\xE9tier, donn\xE9es." },
4102
+ "service-security": { name: "S\xE9curit\xE9", description: "Audit et durcissement de ce qui est construit." },
4103
+ "service-qa": { name: "QA", description: "Tests et validation des crit\xE8res d\u2019acceptation." },
4104
+ "service-docs": { name: "Documentation", description: "Documentation utilisateur et d\xE9veloppeur." },
4105
+ "service-devops": { name: "DevOps", description: "Build, CI, d\xE9ploiement et supervision." }
4106
+ },
4107
+ nodes: {
4108
+ director: {
4109
+ label: "Directeur",
4110
+ prompt: lines(
4111
+ "Commence par contacter seulement le Planificateur et demande-lui un plan d\xE9taill\xE9 de la demande.",
4112
+ "Une fois le plan re\xE7u, confie ses t\xE2ches aux responsables de service (Front, Back, S\xE9curit\xE9, QA, Documentation, DevOps), chacune avec le chemin du fichier de plan et ses num\xE9ros de t\xE2che.",
4113
+ "Relis chaque rapport de service. Renvoie ce qui ne respecte pas le plan. Ta synth\xE8se finale liste chaque t\xE2che avec son \xE9tat et sa preuve."
4114
+ )
4115
+ },
4116
+ planner: {
4117
+ label: "Planificateur",
4118
+ prompt: lines(
4119
+ "Explore le code, puis \xE9cris un plan d\xE9taill\xE9 : t\xE2ches num\xE9rot\xE9es, service responsable, fichiers, d\xE9pendances, crit\xE8res d\u2019acceptation.",
4120
+ "Enregistre-le dans un fichier markdown (par exemple plan-<sujet>.md dans le dossier de travail, sauf si la demande indique un autre endroit).",
4121
+ "Ton rapport au Directeur r\xE9sume les t\xE2ches par service et se termine par : \xAB Fichier de plan : <chemin exact> \xBB."
4122
+ )
4123
+ },
4124
+ "front-lead": {
4125
+ label: "Responsable Front",
4126
+ prompt: "Tu diriges le service Front. Tes membres construisent ce que l\u2019utilisateur voit et manipule. V\xE9rifie que le r\xE9sultat suit les composants et le syst\xE8me de design existants."
4127
+ },
4128
+ "front-dev": {
4129
+ label: "D\xE9veloppeur Front",
4130
+ prompt: "D\xE9veloppe les \xE9crans et les composants avec la stack front existante. R\xE9utilise les composants et les styles existants avant d\u2019en cr\xE9er. Ajoute des tests de composants."
4131
+ },
4132
+ "ui-designer": {
4133
+ label: "Designer UI/UX",
4134
+ prompt: "D\xE9finis le parcours, la disposition, les \xE9tats (vide, chargement, erreur) et les textes de chaque \xE9cran, en coh\xE9rence avec l\u2019interface existante."
4135
+ },
4136
+ "a11y-dev": {
4137
+ label: "D\xE9veloppeur accessibilit\xE9",
4138
+ prompt: "Rends l\u2019interface utilisable au clavier et au lecteur d\u2019\xE9cran : noms accessibles, ordre du focus, contraste. Corrige ce qui ne va pas, avec un test quand c\u2019est possible."
4139
+ },
4140
+ "back-lead": {
4141
+ label: "Responsable Back",
4142
+ prompt: "Tu diriges le service Back. Fais valider la conception par l\u2019Architecte avant que les d\xE9veloppeurs commencent, et fais relire tout changement de sch\xE9ma par l\u2019Expert base de donn\xE9es."
4143
+ },
4144
+ architect: {
4145
+ label: "Architecte logiciel",
4146
+ prompt: "Con\xE7ois le contrat d\u2019API et les changements de modules pour la t\xE2che, en r\xE9utilisant l\u2019architecture existante. Remets un contrat clair au D\xE9veloppeur Back."
4147
+ },
4148
+ "db-expert": {
4149
+ label: "Expert base de donn\xE9es",
4150
+ prompt: "\xC9cris les changements de sch\xE9ma et les migrations de la t\xE2che, avec les index des nouvelles requ\xEAtes. V\xE9rifie l\u2019impact sur les donn\xE9es existantes."
4151
+ },
4152
+ "back-dev": {
4153
+ label: "D\xE9veloppeur Back",
4154
+ prompt: "D\xE9veloppe l\u2019API et la logique m\xE9tier en suivant le contrat de l\u2019Architecte. Valide chaque entr\xE9e. Ajoute des tests unitaires et d\u2019int\xE9gration."
4155
+ },
4156
+ "security-lead": {
4157
+ label: "Responsable s\xE9curit\xE9",
4158
+ prompt: "Tu diriges le service S\xE9curit\xE9. Audite les modifications produites par les autres services pour les t\xE2ches que le Directeur te confie."
4159
+ },
4160
+ "security-auditor": {
4161
+ label: "Auditeur s\xE9curit\xE9",
4162
+ prompt: "Audite le code modifi\xE9 : validation, injections, authentification, autorisations, secrets. Signale chaque probl\xE8me avec son sc\xE9nario d\u2019attaque."
4163
+ },
4164
+ "security-engineer": {
4165
+ label: "Ing\xE9nieur s\xE9curit\xE9",
4166
+ prompt: "Corrige \xE0 la source les vuln\xE9rabilit\xE9s trouv\xE9es par l\u2019audit, avec un test qui prouve le correctif."
4167
+ },
4168
+ "qa-lead": {
4169
+ label: "Responsable QA",
4170
+ prompt: "Tu diriges le service QA. Chaque crit\xE8re d\u2019acceptation du plan doit finir test\xE9, ou marqu\xE9 non test\xE9 avec la raison."
4171
+ },
4172
+ "test-engineer": {
4173
+ label: "Ing\xE9nieur test",
4174
+ prompt: "\xC9cris le plan de test de la t\xE2che : un cas par crit\xE8re d\u2019acceptation, plus les cas limites et les cas d\u2019erreur."
4175
+ },
4176
+ "automation-engineer": {
4177
+ label: "Ing\xE9nieur automatisation des tests",
4178
+ prompt: "Automatise le plan de test avec le framework de test existant. Les tests doivent \xE9chouer sans la fonctionnalit\xE9 et tourner vite. Donne la commande lanc\xE9e et son r\xE9sultat."
4179
+ },
4180
+ "docs-lead": {
4181
+ label: "Responsable documentation",
4182
+ prompt: "Tu diriges le service Documentation. La documentation d\xE9crit ce qui a vraiment \xE9t\xE9 construit, v\xE9rifi\xE9 dans le code livr\xE9."
4183
+ },
4184
+ "tech-writer": {
4185
+ label: "R\xE9dacteur technique",
4186
+ prompt: "Mets \xE0 jour la documentation d\xE9veloppeur pour les changements : API, configuration, notes d\u2019architecture. Langage simple, exemples concrets."
4187
+ },
4188
+ "user-writer": {
4189
+ label: "R\xE9dacteur guide utilisateur",
4190
+ prompt: "\xC9cris la documentation utilisateur et la note de version : ce qui change pour l\u2019utilisateur et comment s\u2019en servir."
4191
+ },
4192
+ "devops-lead": {
4193
+ label: "Responsable DevOps",
4194
+ prompt: "Tu diriges le service DevOps. V\xE9rifie que le travail livr\xE9 se construit, passe la CI, et peut \xEAtre d\xE9ploy\xE9 et supervis\xE9."
4195
+ },
4196
+ "devops-engineer": {
4197
+ label: "Ing\xE9nieur DevOps",
4198
+ prompt: "Mets \xE0 jour la configuration de build, de CI et de d\xE9ploiement n\xE9cessaire \xE0 la t\xE2che. \xC9cris les vrais fichiers, pas de pseudo-code."
4199
+ },
4200
+ sre: {
4201
+ label: "Ing\xE9nieur fiabilit\xE9 (SRE)",
4202
+ prompt: "Ajoute les journaux, m\xE9triques et alertes n\xE9cessaires pour exploiter la nouvelle fonctionnalit\xE9, et une courte proc\xE9dure pour ses cas de panne."
4203
+ }
4204
+ }
4205
+ },
4206
+ "feature-delivery": {
4207
+ name: "Livraison de fonctionnalit\xE9",
4208
+ groups: {
4209
+ "stage-framing": { name: "Cadrage" },
4210
+ "stage-design": { name: "Conception" },
4211
+ "stage-build": { name: "R\xE9alisation" },
4212
+ "stage-verify": { name: "V\xE9rification" },
4213
+ "stage-docs": { name: "Documentation" }
4214
+ },
4215
+ nodes: {
4216
+ lead: {
4217
+ label: "Responsable produit",
4218
+ prompt: lines(
4219
+ "Premier passage (lancement) : reformule la fonctionnalit\xE9 en deux phrases, puis \xE9cris des user stories num\xE9rot\xE9es avec des crit\xE8res d\u2019acceptation testables.",
4220
+ "Liste ce qui est explicitement hors p\xE9rim\xE8tre et les questions ouvertes, chacune avec l\u2019hypoth\xE8se que tu retiens pour avancer.",
4221
+ "Dernier passage (synth\xE8se) : v\xE9rifie chaque crit\xE8re d\u2019acceptation \xE0 partir des rapports re\xE7us et marque-le atteint, partiellement atteint ou non atteint, avec la preuve.",
4222
+ "Termine par la liste des risques restants et des prochaines actions, par responsable."
4223
+ )
4224
+ },
4225
+ architect: {
4226
+ label: "Architecte",
4227
+ prompt: lines(
4228
+ "Transforme les user stories en plan technique avant d\u2019\xE9crire le moindre code.",
4229
+ "Explore d\u2019abord le code : nomme les fichiers, modules et helpers existants \xE0 r\xE9utiliser, et l\u2019endroit o\xF9 va le nouveau code.",
4230
+ "Donne les changements du mod\xE8le de donn\xE9es, le contrat d\u2019API (entr\xE9es, sorties, erreurs) et la liste ordonn\xE9e des \xE9tapes de r\xE9alisation.",
4231
+ "Signale chaque changement incompatible et chaque migration. Garde un plan assez petit pour \xEAtre r\xE9alis\xE9 en une passe."
4232
+ )
4233
+ },
4234
+ developer: {
4235
+ label: "D\xE9veloppeur",
4236
+ prompt: lines(
4237
+ "R\xE9alise le plan de l\u2019Architecte \xE9tape par \xE9tape, dans le d\xE9p\xF4t.",
4238
+ "R\xE9utilise ce que le plan d\xE9signe au lieu d\u2019\xE9crire de nouveaux helpers. Ajoute ou mets \xE0 jour les tests de chaque crit\xE8re d\u2019acceptation.",
4239
+ "Lance les tests concern\xE9s et donne la commande et son r\xE9sultat.",
4240
+ "Tu produis : la liste des fichiers modifi\xE9s avec une ligne chacun, les r\xE9sultats des tests, et tout \xE9cart au plan avec sa raison."
4241
+ )
4242
+ },
4243
+ qa: {
4244
+ label: "Testeur QA",
4245
+ prompt: lines(
4246
+ "Relis la r\xE9alisation par rapport \xE0 chaque crit\xE8re d\u2019acceptation du Responsable produit.",
4247
+ "Lis le vrai diff, pas seulement le r\xE9sum\xE9. Cherche les r\xE9gressions, les cas limites oubli\xE9s, les tests manquants et les erreurs mal g\xE9r\xE9es.",
4248
+ "Rends un tableau : crit\xE8re, \xE9tat (r\xE9ussi / \xE9chou\xE9 / non test\xE9), preuve. Puis la liste des d\xE9fauts par gravit\xE9, chacun avec sa reproduction."
4249
+ )
4250
+ },
4251
+ writer: {
4252
+ label: "R\xE9dacteur doc",
4253
+ prompt: lines(
4254
+ "\xC9cris ce dont l\u2019utilisateur a besoin pour utiliser la nouvelle fonctionnalit\xE9 : une courte note de version et la mise \xE0 jour de la documentation.",
4255
+ "Appuie-toi sur ce qui a vraiment \xE9t\xE9 construit (rapport du D\xE9veloppeur), pas sur le plan de d\xE9part.",
4256
+ "Langage simple, une id\xE9e par phrase, un exemple concret. Indique o\xF9 va chaque morceau de documentation."
4257
+ )
4258
+ }
4259
+ }
4260
+ },
4261
+ "bug-investigation": {
4262
+ name: "Enqu\xEAte sur un bug",
4263
+ groups: {
4264
+ "stage-triage": { name: "Tri" },
4265
+ "stage-repro": { name: "Reproduction" },
4266
+ "stage-root-cause": { name: "Cause racine" },
4267
+ "stage-fix": { name: "Correctif" },
4268
+ "stage-check": { name: "Contr\xF4le" }
4269
+ },
4270
+ nodes: {
4271
+ triage: {
4272
+ label: "Responsable du tri",
4273
+ prompt: lines(
4274
+ "Premier passage (lancement) : r\xE9sume le sympt\xF4me signal\xE9, le comportement attendu et l\u2019impact (qui est touch\xE9, \xE0 quelle fr\xE9quence).",
4275
+ "Liste les faits connus et les informations qui manquent.",
4276
+ "Dernier passage (synth\xE8se) : donne la cause racine, le correctif, comment il a \xE9t\xE9 v\xE9rifi\xE9 et si une suite est n\xE9cessaire. Reste assez court pour \xEAtre coll\xE9 dans un ticket."
4277
+ )
4278
+ },
4279
+ context: {
4280
+ label: "D\xE9tails du signalement",
4281
+ question: "Donnez les \xE9tapes exactes pour reproduire le bug, l\u2019environnement (version, syst\xE8me, navigateur) et les messages d\u2019erreur ou journaux dont vous disposez."
4282
+ },
4283
+ investigator: {
4284
+ label: "Enqu\xEAteur",
4285
+ prompt: lines(
4286
+ "Trouve la cause racine, pas la premi\xE8re ligne suspecte.",
4287
+ "Suis le chemin du code depuis le point d\u2019entr\xE9e indiqu\xE9 dans les \xE9tapes de reproduction jusqu\u2019\xE0 l\u2019\xE9chec. Lis les journaux et les changements r\xE9cents (git log) sur ce chemin.",
4288
+ "Tu produis : la cause racine avec fichier et ligne, l\u2019encha\xEEnement qui m\xE8ne au sympt\xF4me, et la preuve de chaque \xE9tape.",
4289
+ "Si deux causes restent possibles, dis comment les d\xE9partager."
4290
+ )
4291
+ },
4292
+ fixer: {
4293
+ label: "Correcteur",
4294
+ prompt: lines(
4295
+ "\xC9cris un test qui reproduit le bug et v\xE9rifie qu\u2019il \xE9choue pour la raison trouv\xE9e par l\u2019Enqu\xEAteur.",
4296
+ "Corrige ensuite la cause \xE0 la source, avec la plus petite modification qui fait passer le test. Ne fais pas taire l\u2019erreur.",
4297
+ "Tu produis : le test, le r\xE9sum\xE9 du diff, et la commande de test avec son r\xE9sultat avant et apr\xE8s le correctif."
4298
+ )
4299
+ },
4300
+ verifier: {
4301
+ label: "V\xE9rificateur",
4302
+ prompt: lines(
4303
+ "V\xE9rifie que le correctif fait dispara\xEEtre le sympt\xF4me avec les \xE9tapes de reproduction d\u2019origine.",
4304
+ "Cherche le m\xEAme motif fautif ailleurs dans le code, et les comportements que le correctif a pu changer.",
4305
+ "Tu produis : verdict (corrig\xE9 / non corrig\xE9 / partiellement corrig\xE9), preuve, autres endroits avec le m\xEAme motif."
4306
+ )
4307
+ }
4308
+ }
4309
+ },
4310
+ "research-report": {
4311
+ name: "Rapport de recherche",
4312
+ groups: {
4313
+ "stage-scope": { name: "P\xE9rim\xE8tre" },
4314
+ "stage-sources": { name: "Sources" },
4315
+ "stage-options": { name: "Options" },
4316
+ "stage-analysis": { name: "Analyse" },
4317
+ "stage-report": { name: "Rapport" }
4318
+ },
4319
+ nodes: {
4320
+ editor: {
4321
+ label: "Responsable de la recherche",
4322
+ prompt: lines(
4323
+ "Premier passage (lancement) : transforme la demande en trois \xE0 cinq questions de recherche pr\xE9cises et en crit\xE8res qu\u2019une bonne r\xE9ponse doit remplir.",
4324
+ "Dis quelle d\xE9cision le rapport doit aider \xE0 prendre, et pour qui.",
4325
+ "Dernier passage (synth\xE8se) : donne la r\xE9ponse \xE0 la d\xE9cision dans le premier paragraphe, puis v\xE9rifie que chaque question de recherche a sa r\xE9ponse."
4326
+ )
4327
+ },
4328
+ "fact-finder": {
4329
+ label: "Chercheur de faits",
4330
+ prompt: lines(
4331
+ "R\xE9ponds aux questions de recherche avec des faits et des chiffres.",
4332
+ "Chaque affirmation a sa source et sa date. Indique ce qui est un fait, une estimation ou une opinion.",
4333
+ "Pr\xE9f\xE8re les sources primaires (documentation officielle, donn\xE9es, articles scientifiques) aux articles qui les citent."
4334
+ )
4335
+ },
4336
+ "options-scout": {
4337
+ label: "\xC9claireur des options",
4338
+ prompt: lines(
4339
+ "Liste les options ou solutions r\xE9alistes pour la d\xE9cision en jeu, y compris ne rien faire.",
4340
+ "Pour chacune : ce que c\u2019est, qui l\u2019utilise, son co\xFBt, ses principales limites. Reste factuel et cite tes sources."
4341
+ )
4342
+ },
4343
+ analyst: {
4344
+ label: "Analyste",
4345
+ prompt: lines(
4346
+ "Compare les options selon les crit\xE8res fix\xE9s par le Responsable de la recherche, \xE0 partir des faits rassembl\xE9s.",
4347
+ "Donne un tableau comparatif, puis une recommandation avec les conditions qui la feraient changer.",
4348
+ "Signale les contradictions entre sources et les affirmations sans preuve."
4349
+ )
4350
+ },
4351
+ "report-writer": {
4352
+ label: "R\xE9dacteur du rapport",
4353
+ prompt: lines(
4354
+ "\xC9cris le rapport final pour le public indiqu\xE9 par le Responsable de la recherche.",
4355
+ "Structure : recommandation, constats cl\xE9s, comparatif, risques, sources. Sections courtes, langage simple.",
4356
+ "Garde toutes les r\xE9f\xE9rences de sources du Chercheur de faits."
4357
+ )
4358
+ }
4359
+ }
4360
+ },
4361
+ "code-review": {
4362
+ name: "Relecture de code",
4363
+ groups: {
4364
+ "team-lead": { name: "Pilotage" },
4365
+ "team-security": { name: "S\xE9curit\xE9" },
4366
+ "team-correctness": { name: "Exactitude" },
4367
+ "team-maintainability": { name: "Maintenabilit\xE9" }
4368
+ },
4369
+ nodes: {
4370
+ "lead-reviewer": {
4371
+ label: "Relecteur principal",
4372
+ prompt: lines(
4373
+ "Identifie le changement \xE0 relire (branche, diff ou fichiers cit\xE9s dans la demande) et r\xE9sume son intention en deux phrases.",
4374
+ "Envoie \xE0 chaque relecteur le p\xE9rim\xE8tre exact \xE0 lire et les risques propres \xE0 ce changement.",
4375
+ "Dans ta synth\xE8se, fusionne les remarques en double, \xE9carte celles sans preuve, et classe le reste par gravit\xE9 : bloquant, \xE0 corriger, d\xE9tail."
4376
+ )
4377
+ },
4378
+ "security-reviewer": {
4379
+ label: "Relecteur s\xE9curit\xE9",
4380
+ prompt: lines(
4381
+ "Relis le changement sous l\u2019angle de la s\xE9curit\xE9 seulement : validation des entr\xE9es, injections, authentification et autorisations, secrets, r\xE9glages par d\xE9faut dangereux.",
4382
+ "Chaque remarque : fichier et ligne, sc\xE9nario d\u2019attaque, correctif. Pas de remarque sans sc\xE9nario concret."
4383
+ )
4384
+ },
4385
+ "correctness-reviewer": {
4386
+ label: "Relecteur exactitude",
4387
+ prompt: lines(
4388
+ "Cherche les bugs : logique fausse, erreurs non g\xE9r\xE9es, acc\xE8s concurrents, cas limites (vide, null, grandes entr\xE9es), r\xE9gressions du comportement existant.",
4389
+ "V\xE9rifie que les tests couvrent le comportement modifi\xE9 et \xE9choueraient sans le changement.",
4390
+ "Chaque remarque : fichier et ligne, l\u2019entr\xE9e qui le casse, le r\xE9sultat attendu et le r\xE9sultat obtenu."
4391
+ )
4392
+ },
4393
+ "maintainability-reviewer": {
4394
+ label: "Relecteur maintenabilit\xE9",
4395
+ prompt: lines(
4396
+ "Cherche la logique dupliqu\xE9e qui existe d\xE9j\xE0 ailleurs dans le code, les noms peu clairs, le code mort et les changements hors du p\xE9rim\xE8tre annonc\xE9.",
4397
+ "Cherche dans le d\xE9p\xF4t avant de parler de doublon, et nomme la fonction existante \xE0 r\xE9utiliser.",
4398
+ "Ne signale pas les pr\xE9f\xE9rences de style qu\u2019un linter rep\xE8re."
4399
+ )
4400
+ }
4401
+ }
4402
+ }
4403
+ };
4404
+
3943
4405
  // ../server/src/services/scenario-presets.ts
4406
+ var STAGE = { columnGap: 380, rowGap: 240, width: 300, height: 180, nodeX: 40, nodeY: 60 };
4407
+ function stage(id, name, column, row = 0, description) {
4408
+ return {
4409
+ id,
4410
+ name,
4411
+ description,
4412
+ position: { x: column * STAGE.columnGap, y: row * STAGE.rowGap },
4413
+ width: STAGE.width,
4414
+ height: STAGE.height
4415
+ };
4416
+ }
4417
+ function presetNode(fields) {
4418
+ return {
4419
+ type: "ai",
4420
+ parentIds: [],
4421
+ prompt: "",
4422
+ question: "",
4423
+ autoGenerated: false,
4424
+ canAddNode: false,
4425
+ aiCli: "claude-code",
4426
+ model: "",
4427
+ position: { x: STAGE.nodeX, y: STAGE.nodeY },
4428
+ injectParentOutputs: false,
4429
+ injectedAncestorIds: [],
4430
+ ...fields
4431
+ };
4432
+ }
4433
+ var lines2 = (...l) => l.join("\n");
4434
+ var PIPELINE_LABELS = {
4435
+ group: { en: "Stage", fr: "\xC9tape" },
4436
+ node: { en: "Agent", fr: "Agent" },
4437
+ role: { en: "Role", fr: "R\xF4le" },
4438
+ leader: { en: "Lead", fr: "Responsable" }
4439
+ };
4440
+ var ROLES = [
4441
+ {
4442
+ id: "manager",
4443
+ name: "Manager",
4444
+ systemPrompt: [
4445
+ "You are a MANAGER. Your only job is to coordinate, plan, and delegate.",
4446
+ "NEVER write code, scripts, or any technical artifact \u2014 not even as an example.",
4447
+ "NEVER answer a technical question directly \u2014 always assign it to the right person.",
4448
+ "Output only: task breakdowns, assignments, decisions, and synthesis."
4449
+ ].join("\n"),
4450
+ prompt: ""
4451
+ },
4452
+ {
4453
+ id: "engineer",
4454
+ name: "Engineer",
4455
+ systemPrompt: [
4456
+ "You are an ENGINEER. Write working, production-ready code.",
4457
+ "Always prefer real implementation over pseudocode or high-level descriptions.",
4458
+ "Be concise in prose; let the code speak.",
4459
+ "Output: source files, architecture decisions, technical specifications."
4460
+ ].join("\n"),
4461
+ prompt: ""
4462
+ },
4463
+ {
4464
+ id: "designer",
4465
+ name: "Designer",
4466
+ systemPrompt: [
4467
+ "You are a DESIGNER. Define UX flows, visual hierarchy, and interaction patterns.",
4468
+ "NEVER write code or CSS.",
4469
+ "Describe interfaces in structured text: component name, layout, states, behavior.",
4470
+ "Output: text wireframes, design decisions, component specs, UX guidelines."
4471
+ ].join("\n"),
4472
+ prompt: ""
4473
+ },
4474
+ {
4475
+ id: "analyst",
4476
+ name: "Analyst",
4477
+ systemPrompt: [
4478
+ "You are an ANALYST. Investigate data, identify patterns, and surface actionable insights.",
4479
+ "NEVER write code or scripts \u2014 if you need data processed, request it from an Engineer.",
4480
+ "Output: structured analysis, metrics, findings, and evidence-based recommendations."
4481
+ ].join("\n"),
4482
+ prompt: ""
4483
+ },
4484
+ {
4485
+ id: "qa",
4486
+ name: "QA",
4487
+ systemPrompt: [
4488
+ "You are a QA ENGINEER. Define what must be tested and how.",
4489
+ "NEVER write implementation code.",
4490
+ "You may write Gherkin / BDD scenarios or structured test cases as plain text.",
4491
+ "Output: test plans, test cases, edge cases, risk assessments, acceptance criteria."
4492
+ ].join("\n"),
4493
+ prompt: ""
4494
+ },
4495
+ {
4496
+ id: "devops",
4497
+ name: "DevOps",
4498
+ systemPrompt: [
4499
+ "You are a DEVOPS ENGINEER. Own infrastructure, deployment, and operations.",
4500
+ "Write actual scripts and configuration files (shell, YAML, HCL, Dockerfile\u2026) \u2014 no pseudocode.",
4501
+ "Output: scripts, CI/CD pipelines, infrastructure-as-code, runbooks."
4502
+ ].join("\n"),
4503
+ prompt: ""
4504
+ },
4505
+ {
4506
+ id: "product",
4507
+ name: "Product",
4508
+ systemPrompt: [
4509
+ "You are a PRODUCT MANAGER. Own requirements and priorities.",
4510
+ "NEVER write code or technical specifications.",
4511
+ "Output: PRDs, user stories with acceptance criteria, prioritization decisions, roadmap items."
4512
+ ].join("\n"),
4513
+ prompt: ""
4514
+ },
4515
+ {
4516
+ id: "writer",
4517
+ name: "Writer",
4518
+ systemPrompt: [
4519
+ "You are a TECHNICAL WRITER. Produce clear, accurate, well-structured written content.",
4520
+ "NEVER write code. If a code example is needed, flag it for an Engineer.",
4521
+ "Output: documentation, guides, release notes, changelogs, communication drafts."
4522
+ ].join("\n"),
4523
+ prompt: ""
4524
+ },
4525
+ {
4526
+ id: "researcher",
4527
+ name: "Researcher",
4528
+ systemPrompt: [
4529
+ "You are a RESEARCHER. Gather information, compare options, and synthesize knowledge into actionable insights.",
4530
+ "NEVER write code.",
4531
+ "Output: research summaries, comparisons, pros/cons analyses, evidence-based recommendations."
4532
+ ].join("\n"),
4533
+ prompt: ""
4534
+ },
4535
+ {
4536
+ id: "other",
4537
+ name: "Other",
4538
+ systemPrompt: "",
4539
+ prompt: ""
4540
+ }
4541
+ ];
4542
+ var COMPANY_ROLES = [
4543
+ {
4544
+ id: "director",
4545
+ name: "Director",
4546
+ systemPrompt: lines2(
4547
+ "You are the DIRECTOR of the company. You own the final result and you review everything.",
4548
+ "NEVER write code, plans or technical artifacts yourself. You delegate and you review.",
4549
+ "Step 1: send the request to the Planner only. No service receives work before the plan exists.",
4550
+ "Step 2: read the Planner report and the plan file it names. Dispatch each task to the lead of the service that owns it, quoting the plan file path and the task numbers. Contact only the services that have tasks.",
4551
+ "All services you name in one message run at the same time. To respect the plan dependencies, name in each round only the services whose tasks no longer wait for another task, as written in the plan. Build each round from the plan dependencies, not from a fixed order of services.",
4552
+ "Step 3: review each service report against the plan and its acceptance criteria. Send the work back to the service lead with the exact gap when a task is missing, wrong or untested.",
4553
+ "Stop only when every task of the plan is delivered and reviewed."
4554
+ ),
4555
+ prompt: ""
4556
+ },
4557
+ {
4558
+ id: "planner",
4559
+ name: "Planner",
4560
+ systemPrompt: lines2(
4561
+ "You are the PLANNER. You turn the request into a detailed, executable plan.",
4562
+ "NEVER write code. NEVER contact anyone: you have no direct reports and you answer only to the Director.",
4563
+ "Read the existing codebase first and base every task on what already exists (files, modules, conventions).",
4564
+ "Split the request into numbered tasks, each assigned to one service: Front, Back, Security, QA, Documentation or DevOps.",
4565
+ "Each task gives: goal, files concerned, dependencies on other tasks, acceptance criteria that can be checked.",
4566
+ "Write the plan to a markdown file and end your report with its exact path."
4567
+ ),
4568
+ prompt: ""
4569
+ },
4570
+ {
4571
+ id: "service-lead",
4572
+ name: "Service lead",
4573
+ systemPrompt: lines2(
4574
+ "You are the LEAD of a service. You receive a task from the Director.",
4575
+ "NEVER write code or produce the deliverable yourself. You split, assign and review.",
4576
+ "Split the task into sub-tasks and give each one to the right member of your service, with its acceptance criteria and the plan file path.",
4577
+ "Hire a temporary member only when no one in your service has the needed skill.",
4578
+ "Review every deliverable against the acceptance criteria: read the actual changes, not only the summary.",
4579
+ "If a deliverable does not meet the specification, send it back to the member with the precise gap.",
4580
+ "When everything is accepted, report to the Director: what was done, files changed, how it was checked, remaining risks."
4581
+ ),
4582
+ prompt: ""
4583
+ },
4584
+ ...ROLES.filter((r) => ["engineer", "designer", "qa", "devops", "writer"].includes(r.id)),
4585
+ {
4586
+ id: "architect",
4587
+ name: "Architect",
4588
+ systemPrompt: lines2(
4589
+ "You are a SOFTWARE ARCHITECT. You design module boundaries, APIs and data flows.",
4590
+ "Base every decision on the existing architecture and say which existing parts are reused.",
4591
+ "Output: API contracts, module layout, trade-offs, and the code skeleton when it removes ambiguity."
4592
+ ),
4593
+ prompt: ""
4594
+ },
4595
+ {
4596
+ id: "database",
4597
+ name: "Database expert",
4598
+ systemPrompt: lines2(
4599
+ "You are a DATABASE EXPERT. You own schemas, migrations, indexes and query performance.",
4600
+ "Write the actual migrations and queries. Every migration is reversible or says why not.",
4601
+ "Output: schema changes, migrations, indexes, and the impact on existing data."
4602
+ ),
4603
+ prompt: ""
4604
+ },
4605
+ {
4606
+ id: "security",
4607
+ name: "Security",
4608
+ systemPrompt: lines2(
4609
+ "You are a SECURITY ENGINEER. You find and fix vulnerabilities.",
4610
+ "Check input validation, injection, authentication, authorization, secrets and unsafe defaults.",
4611
+ "Each finding: file and line, attack scenario, fix. No finding without a concrete scenario."
4612
+ ),
4613
+ prompt: ""
4614
+ },
4615
+ ROLES.find((r) => r.id === "other")
4616
+ ];
4617
+ var SERVICE = { columnGap: 720, rowGap: 340, leadX: 40, leadY: 50, memberY: 170, memberGap: 210, height: 260 };
4618
+ function service(key, name, cell, description, lead, members) {
4619
+ const groupId = `service-${key}`;
4620
+ const leadId = `${key}-lead`;
4621
+ return {
4622
+ group: {
4623
+ id: groupId,
4624
+ name,
4625
+ description,
4626
+ position: { x: cell.column * SERVICE.columnGap, y: cell.row * SERVICE.rowGap },
4627
+ width: Math.max(STAGE.width, members.length * SERVICE.memberGap + 40),
4628
+ height: SERVICE.height
4629
+ },
4630
+ nodes: [
4631
+ presetNode({
4632
+ id: leadId,
4633
+ label: lead.label,
4634
+ role: "service-lead",
4635
+ groupId,
4636
+ parentIds: ["director"],
4637
+ canAddNode: true,
4638
+ prompt: lead.prompt,
4639
+ position: { x: SERVICE.leadX, y: SERVICE.leadY }
4640
+ }),
4641
+ ...members.map((m, i) => presetNode({
4642
+ id: m.id,
4643
+ label: m.label,
4644
+ role: m.role,
4645
+ groupId,
4646
+ parentIds: [leadId],
4647
+ prompt: m.prompt,
4648
+ position: { x: 20 + i * SERVICE.memberGap, y: SERVICE.memberY }
4649
+ }))
4650
+ ]
4651
+ };
4652
+ }
4653
+ var COMPANY_SERVICES = [
4654
+ service(
4655
+ "front",
4656
+ "Front",
4657
+ { column: 0, row: 1 },
4658
+ "User interface: screens, components, styles, accessibility.",
4659
+ { label: "Front Lead", prompt: "You lead the Front service. Your members build what the user sees and touches. Check that the result follows the existing components and design system." },
4660
+ [
4661
+ { id: "front-dev", label: "Front Developer", role: "engineer", prompt: "Implement screens and components in the existing front-end stack. Reuse the existing components and styles before creating new ones. Add component tests." },
4662
+ { id: "ui-designer", label: "UI/UX Designer", role: "designer", prompt: "Define the user flow, layout, states (empty, loading, error) and texts of each screen, consistent with the existing interface." },
4663
+ { id: "a11y-dev", label: "Accessibility Developer", role: "engineer", prompt: "Make the interface usable with keyboard and screen reader: names, focus order, contrast. Fix what fails, with a test when possible." }
4664
+ ]
4665
+ ),
4666
+ service(
4667
+ "back",
4668
+ "Back",
4669
+ { column: 1, row: 1 },
4670
+ "Server: APIs, business logic, data.",
4671
+ { label: "Back Lead", prompt: "You lead the Back service. Have the Architect validate the design before the developers start, and the Database expert review any schema change." },
4672
+ [
4673
+ { id: "architect", label: "Software Architect", role: "architect", prompt: "Design the API contract and module changes for the task, reusing the existing architecture. Hand a clear contract to the Back Developer." },
4674
+ { id: "db-expert", label: "Database Expert", role: "database", prompt: "Write the schema changes and migrations for the task, with indexes for the new queries. Check the impact on existing data." },
4675
+ { id: "back-dev", label: "Back Developer", role: "engineer", prompt: "Implement the API and business logic following the Architect contract. Validate every input. Add unit and integration tests." }
4676
+ ]
4677
+ ),
4678
+ service(
4679
+ "security",
4680
+ "Security",
4681
+ { column: 2, row: 1 },
4682
+ "Audit and hardening of what is built.",
4683
+ { label: "Security Lead", prompt: "You lead the Security service. Audit the changes produced by the other services for the tasks the Director gives you." },
4684
+ [
4685
+ { id: "security-auditor", label: "Security Auditor", role: "security", prompt: "Audit the changed code: validation, injection, authentication, authorization, secrets. Report each issue with its attack scenario." },
4686
+ { id: "security-engineer", label: "Security Engineer", role: "security", prompt: "Fix the vulnerabilities found by the audit at their source, with a test that proves the fix." }
4687
+ ]
4688
+ ),
4689
+ service(
4690
+ "qa",
4691
+ "QA",
4692
+ { column: 0, row: 2 },
4693
+ "Tests and validation against acceptance criteria.",
4694
+ { label: "QA Lead", prompt: "You lead the QA service. Every acceptance criterion of the plan must end up tested or explicitly marked untested with the reason." },
4695
+ [
4696
+ { id: "test-engineer", label: "Test Engineer", role: "qa", prompt: "Write the test plan for the task: one case per acceptance criterion, plus edge cases and error cases." },
4697
+ { id: "automation-engineer", label: "Test Automation Engineer", role: "engineer", prompt: "Automate the test plan in the existing test framework. Tests must fail without the feature and run fast. Report the command and its result." }
4698
+ ]
4699
+ ),
4700
+ service(
4701
+ "docs",
4702
+ "Documentation",
4703
+ { column: 1, row: 2 },
4704
+ "User and developer documentation.",
4705
+ { label: "Docs Lead", prompt: "You lead the Documentation service. Documentation describes what was actually built, checked against the delivered code." },
4706
+ [
4707
+ { id: "tech-writer", label: "Technical Writer", role: "writer", prompt: "Update the developer documentation for the changes: APIs, configuration, architecture notes. Plain language, concrete examples." },
4708
+ { id: "user-writer", label: "User Guide Writer", role: "writer", prompt: "Write the user-facing documentation and release note: what changes for the user and how to use it." }
4709
+ ]
4710
+ ),
4711
+ service(
4712
+ "devops",
4713
+ "DevOps",
4714
+ { column: 2, row: 2 },
4715
+ "Build, CI, deployment and monitoring.",
4716
+ { label: "DevOps Lead", prompt: "You lead the DevOps service. Make sure the delivered work builds, passes CI and can be deployed and monitored." },
4717
+ [
4718
+ { id: "devops-engineer", label: "DevOps Engineer", role: "devops", prompt: "Update build, CI and deployment configuration needed by the task. Write the actual files, no pseudocode." },
4719
+ { id: "sre", label: "Site Reliability Engineer", role: "devops", prompt: "Add the logs, metrics and alerts needed to run the new feature, and a short runbook for its failure cases." }
4720
+ ]
4721
+ )
4722
+ ];
3944
4723
  var BUILT_IN_PRESETS = [
3945
4724
  {
3946
4725
  id: "enterprise",
3947
- name: "Enterprise",
4726
+ name: "Empty company",
3948
4727
  icon: "ti-building",
3949
4728
  labels: {
3950
4729
  group: { en: "Department", fr: "D\xE9partement" },
@@ -3960,125 +4739,390 @@ var BUILT_IN_PRESETS = [
3960
4739
  { id: "group-management", name: "Management", position: { x: 0, y: 0 }, width: 300, height: 200 }
3961
4740
  ],
3962
4741
  nodes: [
3963
- {
4742
+ presetNode({
3964
4743
  id: "leader",
3965
- type: "ai",
3966
- parentIds: [],
3967
- groupId: "group-management",
3968
4744
  label: "Leader One",
3969
4745
  role: "manager",
4746
+ groupId: "group-management",
3970
4747
  prompt: "Analyze the objective. Break it into concrete tasks and assign each to the right team member with a clear expected output. Do not do the technical work yourself.",
3971
- question: "",
3972
- autoGenerated: false,
3973
- canAddNode: false,
3974
- aiCli: "claude-code",
3975
- model: "sonnet",
3976
4748
  position: { x: 50, y: 50 }
3977
- }
4749
+ })
3978
4750
  ]
3979
4751
  },
3980
- roles: [
3981
- {
3982
- id: "manager",
3983
- name: "Manager",
3984
- systemPrompt: [
3985
- "You are a MANAGER. Your only job is to coordinate, plan, and delegate.",
3986
- "NEVER write code, scripts, or any technical artifact \u2014 not even as an example.",
3987
- "NEVER answer a technical question directly \u2014 always assign it to the right person.",
3988
- "Output only: task breakdowns, assignments, decisions, and synthesis."
3989
- ].join("\n"),
3990
- prompt: ""
3991
- },
3992
- {
3993
- id: "engineer",
3994
- name: "Engineer",
3995
- systemPrompt: [
3996
- "You are an ENGINEER. Write working, production-ready code.",
3997
- "Always prefer real implementation over pseudocode or high-level descriptions.",
3998
- "Be concise in prose; let the code speak.",
3999
- "Output: source files, architecture decisions, technical specifications."
4000
- ].join("\n"),
4001
- prompt: ""
4002
- },
4003
- {
4004
- id: "designer",
4005
- name: "Designer",
4006
- systemPrompt: [
4007
- "You are a DESIGNER. Define UX flows, visual hierarchy, and interaction patterns.",
4008
- "NEVER write code or CSS.",
4009
- "Describe interfaces in structured text: component name, layout, states, behavior.",
4010
- "Output: text wireframes, design decisions, component specs, UX guidelines."
4011
- ].join("\n"),
4012
- prompt: ""
4013
- },
4014
- {
4015
- id: "analyst",
4016
- name: "Analyst",
4017
- systemPrompt: [
4018
- "You are an ANALYST. Investigate data, identify patterns, and surface actionable insights.",
4019
- "NEVER write code or scripts \u2014 if you need data processed, request it from an Engineer.",
4020
- "Output: structured analysis, metrics, findings, and evidence-based recommendations."
4021
- ].join("\n"),
4022
- prompt: ""
4023
- },
4024
- {
4025
- id: "qa",
4026
- name: "QA",
4027
- systemPrompt: [
4028
- "You are a QA ENGINEER. Define what must be tested and how.",
4029
- "NEVER write implementation code.",
4030
- "You may write Gherkin / BDD scenarios or structured test cases as plain text.",
4031
- "Output: test plans, test cases, edge cases, risk assessments, acceptance criteria."
4032
- ].join("\n"),
4033
- prompt: ""
4034
- },
4035
- {
4036
- id: "devops",
4037
- name: "DevOps",
4038
- systemPrompt: [
4039
- "You are a DEVOPS ENGINEER. Own infrastructure, deployment, and operations.",
4040
- "Write actual scripts and configuration files (shell, YAML, HCL, Dockerfile\u2026) \u2014 no pseudocode.",
4041
- "Output: scripts, CI/CD pipelines, infrastructure-as-code, runbooks."
4042
- ].join("\n"),
4043
- prompt: ""
4044
- },
4045
- {
4046
- id: "product",
4047
- name: "Product",
4048
- systemPrompt: [
4049
- "You are a PRODUCT MANAGER. Own requirements and priorities.",
4050
- "NEVER write code or technical specifications.",
4051
- "Output: PRDs, user stories with acceptance criteria, prioritization decisions, roadmap items."
4052
- ].join("\n"),
4053
- prompt: ""
4054
- },
4055
- {
4056
- id: "writer",
4057
- name: "Writer",
4058
- systemPrompt: [
4059
- "You are a TECHNICAL WRITER. Produce clear, accurate, well-structured written content.",
4060
- "NEVER write code. If a code example is needed, flag it for an Engineer.",
4061
- "Output: documentation, guides, release notes, changelogs, communication drafts."
4062
- ].join("\n"),
4063
- prompt: ""
4064
- },
4065
- {
4066
- id: "researcher",
4067
- name: "Researcher",
4068
- systemPrompt: [
4069
- "You are a RESEARCHER. Gather information, compare options, and synthesize knowledge into actionable insights.",
4070
- "NEVER write code.",
4071
- "Output: research summaries, comparisons, pros/cons analyses, evidence-based recommendations."
4072
- ].join("\n"),
4073
- prompt: ""
4074
- },
4075
- {
4076
- id: "other",
4077
- name: "Other",
4078
- systemPrompt: "",
4079
- prompt: ""
4080
- }
4081
- ]
4752
+ translations: { fr: { ...PRESET_FR["enterprise"], roles: ROLES_FR } },
4753
+ roles: ROLES
4754
+ },
4755
+ {
4756
+ id: "company",
4757
+ name: "Company",
4758
+ icon: "ti-sitemap",
4759
+ labels: {
4760
+ group: { en: "Service", fr: "Service" },
4761
+ node: { en: "Employee", fr: "Employ\xE9" },
4762
+ role: { en: "Position", fr: "Poste" },
4763
+ leader: { en: "Director", fr: "Directeur" }
4764
+ },
4765
+ defaultTraversalMode: "hierarchical",
4766
+ canChangeTraversalMode: false,
4767
+ initialData: {
4768
+ leaderId: "director",
4769
+ groups: [
4770
+ { id: "service-direction", name: "Direction", description: "Owns the result and reviews every delivery.", position: { x: 0, y: 0 }, width: STAGE.width, height: STAGE.height },
4771
+ { id: "service-planning", name: "Planning", description: "Turns the request into a written plan, task by task.", position: { x: SERVICE.columnGap, y: 0 }, width: STAGE.width, height: STAGE.height },
4772
+ ...COMPANY_SERVICES.map((sv) => sv.group)
4773
+ ],
4774
+ nodes: [
4775
+ presetNode({
4776
+ id: "director",
4777
+ label: "Director",
4778
+ role: "director",
4779
+ groupId: "service-direction",
4780
+ prompt: lines2(
4781
+ "First, contact only the Planner and ask for a detailed plan of the request.",
4782
+ "Once the plan is back, dispatch its tasks to the service leads (Front, Back, Security, QA, Documentation, DevOps), each with the plan file path and its task numbers.",
4783
+ "Review each service report. Send back what does not meet the plan. Your final synthesis lists every task with its status and evidence."
4784
+ )
4785
+ }),
4786
+ presetNode({
4787
+ id: "planner",
4788
+ label: "Planner",
4789
+ role: "planner",
4790
+ groupId: "service-planning",
4791
+ parentIds: ["director"],
4792
+ prompt: lines2(
4793
+ "Explore the codebase, then write a detailed plan: numbered tasks, owning service, files, dependencies, acceptance criteria.",
4794
+ "Save it as a markdown file (for example plan-<topic>.md in the working directory, unless the request names another place).",
4795
+ 'Your report to the Director summarizes the tasks by service and ends with: "Plan file: <exact path>".'
4796
+ )
4797
+ }),
4798
+ ...COMPANY_SERVICES.flatMap((sv) => sv.nodes)
4799
+ ]
4800
+ },
4801
+ translations: { fr: { ...PRESET_FR["company"], roles: ROLES_FR } },
4802
+ roles: COMPANY_ROLES
4803
+ },
4804
+ {
4805
+ id: "feature-delivery",
4806
+ name: "Feature delivery",
4807
+ icon: "ti-send",
4808
+ labels: PIPELINE_LABELS,
4809
+ defaultTraversalMode: "topological",
4810
+ canChangeTraversalMode: true,
4811
+ initialData: {
4812
+ leaderId: "lead",
4813
+ groups: [
4814
+ stage("stage-framing", "Framing", 0),
4815
+ stage("stage-design", "Design", 1),
4816
+ stage("stage-build", "Build", 2),
4817
+ stage("stage-verify", "Verify", 3, 0),
4818
+ stage("stage-docs", "Docs", 3, 1)
4819
+ ],
4820
+ nodes: [
4821
+ presetNode({
4822
+ id: "lead",
4823
+ label: "Product Lead",
4824
+ role: "product",
4825
+ groupId: "stage-framing",
4826
+ prompt: lines2(
4827
+ "First pass (kickoff): restate the feature in two sentences, then write numbered user stories with testable acceptance criteria.",
4828
+ "List what is explicitly out of scope and the open questions, each with the assumption you take to move forward.",
4829
+ "Final pass (synthesis): check each acceptance criterion against the outputs you receive and mark it met, partially met or not met with the evidence.",
4830
+ "End with the list of remaining risks and the next actions, by owner."
4831
+ )
4832
+ }),
4833
+ presetNode({
4834
+ id: "architect",
4835
+ label: "Architect",
4836
+ role: "engineer",
4837
+ groupId: "stage-design",
4838
+ parentIds: ["lead"],
4839
+ prompt: lines2(
4840
+ "Turn the user stories into a technical plan before any code is written.",
4841
+ "Explore the codebase first: name the existing files, modules and helpers to reuse, and where the new code goes.",
4842
+ "Give the data model changes, the API contract (inputs, outputs, errors) and the ordered list of implementation steps.",
4843
+ "Flag every breaking change and migration. Keep the plan small enough for one implementation pass."
4844
+ )
4845
+ }),
4846
+ presetNode({
4847
+ id: "developer",
4848
+ label: "Developer",
4849
+ role: "engineer",
4850
+ groupId: "stage-build",
4851
+ parentIds: ["architect"],
4852
+ injectedAncestorIds: ["lead"],
4853
+ prompt: lines2(
4854
+ "Implement the plan from the Architect step by step, in the repository.",
4855
+ "Reuse what the plan points to instead of writing new helpers. Add or update tests for each acceptance criterion.",
4856
+ "Run the relevant tests and report the command and its result.",
4857
+ "Output: the list of changed files with one line each, the test results, and any deviation from the plan with its reason."
4858
+ )
4859
+ }),
4860
+ presetNode({
4861
+ id: "qa",
4862
+ label: "QA Reviewer",
4863
+ role: "qa",
4864
+ groupId: "stage-verify",
4865
+ parentIds: ["developer"],
4866
+ injectedAncestorIds: ["lead"],
4867
+ prompt: lines2(
4868
+ "Review the implementation against each acceptance criterion from the Product Lead.",
4869
+ "Read the actual diff, not only the summary. Look for regressions, missing edge cases, missing tests and error handling gaps.",
4870
+ "Output a table: criterion, status (pass / fail / untested), evidence. Then the list of defects ordered by severity, each with a reproduction."
4871
+ )
4872
+ }),
4873
+ presetNode({
4874
+ id: "writer",
4875
+ label: "Docs Writer",
4876
+ role: "writer",
4877
+ groupId: "stage-docs",
4878
+ parentIds: ["developer"],
4879
+ injectedAncestorIds: ["lead"],
4880
+ prompt: lines2(
4881
+ "Write what a user needs to use the new feature: a short release note and the documentation update.",
4882
+ "Base it on what was actually built (Developer output), not on the initial plan.",
4883
+ "Plain language, one idea per sentence, a concrete example. Say where each piece of documentation goes."
4884
+ )
4885
+ })
4886
+ ]
4887
+ },
4888
+ translations: { fr: { ...PRESET_FR["feature-delivery"], roles: ROLES_FR } },
4889
+ roles: ROLES
4890
+ },
4891
+ {
4892
+ id: "bug-investigation",
4893
+ name: "Bug investigation",
4894
+ icon: "ti-alert-triangle",
4895
+ labels: PIPELINE_LABELS,
4896
+ defaultTraversalMode: "topological",
4897
+ canChangeTraversalMode: true,
4898
+ initialData: {
4899
+ leaderId: "triage",
4900
+ groups: [
4901
+ stage("stage-triage", "Triage", 0),
4902
+ stage("stage-repro", "Reproduction", 1),
4903
+ stage("stage-root-cause", "Root cause", 2),
4904
+ stage("stage-fix", "Fix", 3),
4905
+ stage("stage-check", "Verification", 4)
4906
+ ],
4907
+ nodes: [
4908
+ presetNode({
4909
+ id: "triage",
4910
+ label: "Triage Lead",
4911
+ role: "manager",
4912
+ groupId: "stage-triage",
4913
+ prompt: lines2(
4914
+ "First pass (kickoff): summarize the reported symptom, the expected behaviour and the impact (who is affected, how often).",
4915
+ "List the facts you have and the information that is missing.",
4916
+ "Final pass (synthesis): state the root cause, the fix, how it was verified and whether a follow-up is needed. Keep it short enough to paste in a ticket."
4917
+ )
4918
+ }),
4919
+ presetNode({
4920
+ id: "context",
4921
+ label: "Reporter details",
4922
+ role: "other",
4923
+ groupId: "stage-repro",
4924
+ parentIds: ["triage"],
4925
+ type: "ask",
4926
+ question: "Give the exact steps to reproduce, the environment (version, OS, browser) and any error message or log you have."
4927
+ }),
4928
+ presetNode({
4929
+ id: "investigator",
4930
+ label: "Investigator",
4931
+ role: "analyst",
4932
+ groupId: "stage-root-cause",
4933
+ parentIds: ["context"],
4934
+ injectedAncestorIds: ["triage"],
4935
+ prompt: lines2(
4936
+ "Find the root cause, not the first suspicious line.",
4937
+ "Follow the code path from the entry point named in the reproduction steps to the failure. Read logs and recent changes (git log) on that path.",
4938
+ "Output: the root cause with file and line, the chain of events that leads to the symptom, and the evidence for each link.",
4939
+ "If two causes remain possible, say how to tell them apart."
4940
+ )
4941
+ }),
4942
+ presetNode({
4943
+ id: "fixer",
4944
+ label: "Fixer",
4945
+ role: "engineer",
4946
+ groupId: "stage-fix",
4947
+ parentIds: ["investigator"],
4948
+ injectedAncestorIds: ["context"],
4949
+ prompt: lines2(
4950
+ "Write a test that reproduces the bug and check that it fails for the reason found by the Investigator.",
4951
+ "Then fix the cause at its source, with the smallest change that makes the test pass. Do not silence the error.",
4952
+ "Output: the test, the diff summary, and the test command with its result before and after the fix."
4953
+ )
4954
+ }),
4955
+ presetNode({
4956
+ id: "verifier",
4957
+ label: "Verifier",
4958
+ role: "qa",
4959
+ groupId: "stage-check",
4960
+ parentIds: ["fixer"],
4961
+ injectedAncestorIds: ["context", "investigator"],
4962
+ prompt: lines2(
4963
+ "Check that the fix removes the symptom with the original reproduction steps.",
4964
+ "Look for the same faulty pattern elsewhere in the codebase, and for behaviour the fix may have changed.",
4965
+ "Output: verdict (fixed / not fixed / partially fixed), evidence, other places with the same pattern."
4966
+ )
4967
+ })
4968
+ ]
4969
+ },
4970
+ translations: { fr: { ...PRESET_FR["bug-investigation"], roles: ROLES_FR } },
4971
+ roles: ROLES
4972
+ },
4973
+ {
4974
+ id: "research-report",
4975
+ name: "Research report",
4976
+ icon: "ti-book",
4977
+ labels: PIPELINE_LABELS,
4978
+ defaultTraversalMode: "topological",
4979
+ canChangeTraversalMode: true,
4980
+ initialData: {
4981
+ leaderId: "editor",
4982
+ groups: [
4983
+ stage("stage-scope", "Scope", 0),
4984
+ stage("stage-sources", "Sources", 1, 0),
4985
+ stage("stage-options", "Options", 1, 1),
4986
+ stage("stage-analysis", "Analysis", 2),
4987
+ stage("stage-report", "Report", 3)
4988
+ ],
4989
+ nodes: [
4990
+ presetNode({
4991
+ id: "editor",
4992
+ label: "Research Lead",
4993
+ role: "manager",
4994
+ groupId: "stage-scope",
4995
+ prompt: lines2(
4996
+ "First pass (kickoff): turn the request into three to five precise research questions and the criteria a good answer must meet.",
4997
+ "Say what decision the report must help make, and for whom.",
4998
+ "Final pass (synthesis): give the answer to the decision in the first paragraph, then check that each research question is answered."
4999
+ )
5000
+ }),
5001
+ presetNode({
5002
+ id: "fact-finder",
5003
+ label: "Fact Finder",
5004
+ role: "researcher",
5005
+ groupId: "stage-sources",
5006
+ parentIds: ["editor"],
5007
+ prompt: lines2(
5008
+ "Answer the research questions with facts and figures.",
5009
+ "Every claim comes with its source and its date. Mark what is a fact, an estimate or an opinion.",
5010
+ "Prefer primary sources (official docs, data, papers) over articles that quote them."
5011
+ )
5012
+ }),
5013
+ presetNode({
5014
+ id: "options-scout",
5015
+ label: "Options Scout",
5016
+ role: "researcher",
5017
+ groupId: "stage-options",
5018
+ parentIds: ["editor"],
5019
+ prompt: lines2(
5020
+ "List the realistic options or solutions for the decision at stake, including doing nothing.",
5021
+ "For each one: what it is, who uses it, its cost, its main limits. Stay factual and cite sources."
5022
+ )
5023
+ }),
5024
+ presetNode({
5025
+ id: "analyst",
5026
+ label: "Analyst",
5027
+ role: "analyst",
5028
+ groupId: "stage-analysis",
5029
+ parentIds: ["fact-finder", "options-scout"],
5030
+ injectedAncestorIds: ["editor"],
5031
+ prompt: lines2(
5032
+ "Compare the options against the criteria set by the Research Lead, using the facts gathered.",
5033
+ "Give a comparison table, then a recommendation with the conditions under which it would change.",
5034
+ "Point out contradictions between sources and claims that lack evidence."
5035
+ )
5036
+ }),
5037
+ presetNode({
5038
+ id: "report-writer",
5039
+ label: "Report Writer",
5040
+ role: "writer",
5041
+ groupId: "stage-report",
5042
+ parentIds: ["analyst"],
5043
+ injectedAncestorIds: ["fact-finder"],
5044
+ prompt: lines2(
5045
+ "Write the final report for the audience named by the Research Lead.",
5046
+ "Structure: recommendation, key findings, comparison, risks, sources. Short sections, plain language.",
5047
+ "Keep every source reference from the Fact Finder."
5048
+ )
5049
+ })
5050
+ ]
5051
+ },
5052
+ translations: { fr: { ...PRESET_FR["research-report"], roles: ROLES_FR } },
5053
+ roles: ROLES
5054
+ },
5055
+ {
5056
+ id: "code-review",
5057
+ name: "Code review",
5058
+ icon: "ti-code",
5059
+ labels: {
5060
+ group: { en: "Team", fr: "\xC9quipe" },
5061
+ node: { en: "Reviewer", fr: "Relecteur" },
5062
+ role: { en: "Focus", fr: "Angle" },
5063
+ leader: { en: "Lead reviewer", fr: "Relecteur principal" }
5064
+ },
5065
+ defaultTraversalMode: "hierarchical",
5066
+ canChangeTraversalMode: true,
5067
+ initialData: {
5068
+ leaderId: "lead-reviewer",
5069
+ groups: [
5070
+ stage("team-lead", "Lead", 0),
5071
+ stage("team-security", "Security", 1, 0),
5072
+ stage("team-correctness", "Correctness", 1, 1),
5073
+ stage("team-maintainability", "Maintainability", 1, 2)
5074
+ ],
5075
+ nodes: [
5076
+ presetNode({
5077
+ id: "lead-reviewer",
5078
+ label: "Lead Reviewer",
5079
+ role: "manager",
5080
+ groupId: "team-lead",
5081
+ prompt: lines2(
5082
+ "Identify the change to review (branch, diff or files named in the request) and summarize its intent in two sentences.",
5083
+ "Send each reviewer the exact scope to read and the risks specific to this change.",
5084
+ "In your synthesis, merge duplicate findings, drop the ones without evidence, and order the rest by severity: blocking, should fix, nit."
5085
+ )
5086
+ }),
5087
+ presetNode({
5088
+ id: "security-reviewer",
5089
+ label: "Security Reviewer",
5090
+ role: "qa",
5091
+ groupId: "team-security",
5092
+ parentIds: ["lead-reviewer"],
5093
+ prompt: lines2(
5094
+ "Review the change for security issues only: input validation, injection, authentication and authorization, secrets, unsafe defaults.",
5095
+ "Each finding: file and line, the attack scenario, the fix. No finding without a concrete scenario."
5096
+ )
5097
+ }),
5098
+ presetNode({
5099
+ id: "correctness-reviewer",
5100
+ label: "Correctness Reviewer",
5101
+ role: "qa",
5102
+ groupId: "team-correctness",
5103
+ parentIds: ["lead-reviewer"],
5104
+ prompt: lines2(
5105
+ "Look for bugs: wrong logic, unhandled errors, race conditions, edge cases (empty, null, large inputs), regressions in existing behaviour.",
5106
+ "Check that tests cover the changed behaviour and would fail without the change.",
5107
+ "Each finding: file and line, the input that breaks it, the expected and actual result."
5108
+ )
5109
+ }),
5110
+ presetNode({
5111
+ id: "maintainability-reviewer",
5112
+ label: "Maintainability Reviewer",
5113
+ role: "engineer",
5114
+ groupId: "team-maintainability",
5115
+ parentIds: ["lead-reviewer"],
5116
+ prompt: lines2(
5117
+ "Look for duplicated logic that already exists elsewhere in the codebase, unclear naming, dead code and changes outside the stated scope.",
5118
+ "Search the repository before claiming a duplicate, and name the existing function to reuse.",
5119
+ "Do not report style preferences that a linter would catch."
5120
+ )
5121
+ })
5122
+ ]
5123
+ },
5124
+ translations: { fr: { ...PRESET_FR["code-review"], roles: ROLES_FR } },
5125
+ roles: ROLES
4082
5126
  }
4083
5127
  ];
4084
5128
  function listPresets() {
@@ -4087,12 +5131,13 @@ function listPresets() {
4087
5131
  function getPreset(id) {
4088
5132
  return BUILT_IN_PRESETS.find((p) => p.id === id);
4089
5133
  }
5134
+ function getPresetRole(presetId, roleId, locale) {
5135
+ const preset = presetId ? getPreset(presetId) : void 0;
5136
+ if (!preset) return void 0;
5137
+ return (locale ? localizePreset(preset, locale) : preset).roles.find((r) => r.id === roleId);
5138
+ }
4090
5139
 
4091
5140
  // ../server/src/services/scenario-runner.ts
4092
- var DEFAULT_NODE_MODELS = {
4093
- "claude-code": "sonnet",
4094
- codex: ""
4095
- };
4096
5141
  var MAX_BUFFER = 500;
4097
5142
  var activeBuses = /* @__PURE__ */ new Map();
4098
5143
  var activeAbortControllers = /* @__PURE__ */ new Map();
@@ -4421,27 +5466,26 @@ function buildSystemPrompt(node, scenario) {
4421
5466
  const group = scenario.groups.find((t) => t.id === node.groupId);
4422
5467
  const manager = node.parentIds[0] ? scenario.nodes.find((p) => p.id === node.parentIds[0]) : null;
4423
5468
  const reports = getDirectReports(scenario.nodes, node.id);
4424
- const preset = scenario.presetId ? getPreset(scenario.presetId) : void 0;
4425
- const presetRole = preset?.roles.find((r) => r.id === (node.role ?? "other"));
5469
+ const presetRole = getPresetRole(scenario.presetId, node.role ?? "other", scenario.locale);
4426
5470
  const roleBehavior = presetRole?.systemPrompt ?? "";
4427
5471
  const rolePrompt = presetRole?.prompt ?? "";
4428
- const lines = [
5472
+ const lines3 = [
4429
5473
  `You are ${node.label}${group ? `, member of the ${group.name} group` : ""}.`,
4430
5474
  `Your role type: **${(node.role ?? "other").toUpperCase()}**.`,
4431
5475
  ""
4432
5476
  ];
4433
5477
  if (roleBehavior) {
4434
- lines.push("## Role Behavior (strictly enforce)", roleBehavior, "");
5478
+ lines3.push("## Role Behavior (strictly enforce)", roleBehavior, "");
4435
5479
  }
4436
5480
  const profileSection = [node.prompt, rolePrompt].filter(Boolean).join("\n\n");
4437
- lines.push("## Your Profile & Instructions", profileSection || "(No profile provided)", "");
5481
+ lines3.push("## Your Profile & Instructions", profileSection || "(No profile provided)", "");
4438
5482
  if (manager) {
4439
- lines.push(`## Reporting Line`, `You report to ${manager.label} (${manager.role ?? "other"}).`, "");
5483
+ lines3.push(`## Reporting Line`, `You report to ${manager.label} (${manager.role ?? "other"}).`, "");
4440
5484
  } else {
4441
- lines.push(`## Position`, `You are the leader of this scenario. You coordinate all groups.`, "");
5485
+ lines3.push(`## Position`, `You are the leader of this scenario. You coordinate all groups.`, "");
4442
5486
  }
4443
5487
  if (reports.length > 0) {
4444
- lines.push(
5488
+ lines3.push(
4445
5489
  `## Your Direct Reports`,
4446
5490
  ...reports.map((r) => {
4447
5491
  const rGroup = scenario.groups.find((g) => g.id === r.groupId);
@@ -4452,7 +5496,7 @@ function buildSystemPrompt(node, scenario) {
4452
5496
  );
4453
5497
  }
4454
5498
  if (node.canAddNode) {
4455
- lines.push(
5499
+ lines3.push(
4456
5500
  "## Hiring Capability",
4457
5501
  "You are allowed to hire temporary contractors for this run.",
4458
5502
  'Use exactly: <hire_person label="Jane Doe" role="engineer">Task focus prompt</hire_person>',
@@ -4461,7 +5505,7 @@ function buildSystemPrompt(node, scenario) {
4461
5505
  ""
4462
5506
  );
4463
5507
  }
4464
- lines.push(
5508
+ lines3.push(
4465
5509
  "## Output Instructions",
4466
5510
  "Write your output clearly and in a structured format.",
4467
5511
  "Stay strictly within your role \u2014 do not produce deliverables that belong to a different role.",
@@ -4470,9 +5514,9 @@ function buildSystemPrompt(node, scenario) {
4470
5514
  );
4471
5515
  const runeya_ai_vars = Object.entries(process.env).filter(([k]) => k.startsWith("RUNEYA_AI_")).map(([k, v]) => `${k}=${v}`).join("\n");
4472
5516
  if (runeya_ai_vars) {
4473
- lines.push("", "## Environment", "", runeya_ai_vars);
5517
+ lines3.push("", "## Environment", "", runeya_ai_vars);
4474
5518
  }
4475
- return lines.join("\n");
5519
+ return lines3.join("\n");
4476
5520
  }
4477
5521
  function buildUserMessage(node, scenario, userRequest, managerOutput, isLeaderSynthesis, isLeaderDispatch, allOutputs) {
4478
5522
  const parts = [];
@@ -4596,7 +5640,7 @@ function resolveNodeExecutionConfig(node, runOverrides) {
4596
5640
  const crossFamily = !!runOverrides?.runnerOverride && runOverrides.runnerOverride !== baseCli;
4597
5641
  const modelOverride = runOverrides?.modelOverride?.trim() ?? "";
4598
5642
  const nodeModel = node.model?.trim() ?? "";
4599
- const model = modelOverride || (crossFamily ? DEFAULT_NODE_MODELS[aiCli] : nodeModel || DEFAULT_NODE_MODELS[aiCli]);
5643
+ const model = modelOverride || (crossFamily ? "" : nodeModel);
4600
5644
  return { aiCli, model };
4601
5645
  }
4602
5646
  function createNodeRunnerState(aiCli) {
@@ -4614,8 +5658,8 @@ async function nodeRuneyaAccess(conversationId) {
4614
5658
  let injectedEnv;
4615
5659
  if (ref?.id) {
4616
5660
  try {
4617
- const { projectStore: projectStore2 } = await import("./project-store-FLXTAD3J.js");
4618
- const { environmentResolver: environmentResolver2 } = await import("./environment-resolver-ZDTF3MHI.js");
5661
+ const { projectStore: projectStore2 } = await import("./project-store-BYAE4SVZ.js");
5662
+ const { environmentResolver: environmentResolver2 } = await import("./environment-resolver-SY36Q67E.js");
4619
5663
  const project = await projectStore2.get(ref.orgId ? { id: ref.id, orgId: ref.orgId } : ref.id);
4620
5664
  if (project?.activeEnvironmentId) {
4621
5665
  const injected = await environmentResolver2.resolveAiInjectedEnv(project.activeEnvironmentId);
@@ -5490,6 +6534,7 @@ var scenarioRouter = router({
5490
6534
  nodes: z16.array(ScenarioNodeSchema).min(1).max(500),
5491
6535
  traversalMode: z16.enum(["hierarchical", "topological"]).optional(),
5492
6536
  presetId: z16.string().max(128).optional(),
6537
+ locale: z16.string().max(16).optional(),
5493
6538
  isPublished: z16.boolean().optional(),
5494
6539
  ...ScopeShape2
5495
6540
  })).mutation(({ input }) => {
@@ -5504,6 +6549,7 @@ var scenarioRouter = router({
5504
6549
  nodes: input.nodes,
5505
6550
  traversalMode: input.traversalMode ?? "hierarchical",
5506
6551
  presetId: input.presetId,
6552
+ locale: input.locale,
5507
6553
  isPublished: input.isPublished ?? false,
5508
6554
  createdAt: now,
5509
6555
  updatedAt: now
@@ -5519,6 +6565,7 @@ var scenarioRouter = router({
5519
6565
  nodes: z16.array(ScenarioNodeSchema).min(1).max(500).optional(),
5520
6566
  traversalMode: z16.enum(["hierarchical", "topological"]).optional(),
5521
6567
  presetId: z16.string().max(128).optional(),
6568
+ locale: z16.string().max(16).optional(),
5522
6569
  isPublished: z16.boolean().optional(),
5523
6570
  ...ScopeShape2
5524
6571
  })).mutation(({ input }) => updateOrThrow(
@@ -5531,6 +6578,7 @@ var scenarioRouter = router({
5531
6578
  nodes: input.nodes,
5532
6579
  traversalMode: input.traversalMode,
5533
6580
  presetId: input.presetId,
6581
+ locale: input.locale,
5534
6582
  isPublished: input.isPublished,
5535
6583
  updatedAt: Date.now()
5536
6584
  }, await scopeOf2(input)),
@@ -6124,7 +7172,7 @@ import { TRPCError as TRPCError18 } from "@trpc/server";
6124
7172
 
6125
7173
  // ../server/src/services/ai-client-mcp.ts
6126
7174
  import { execFile as execFile4 } from "child_process";
6127
- import { existsSync as existsSync2 } from "fs";
7175
+ import { existsSync as existsSync2, readdirSync } from "fs";
6128
7176
  import { mkdir as mkdir5, readFile as readFile4, realpath } from "fs/promises";
6129
7177
  import { homedir as homedir3 } from "os";
6130
7178
  import { dirname as dirname4, join as join7 } from "path";
@@ -6145,9 +7193,21 @@ function vscodeUserDir(home) {
6145
7193
  if (process.platform === "win32") return join7(process.env["APPDATA"] ?? join7(home, "AppData", "Roaming"), "Code", "User");
6146
7194
  return join7(home, ".config", "Code", "User");
6147
7195
  }
6148
- function claudeDesktopDir(home) {
6149
- if (process.platform === "darwin") return join7(home, "Library", "Application Support", "Claude");
6150
- if (process.platform === "win32") return join7(process.env["APPDATA"] ?? join7(home, "AppData", "Roaming"), "Claude");
7196
+ function listDir(dir) {
7197
+ try {
7198
+ return readdirSync(dir);
7199
+ } catch {
7200
+ return [];
7201
+ }
7202
+ }
7203
+ function claudeDesktopDir(home, platform = process.platform, vars = process.env, exists4 = existsSync2, list = listDir) {
7204
+ if (platform === "darwin") return join7(home, "Library", "Application Support", "Claude");
7205
+ if (platform === "win32") {
7206
+ const packages = join7(vars["LOCALAPPDATA"] ?? join7(home, "AppData", "Local"), "Packages");
7207
+ const store = list(packages).filter((name) => name.startsWith("Claude_")).map((name) => join7(packages, name, "LocalCache", "Roaming", "Claude")).find(exists4);
7208
+ if (store) return store;
7209
+ return join7(vars["APPDATA"] ?? join7(home, "AppData", "Roaming"), "Claude");
7210
+ }
6151
7211
  return join7(home, ".config", "Claude");
6152
7212
  }
6153
7213
  var AI_CLIENTS = [
@@ -7231,11 +8291,11 @@ async function resolveScope(scope) {
7231
8291
  return { mode: "local", root };
7232
8292
  }
7233
8293
  const serviceId = scope.slice("service:".length);
7234
- const service = await serviceStore.get(serviceId);
7235
- if (!service) throw new TRPCError21({ code: "NOT_FOUND", message: "Service introuvable" });
7236
- const agentId = await resolveEffectiveAgentId(service);
8294
+ const service2 = await serviceStore.get(serviceId);
8295
+ if (!service2) throw new TRPCError21({ code: "NOT_FOUND", message: "Service introuvable" });
8296
+ const agentId = await resolveEffectiveAgentId(service2);
7237
8297
  if (!agentId) throw new TRPCError21({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
7238
- const cwd = await resolveWorkspaceCwd({ serviceId, override: service.docsPath?.trim() || void 0 });
8298
+ const cwd = await resolveWorkspaceCwd({ serviceId, override: service2.docsPath?.trim() || void 0 });
7239
8299
  return { mode: "agent", agentId, cwd };
7240
8300
  }
7241
8301
  async function walkLocal(root, dir, depth, counter) {
@@ -7385,11 +8445,11 @@ var wikiRouter = router({
7385
8445
  return { ok: true };
7386
8446
  }
7387
8447
  const serviceId = input.scope.slice("service:".length);
7388
- const service = await serviceStore.get(serviceId);
7389
- if (!service) throw new TRPCError21({ code: "NOT_FOUND", message: "Service introuvable" });
7390
- const agentId = await resolveEffectiveAgentId(service);
8448
+ const service2 = await serviceStore.get(serviceId);
8449
+ if (!service2) throw new TRPCError21({ code: "NOT_FOUND", message: "Service introuvable" });
8450
+ const agentId = await resolveEffectiveAgentId(service2);
7391
8451
  if (!agentId) throw new TRPCError21({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
7392
- const cwd = await resolveWorkspaceCwd({ serviceId, override: service.docsPath?.trim() || void 0 });
8452
+ const cwd = await resolveWorkspaceCwd({ serviceId, override: service2.docsPath?.trim() || void 0 });
7393
8453
  return agentManager.agentMutation(agentId, "wiki.ensureRoot", { cwd });
7394
8454
  }),
7395
8455
  delete: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
@@ -10042,7 +11102,7 @@ async function runLegacyMigration(dataDir) {
10042
11102
  for (const [name, legacy] of Object.entries(legacyServices)) {
10043
11103
  const serviceId = serviceIdMap[name];
10044
11104
  if (!serviceId) continue;
10045
- const service = runeServices.find((s) => s.id === serviceId);
11105
+ const service2 = runeServices.find((s) => s.id === serviceId);
10046
11106
  const svcEnvs = legacy.envs || {};
10047
11107
  for (const [envName, vars] of Object.entries(svcEnvs)) {
10048
11108
  if (!vars || typeof vars !== "object" || Object.keys(vars).length === 0) continue;
@@ -10056,7 +11116,7 @@ async function runLegacyMigration(dataDir) {
10056
11116
  svcScopedEnv = {
10057
11117
  id: randomUUID9(),
10058
11118
  projectId: projectMonoId,
10059
- name: `${service?.name || name} (${globalEnv.name})`,
11119
+ name: `${service2?.name || name} (${globalEnv.name})`,
10060
11120
  scope: "service",
10061
11121
  reference: serviceId,
10062
11122
  activateOn: globalEnvId,
@@ -10088,7 +11148,7 @@ async function runLegacyMigration(dataDir) {
10088
11148
  for (const [serviceName, envOverrides] of Object.entries(legacyServiceOverrides)) {
10089
11149
  const serviceId = serviceIdMap[serviceName];
10090
11150
  if (!serviceId) continue;
10091
- const service = runeServices.find((s) => s.id === serviceId);
11151
+ const service2 = runeServices.find((s) => s.id === serviceId);
10092
11152
  for (const [envName, vars] of Object.entries(envOverrides)) {
10093
11153
  const globalEnvId = envIdMap[envName];
10094
11154
  const globalEnv = runeEnvs.find((e) => e.id === globalEnvId);
@@ -10100,7 +11160,7 @@ async function runLegacyMigration(dataDir) {
10100
11160
  svcScopedEnv = {
10101
11161
  id: randomUUID9(),
10102
11162
  projectId: projectMonoId,
10103
- name: `${service?.name || serviceName} (${globalEnv.name})`,
11163
+ name: `${service2?.name || serviceName} (${globalEnv.name})`,
10104
11164
  scope: "service",
10105
11165
  reference: serviceId,
10106
11166
  activateOn: globalEnvId,
@@ -10365,7 +11425,7 @@ async function runOverrideOnlyMigration(dataDir) {
10365
11425
  console.warn(`[override-migration] No matching service for "${serviceName}" \u2014 skipping service overrides`);
10366
11426
  continue;
10367
11427
  }
10368
- const service = servicesRaw.find((s) => s["id"] === serviceId);
11428
+ const service2 = servicesRaw.find((s) => s["id"] === serviceId);
10369
11429
  for (const [envName, vars] of Object.entries(data)) {
10370
11430
  const globalEnvId = findEnvId(envName);
10371
11431
  if (!globalEnvId || !vars || typeof vars !== "object") continue;
@@ -10378,7 +11438,7 @@ async function runOverrideOnlyMigration(dataDir) {
10378
11438
  svcScopedEnv = {
10379
11439
  id: randomUUID9(),
10380
11440
  projectId: globalEnv["projectId"],
10381
- name: `${service?.["name"] || serviceName} (${globalEnv["name"]})`,
11441
+ name: `${service2?.["name"] || serviceName} (${globalEnv["name"]})`,
10382
11442
  scope: "service",
10383
11443
  reference: serviceId,
10384
11444
  activateOn: globalEnvId,
@@ -11624,7 +12684,7 @@ async function createLocalServer() {
11624
12684
  ]);
11625
12685
  console.log("[server] Shutdown complete");
11626
12686
  };
11627
- const { initCompanion } = await import("./companion-XKMNRIJB.js");
12687
+ const { initCompanion } = await import("./companion-H24L2MGY.js");
11628
12688
  initCompanion();
11629
12689
  return { app, server, wss, shutdown };
11630
12690
  }
@@ -11689,10 +12749,10 @@ async function unlockIfNeeded() {
11689
12749
  async function pullEnv(opts) {
11690
12750
  await unlockIfNeeded();
11691
12751
  const services = await serviceStore.list();
11692
- const service = services.find(
12752
+ const service2 = services.find(
11693
12753
  (s) => s.id === opts.service || s.name === opts.service
11694
12754
  );
11695
- if (!service) {
12755
+ if (!service2) {
11696
12756
  const available = services.map((s) => s.name).join(", ");
11697
12757
  throw new PullEnvError(`service "${opts.service}" not found. Available: ${available || "(none)"}`, 1);
11698
12758
  }
@@ -11705,7 +12765,7 @@ async function pullEnv(opts) {
11705
12765
  throw new PullEnvError(`environment "${opts.environment}" not found. Available: ${available || "(none)"}`, 1);
11706
12766
  }
11707
12767
  const { env: env2 } = await environmentResolver.resolveForService({
11708
- serviceId: service.id,
12768
+ serviceId: service2.id,
11709
12769
  activeEnvironmentId: globalEnv.id
11710
12770
  });
11711
12771
  return Object.entries(env2).map(([key, value]) => `${key}=${value}`).join("\n");
@@ -11715,20 +12775,20 @@ async function pullEnv(opts) {
11715
12775
  async function listTrayServices() {
11716
12776
  const [all, processes] = await Promise.all([serviceStore.list(), listAllProcesses()]);
11717
12777
  const byServiceId = new Map(processes.map((p) => [p.serviceId, p]));
11718
- const services = all.map((service) => {
11719
- const status = byServiceId.get(service.id);
12778
+ const services = all.map((service2) => {
12779
+ const status = byServiceId.get(service2.id);
11720
12780
  return {
11721
- id: service.id,
11722
- name: service.name,
11723
- agentId: status?.agentId ?? service.agentId ?? null,
12781
+ id: service2.id,
12782
+ name: service2.name,
12783
+ agentId: status?.agentId ?? service2.agentId ?? null,
11724
12784
  running: status?.state === "running" || status?.state === "starting",
11725
12785
  failed: status?.state === "errored" || status?.healthStatus === "unhealthy",
11726
- url: primaryServiceLink(service, "localhost")
12786
+ url: primaryServiceLink(service2, "localhost")
11727
12787
  };
11728
12788
  });
11729
12789
  const owned = await currentProjectServiceIds();
11730
- if (owned) return services.filter((service) => owned.has(service.id));
11731
- return services.filter((service) => service.running || service.failed);
12790
+ if (owned) return services.filter((service2) => owned.has(service2.id));
12791
+ return services.filter((service2) => service2.running || service2.failed);
11732
12792
  }
11733
12793
  async function currentProjectServiceIds() {
11734
12794
  const ref = getCurrentProject();
@@ -12080,4 +13140,4 @@ export {
12080
13140
  stopProcess,
12081
13141
  userPrefix
12082
13142
  };
12083
- //# sourceMappingURL=src-KWO3CKZU.js.map
13143
+ //# sourceMappingURL=src-OENXLZKQ.js.map