SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
19 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%

mode Orchestrateur multi-sites : 1 session Claude Code sur M3U96a qui coordonne des modifs sur les 13 apps via SSH, avec contexte complet (workspace ~/ka-orchestrator + CLAUDE.md table app→nœud→dir, ORCH_SYSTEM)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 1 mo ago (Aug 21, 2026) parent d2f510a

7 changed files +43 −5

modified data/audit.jsonl +7 −0
@@ -792,3 +792,10 @@
792 792 {"ts":"2026-08-21T16:40:17.848Z","kind":"result","chatId":"216855a50e0cb8e8","subtype":"success","cost":0.317378,"duration_ms":9175,"turns":2}
793 793 {"ts":"2026-08-21T16:40:19.058Z","kind":"result","chatId":"7013b58a64caa8c7","subtype":"success","cost":0.3702575,"duration_ms":10406,"turns":2}
794 794 {"ts":"2026-08-21T16:40:20.540Z","kind":"result","chatId":"05e031db939b2426","subtype":"success","cost":0.3163415,"duration_ms":11917,"turns":2}
795 +{"ts":"2026-08-21T16:48:36.872Z","kind":"prompt","chatId":"747405bac0551176","project":"ORCH","node":"M3U96a","dir":"/Users/simon-pierreboucher/ka-orchestrator","model":"fable","permMode":"bypass","prompt":"Tâche multi-sites (LECTURE SEULE, ne modifie rien): donne le dernier commit (hash court + sujet) de lou-ka, immo-ka et vrai-prix. Rappelle-toi que lou-ka et immo-ka sont sur d autres nœuds (SSH) et vrai-prix est local sur M3U96a. Présente un petit tableau."}
796 +{"ts":"2026-08-21T16:48:43.698Z","kind":"tool_use","chatId":"747405bac0551176","tool":"Bash","input":"{\"command\":\"ssh M3U96b 'cd ~/apps/lou-ka && git log -1 --format=\\\"%h %s\\\"'\",\"description\":\"Dernier commit de lou-ka sur M3U96b\"}"}
797 +{"ts":"2026-08-21T16:48:44.395Z","kind":"tool_use","chatId":"747405bac0551176","tool":"Bash","input":"{\"command\":\"ssh M4M64a 'cd ~/apps/immo-ka && git log -1 --format=\\\"%h %s\\\"'\",\"description\":\"Dernier commit d'immo-ka sur M4M64a\"}"}
798 +{"ts":"2026-08-21T16:48:45.540Z","kind":"tool_use","chatId":"747405bac0551176","tool":"Bash","input":"{\"command\":\"cd ~/apps/vrai-prix && git log -1 --format=\\\"%h %s\\\"\",\"description\":\"Dernier commit de vrai-prix en local\"}"}
799 +{"ts":"2026-08-21T16:48:51.697Z","kind":"result","chatId":"747405bac0551176","subtype":"success","cost":0.36772950000000004,"duration_ms":14568,"turns":4}
800 +{"ts":"2026-08-21T16:49:00.431Z","kind":"prompt","chatId":"747405bac0551176","project":"ORCH","node":"M3U96a","dir":"/Users/simon-pierreboucher/ka-orchestrator","model":"fable","permMode":"bypass","prompt":"Parmi les 3 apps que tu viens de vérifier, laquelle a le commit le plus ancien ? Réponds en une phrase, sans relancer de commande."}
801 +{"ts":"2026-08-21T16:49:12.651Z","kind":"result","chatId":"747405bac0551176","subtype":"success","cost":0.0698985,"duration_ms":11945,"turns":1}
modified data/backend.log +1 −0
@@ -20,3 +20,4 @@ admin-ka v2 sur port 3300 (dual-stack)
20 20 admin-ka v2 sur port 3300 (dual-stack)
21 21 admin-ka v2 sur port 3300 (dual-stack)
22 22 admin-ka v2 sur port 3300 (dual-stack)
23 +admin-ka v2 sur port 3300 (dual-stack)
modified data/chats.json +2 −1
@@ -81,6 +81,7 @@
81 81 "batch": "21 août, 12 h 40",
82 82 "created": 1787330408310,
83 83 "updated": 1787330421004,
84 − "lastModel": "claude-fable-5"
84 + "lastModel": "claude-fable-5",
85 + "autoAllowAll": false
85 86 }
86 87 ]
\ No newline at end of file
modified data/eco.sqlite +0 −0

