#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════════════ # BUILD-D1+D2 — Leon/Vincento Remediering — APPLY SCRIPT (MINIMAL) # ═══════════════════════════════════════════════════════════════════════════════ # STAGED AV: Subagent (build-d1d2-staging 2026-06-06) # KÖRNING: Bernt kör manuellt mot prod efter granskning # KÖRTS: NEJ # # STATUS: Majoriteten av D1+D2 är REDAN APPLICERAT av tidigare session. # Detta script hanterar de 3 återstående åtgärderna: # # A) aamos/comms/engine.mjs rad 384 # KRITISK: routeQuestion() skickar marketing→leon@hypbit.com (raderad adress) # → Ompeka till johan@hypbit.com (CTO, temporärt CMO) # # B) data/agent-heartbeats.json # MEDIUM: leon-daily-dm-status heartbeat är fortfarande aktivt # → Ta bort kirurgiskt via Python/JSON (ALDRIG sed på JSON) # # C) api/cognitive/homo-deus-comms.mjs header-kommentarer # KOSMETIK: Rader 3+6 nämner Vincento i kommentarer # → Rensa # # FÖRUTSÄTTNINGAR: # - AWS CLI konfigurerad med default-profil (platform-ai-agent) # - Kör från bernt@server-2 (INTE root) # - unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN # - Backup-katalog skapas automatiskt # # IDEMPOTENT: Alla steg kontrollerar om redan klart innan de agerar. # ═══════════════════════════════════════════════════════════════════════════════ set -euo pipefail # ── Konfiguration ────────────────────────────────────────────────────────────── INSTANCE_ID="i-09b2204a52c2f33c9" REGION="eu-north-1" AMOS_ROOT="/opt/amos" TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_DIR="${AMOS_ROOT}/backups/d1d2-${TIMESTAMP}" # Sätt rätt AWS-profil unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN 2>/dev/null || true export AWS_DEFAULT_REGION="$REGION" # ── SSM Helper ───────────────────────────────────────────────────────────────── ssm_run() { local description="$1" local commands_json="$2" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "▶ SSM: $description" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" cat > /tmp/ssm-params.json <&1) STATUS=$(echo "$RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0])" 2>/dev/null || echo "UNKNOWN") STDOUT=$(echo "$RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[1])" 2>/dev/null || echo "") STDERR=$(echo "$RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[2])" 2>/dev/null || echo "") echo " Status: $STATUS" [ -n "$STDOUT" ] && [ "$STDOUT" != "None" ] && echo " Output: $STDOUT" [ -n "$STDERR" ] && [ "$STDERR" != "None" ] && [ "$STDERR" != "" ] && echo " Stderr: $STDERR" if [ "$STATUS" != "Success" ]; then echo " ❌ MISSLYCKADES — avbryter. Rätta felet och kör igen." exit 1 fi echo " ✅ OK" } # ══════════════════════════════════════════════════════════════════════════════ echo "═══════════════════════════════════════════════════════════════════" echo " BUILD-D1+D2 APPLY — Minimal (3 återstående åtgärder)" echo " Timestamp: $TIMESTAMP" echo " Instans: $INSTANCE_ID" echo " Backup-dir: $BACKUP_DIR" echo "═══════════════════════════════════════════════════════════════════" echo "" echo "Åtgärder i detta script:" echo " A) aamos/comms/engine.mjs:384 — routeQuestion() marketing→leon FIX [KRITISK]" echo " B) data/agent-heartbeats.json — ta bort leon-daily-dm-status [MEDIUM]" echo " C) homo-deus-comms.mjs — rensa header-kommentarer [KOSMETIK]" echo "" echo "DETTA SCRIPT MUTERAR PRODUKTION." echo "Läs build-d1d2-remediering.md om du inte redan gjort det." echo "" read -p "Skriv 'APPLICERA' för att fortsätta: " CONFIRM if [ "$CONFIRM" != "APPLICERA" ]; then echo "Avbruten." exit 0 fi # ══════════════════════════════════════════════════════════════════════════════ # STEG 0 — Skapa backup-katalog # ══════════════════════════════════════════════════════════════════════════════ ssm_run "Steg 0: Skapa backup-katalog" \ "[\"mkdir -p ${BACKUP_DIR} && echo 'OK: backup-dir skapad'\"]" # ══════════════════════════════════════════════════════════════════════════════ # STEG A — aamos/comms/engine.mjs:384 — KRITISK routeQuestion()-fix # ══════════════════════════════════════════════════════════════════════════════ echo "" echo "══ STEG A: 💀 KRITISK: aamos/comms/engine.mjs:384 ══" echo " routeQuestion(): marketing-frågor → leon@hypbit.com (RADERAD ADRESS)" echo " Ompeka till johan@hypbit.com (CTO, temporärt CMO)" echo "" ssm_run "Steg A1: Backup aamos/comms/engine.mjs" \ "[\"cp ${AMOS_ROOT}/api/aamos/comms/engine.mjs ${BACKUP_DIR}/aamos-comms-engine.mjs.bak && echo OK\"]" ssm_run "Steg A2: Verifiera befintligt innehåll (ska hitta leon@hypbit.com i routeQuestion)" \ "[\"grep -n 'Marketing question' ${AMOS_ROOT}/api/aamos/comms/engine.mjs\"]" # Använd Python för exakt byte-ersättning (undviker sed/unicode-problem) ssm_run "Steg A3: 💀 Ändra routeQuestion(): leon@hypbit.com → johan@hypbit.com" \ "[\"python3 -c \\\"\\nFILE = '${AMOS_ROOT}/api/aamos/comms/engine.mjs'\\nwith open(FILE) as f: c = f.read()\\nold = \\\" to = 'leon@hypbit.com'; reason = 'Marketing question';\\\"\\nnew = \\\" to = 'johan@hypbit.com'; reason = 'Marketing question (CTO Johan -- CMO vakant 2026-06-06)';\\\"\\nif old not in c:\\n print('ALREADY_DONE eller EJ HITTAT -- granska manuellt!')\\n exit(0)\\nnew_c = c.replace(old, new, 1)\\nopen(FILE, 'w').write(new_c)\\nprint('OK: routeQuestion marketing -> johan@hypbit.com')\\n\\\"\"]" ssm_run "Steg A4: Verifiera — leon@hypbit.com ej i aktiv kod" \ "[\"python3 -c \\\"\\nc = open('${AMOS_ROOT}/api/aamos/comms/engine.mjs').read()\\n# Aktiva refs = leon@hypbit.com ej i kommentar\\nactive = [l.strip() for l in c.split('\\\\n') if 'leon@hypbit.com' in l and not l.strip().startswith('//')]\\nprint('active_leon_refs:', active, '(expect: [])')\\nprint('marketing_to:', [l.strip() for l in c.split('\\\\n') if 'Marketing question' in l])\\n\\\"\"]" # ══════════════════════════════════════════════════════════════════════════════ # STEG B — agent-heartbeats.json — Ta bort leon-daily ⚠️ SCHEDULER # ══════════════════════════════════════════════════════════════════════════════ echo "" echo "══ STEG B: ⚠️ agent-heartbeats.json — SCHEDULER — leon-daily bort ══" echo " Bevara: winston, johan, dennis, erik" echo " Ta bort: leon-daily-dm-status" echo "" read -p "Bekräfta borttagning av leon-daily heartbeat [yes/no]: " CONFIRM_HB if [ "$CONFIRM_HB" = "yes" ]; then ssm_run "Steg B1: Backup agent-heartbeats.json" \ "[\"cp ${AMOS_ROOT}/data/agent-heartbeats.json ${BACKUP_DIR}/agent-heartbeats.json.bak && echo OK\"]" ssm_run "Steg B2: Visa heartbeats FÖRE ändring" \ "[\"python3 -c \\\"import json; d=json.load(open('${AMOS_ROOT}/data/agent-heartbeats.json')); print('FORE:', [h['id'] for h in d['heartbeats']])\\\"\"]" ssm_run "Steg B3: 💀 Ta bort leon-daily-dm-status (Python/JSON — kirurgiskt)" \ "[\"python3 -c \\\"\\nimport json, sys\\nFILE = '${AMOS_ROOT}/data/agent-heartbeats.json'\\nwith open(FILE) as f: d = json.load(f)\\nbefore = len(d['heartbeats'])\\nleon_ids = [h['id'] for h in d['heartbeats'] if h.get('agent')=='leon' or h.get('id','').startswith('leon')]\\nif not leon_ids: print('ALREADY_DONE'); sys.exit(0)\\nprint('Tar bort:', leon_ids)\\nd['heartbeats'] = [h for h in d['heartbeats'] if h.get('agent')!='leon' and not h.get('id','').startswith('leon')]\\nif 'n8n_workflow_ids' in d:\\n d['n8n_workflow_ids'] = {k:v for k,v in d['n8n_workflow_ids'].items() if not k.startswith('leon')}\\nafter = len(d['heartbeats'])\\nprint(f'Heartbeats: {before} -> {after}')\\nif after == 0: print('ERROR: Alla raderades!'); sys.exit(1)\\nif after < before - 1: print(f'VARNING: {before-after} poster borttagna, fler an vantad 1!')\\nopen(FILE,'w').write(json.dumps(d, indent=2, ensure_ascii=False)+'\\\\n')\\nprint('OK: leon-daily-dm-status borttagen')\\n\\\"\"]" ssm_run "Steg B4: Verifiera heartbeats EFTER (ska vara exakt 4)" \ "[\"python3 -c \\\"import json; d=json.load(open('${AMOS_ROOT}/data/agent-heartbeats.json')); ids=[h['id'] for h in d['heartbeats']]; print('EFTER COUNT:', len(ids)); print('IDS:', ids)\\\"\"]" else echo " Hoppar över STEG B." fi # ══════════════════════════════════════════════════════════════════════════════ # STEG C — homo-deus-comms.mjs — Rensa header-kommentarer (KOSMETIK) # ══════════════════════════════════════════════════════════════════════════════ echo "" echo "══ STEG C: homo-deus-comms.mjs — header-kommentar (kosmetik) ══" echo "" read -p "Rensa Vincento ur header-kommentarer i homo-deus-comms.mjs? [yes/no]: " CONFIRM_HEADER if [ "$CONFIRM_HEADER" = "yes" ]; then ssm_run "Steg C1: Backup homo-deus-comms.mjs" \ "[\"cp ${AMOS_ROOT}/api/cognitive/homo-deus-comms.mjs ${BACKUP_DIR}/homo-deus-comms.mjs.bak && echo OK\"]" ssm_run "Steg C2: Visa header FÖRE" \ "[\"head -10 ${AMOS_ROOT}/api/cognitive/homo-deus-comms.mjs\"]" ssm_run "Steg C3: Rensa header-kommentarer (Python)" \ "[\"python3 -c \\\"\\nFILE = '${AMOS_ROOT}/api/cognitive/homo-deus-comms.mjs'\\nwith open(FILE) as f: c = f.read()\\n\\n# Rad 3: ta bort Vincento ur agent-mesh-beskrivning\\nold3 = ' * NATS JetStream protocol -- Agent mesh for Bernt, Rufus, Sven, Kjell, Vincento'\\nnew3 = ' * NATS JetStream protocol -- Agent mesh for Bernt, Rufus, Sven, Kjell\\\\n * [2026-06-06] Vincento avvecklad'\\n\\n# Rad 6: ta bort homo.vincento.inbox ur subject-lista\\nold6 = ' * homo.bernt.inbox / homo.rufus.inbox / homo.sven.inbox / homo.kjell.inbox / homo.vincento.inbox'\\nnew6 = ' * homo.bernt.inbox / homo.rufus.inbox / homo.sven.inbox / homo.kjell.inbox'\\n\\nchanged = False\\nif old3 in c:\\n c = c.replace(old3, new3, 1); changed = True\\nelse:\\n print('INFO: Rad 3 matchar ej exakt -- skip (kan redan vara andrat)')\\n\\nif old6 in c:\\n c = c.replace(old6, new6, 1); changed = True\\nelse:\\n print('INFO: Rad 6 matchar ej exakt -- skip')\\n\\nif changed:\\n open(FILE,'w').write(c)\\n print('OK: header-kommentarer uppdaterade')\\nelse:\\n print('ALREADY_DONE eller matchar ej -- kontrollera manuellt')\\n\\\"\"]" ssm_run "Steg C4: Visa header EFTER" \ "[\"head -12 ${AMOS_ROOT}/api/cognitive/homo-deus-comms.mjs\"]" else echo " Hoppar över STEG C." fi # ══════════════════════════════════════════════════════════════════════════════ # STEG D — KOORDINERAT AMOS-CORE RESTART (SIST!) # ══════════════════════════════════════════════════════════════════════════════ echo "" echo "══ STEG D: 🔄 AMOS-CORE RESTART (koordinerat, sist) ══" echo " Steg A (comms/engine.mjs) kräver restart för att laddas om." echo " Port 3100 nere ~10-30 sekunder." echo "" read -p "Starta om amos-core nu? [yes/no]: " CONFIRM_RESTART if [ "$CONFIRM_RESTART" = "yes" ]; then ssm_run "Steg D1: amos-core status FÖRE" \ "[\"sudo systemctl is-active amos-core 2>/dev/null || pm2 list 2>/dev/null | grep -E 'amos|status' | head -5 || echo 'kontrollera manuellt'\"]" ssm_run "Steg D2: 🔄 Restart amos-core" \ "[\"sudo systemctl restart amos-core 2>/dev/null && echo 'systemctl restart OK' || (pm2 restart amos-core 2>/dev/null && echo 'pm2 restart OK') || echo 'restart: ingen match -- kolla manuellt'\"]" echo " Väntar 20 sekunder..." sleep 20 ssm_run "Steg D3: Health check EFTER restart" \ "[\"curl -sf http://localhost:3100/api/health 2>/dev/null | python3 -m json.tool 2>/dev/null || curl -sf http://localhost:3100/api/health 2>/dev/null || echo 'health-check: kontrollera manuellt'\"]" ssm_run "Steg D4: Verifiera routeQuestion marketing-routing" \ "[\"grep -n 'Marketing question' ${AMOS_ROOT}/api/aamos/comms/engine.mjs\"]" else echo " Hoppar över STEG D." echo " KOM IHÅG: sudo systemctl restart amos-core för att ladda om ändringar!" fi # ══════════════════════════════════════════════════════════════════════════════ # SLUTRAPPORT # ══════════════════════════════════════════════════════════════════════════════ echo "" echo "═══════════════════════════════════════════════════════════════════" echo " BUILD-D1+D2 APPLY KLAR — $(date)" echo "═══════════════════════════════════════════════════════════════════" echo "" echo "Backup-katalog: $BACKUP_DIR" echo "" echo "RESULTAT:" echo " ✅ Steg A: aamos/comms/engine.mjs:384 — marketing→johan@hypbit.com" echo " ✅ Steg B: agent-heartbeats.json — leon-daily borttagen" echo " ✅ Steg C: homo-deus-comms.mjs — header-kommentarer rensade" echo " ✅ Steg D: amos-core restartat" echo "" echo "KVARVARANDE UTANFÖR D1+D2-SCOPE:" echo " ⏳ CANON-tillägg: Bernt lägger manuellt i /opt/amos/data/AAMOS_CANON.md" echo " ⏳ EMP-004 payroll-avslut (Leon Magnusson = Leon Russo De Cerame): SEPARAT BESLUT" echo " ⏳ heartbeat-runner.mjs buildVincentoBrief(): separat step" echo " ⏳ skv-integration-w25.mjs:89: väntar Bernts konfirmation" echo " ⏳ data/team.json: Leon fortfarande active" echo " ⏳ Övriga ~70 filer i D3-inventering: arkivering/rensning" echo "" echo "FLAGGAR:" echo " ⚠️ Leon Magnusson = Leon Russo De Cerame (EMP-004, leon@wavult.com)" echo " ⚠️ erik-monday heartbeat innehåller '• Leon: [senaste action]' (trivialt)" echo " ⚠️ EMP-004 fortfarande active i people.mjs/payroll.mjs"