Binary file not shown.

modified data/ngrok.log +12 −0
@@ -1211,3 +1211,15 @@ t=2026-08-21T12:40:39-0400 lvl=info msg="join connections" obj=join id=0c4e1dcdc
1211 1211 t=2026-08-21T12:40:39-0400 lvl=info msg="join connections" obj=join id=0489655aa9c3 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:63948
1212 1212 t=2026-08-21T12:40:39-0400 lvl=info msg="join connections" obj=join id=a40da0d08b5d l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:63949
1213 1213 t=2026-08-21T12:40:40-0400 lvl=info msg="join connections" obj=join id=9243997478cc l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:63950
1214 +t=2026-08-21T12:43:13-0400 lvl=info msg="join connections" obj=join id=ba5b5dca466d l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64027
1215 +t=2026-08-21T12:43:14-0400 lvl=info msg="join connections" obj=join id=780680b5c1a0 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64028
1216 +t=2026-08-21T12:43:14-0400 lvl=info msg="join connections" obj=join id=b2fda2bd99f6 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64029
1217 +t=2026-08-21T12:43:14-0400 lvl=info msg="join connections" obj=join id=b239b3bc1667 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64030
1218 +t=2026-08-21T12:43:14-0400 lvl=info msg="join connections" obj=join id=a25b7a02d5be l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64031
1219 +t=2026-08-21T12:46:22-0400 lvl=info msg="join connections" obj=join id=bb1fb1d5a4fb l=[::1]:3300 r=[2605:b100:149:21ca:d0a1:55e:1003:f5f2]:60975
1220 +t=2026-08-21T12:46:23-0400 lvl=info msg="join connections" obj=join id=8fe3211c4b3c l=[::1]:3300 r=[2605:b100:149:21ca:d0a1:55e:1003:f5f2]:60979
1221 +t=2026-08-21T12:46:23-0400 lvl=info msg="join connections" obj=join id=88a3612eacb6 l=[::1]:3300 r=[2605:b100:149:21ca:d0a1:55e:1003:f5f2]:60981
1222 +t=2026-08-21T12:48:30-0400 lvl=info msg="join connections" obj=join id=83c9dc233bb9 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64149
1223 +t=2026-08-21T12:48:36-0400 lvl=info msg="join connections" obj=join id=3b11b9c96058 l=[::1]:3300 r=76.70.60.50:58039
1224 +t=2026-08-21T12:49:00-0400 lvl=info msg="join connections" obj=join id=0708eaa6cb08 l=[::1]:3300 r=76.70.60.50:58239
1225 +t=2026-08-21T12:49:13-0400 lvl=info msg="join connections" obj=join id=48c8268e85e6 l=[::1]:3300 r=[2605:b100:149:21ca:b509:761e:2e8d:6cfc]:64166
modified public/app.js +6 −1
@@ -1249,7 +1249,12 @@
1249 1249 projectSel.appendChild(o);
1250 1250 }
1251 1251 if (settings.projectId) projectSel.value = settings.projectId;
1252 − projectSel.onchange = () => { settings.projectId = projectSel.value; saveStore(); refreshChips(); if (projectSel.value === 'ALL') inputEl.placeholder = 'Prompt pour TOUTES les apps KA…'; else inputEl.placeholder = 'Demander à Claude Code…'; };
1252 + projectSel.onchange = () => {
1253 + settings.projectId = projectSel.value; saveStore(); refreshChips();
1254 + inputEl.placeholder = projectSel.value === 'ALL' ? 'Prompt diffusé à TOUTES les apps KA…'
1255 + : projectSel.value === 'ORCH' ? 'Tâche multi-sites — 1 session qui coordonne tout…'
1256 + : 'Demander à Claude Code…';
1257 + };
1253 1258 refreshChips();
1254 1259 refreshSettingsView();
1255 1260 // reprise automatique : on rouvre la dernière conversation (historique +
modified server/server.js +15 −3
@@ -218,10 +218,19 @@ const PROJECTS = [
218 218 { id: 'job-ka@M3U96a', name: 'Job·Ka', node: null, dir: path.join(HOME, 'apps', 'job-ka') },
219 219 { id: 'trouve-ka@M2M32', name: 'Trouve·Ka', node: 'M2M32', dir: '~/trouve-ka' },
220 220 ];
221 +// Orchestrateur : une seule session sur M3U96a qui pilote les 13 apps via SSH,
222 +// en gardant le contexte complet de la tâche.
223 +const ORCH_PROJECT = { id: 'ORCH', name: '🎛️ Orchestrateur multi-sites', node: null, dir: path.join(HOME, 'ka-orchestrator') };
221 224 function listProjects() {
222 − return PROJECTS.map(p => ({ id: p.id, name: p.name, node: p.node || SELF_NODE, dir: p.dir }));
225 + return [
226 + { id: ORCH_PROJECT.id, name: ORCH_PROJECT.name, node: SELF_NODE, dir: ORCH_PROJECT.dir },
227 + ...PROJECTS.map(p => ({ id: p.id, name: p.name, node: p.node || SELF_NODE, dir: p.dir })),
228 + ];
229 +}
230 +function findProject(id) {
231 + if (id === 'ORCH') return ORCH_PROJECT;
232 + return PROJECTS.find(p => p.id === id) || null;
223 233 }
224 −function findProject(id) { return PROJECTS.find(p => p.id === id) || null; }
225 234
226 235 // ---------- exécution Claude Code ----------
227 236 const MODELS = ['fable', 'opus', 'sonnet', 'haiku'];
@@ -233,6 +242,8 @@ const ALLOWED_READONLY = 'Read,Glob,Grep,LS,WebFetch,WebSearch,TodoWrite,Noteboo
233 242
234 243 const SYSTEM_APPEND = `RÈGLE OBLIGATOIRE (console administration-ka) : si tu as modifié des fichiers du projet pendant ce tour, tu DOIS avant de conclure : (1) rebuild si le projet a une étape de build ; (2) redéployer — pm2 restart <app> (ou le mécanisme en place) — et VÉRIFIER que l'app répond (healthcheck/port/site) ; (3) committer et pousser : git add + git commit + git push origin main — le remote origin est spbgit (git perso git.spboucher.ai), PAS GitHub. Ne termine jamais en laissant des modifications non commitées ou non redéployées. Si aucun fichier n'a été modifié, ignore cette règle.`;
235 244
245 +const ORCH_SYSTEM = `Tu es la session ORCHESTRATRICE multi-sites du Groupe KA, lancée sur M3U96a. La tâche demandée peut concerner PLUSIEURS apps KA à la fois — tu gardes le contexte complet du début à la fin. Le fichier CLAUDE.md de ton répertoire (~/ka-orchestrator) contient la table app→nœud→répertoire de prod et la méthode : lis-le et suis-le. Tu modifies les repos de PROD à distance via SSH (ssh <nœud> 'cd <dir> && …') ; les apps sur M3U96a se font en local. Planifie avec TodoWrite, explore le pattern commun avant d'agir, applique app par app, et pour CHAQUE app modifiée : build si besoin + pm2 restart + healthcheck + git add/commit/push origin main (spbgit). Termine par un bilan (apps modifiées, commits, restes). Ne laisse aucune app en état incohérent.`;
246 +
236 247 const shq = (s) => `'` + String(s).replace(/'/g, `'\\''`) + `'`;
237 248
238 249 // chatId -> { proc, permToken, stderr, remote }
@@ -280,8 +291,9 @@ function startClaude(chat, prompt) {
280 291 const permMode = PERM_MODES.includes(chat.permMode) ? chat.permMode : 'default';
281 292 let proc;
282 293
294 + const sysAppend = chat.projectId === 'ORCH' ? ORCH_SYSTEM : SYSTEM_APPEND;
283 295 const baseArgs = ['-p', '--output-format', 'stream-json', '--verbose', '--include-partial-messages',
284 − '--model', CLI_MODEL[model], '--append-system-prompt', SYSTEM_APPEND];
296 + '--model', CLI_MODEL[model], '--append-system-prompt', sysAppend];
285 297 if (chat.claudeSessionId) baseArgs.push('--resume', chat.claudeSessionId);
286 298
287 299 if (!chat.node) {
288 300