MicroFish/CONTEXT.md

9.8 KiB

MiroFish — Fork Context (Private Impact Feature)

Branche de travail

feature/private-impact

Remotes


Historique des sessions

2026-04-16 — Session 1

Étapes terminées

  • Prompt N°01 — Lecture complète du code source (audit, zéro modification)
  • Prompt N°02 — Setup Git : fork + remote + branche feature/private-impact
  • Prompt N°03 — Création backend/scripts/run_private_simulation.py
  • Prompt N°04 — Création backend/app/services/private_impact_profile_generator.py
  • Prompt N°05 — Création backend/app/services/private_impact_config_generator.py
  • Prompt N°06 — Création backend/app/services/private_impact_runner.py
  • Prompt N°07 — Blueprint backend/app/api/private.py + enregistrement (api/__init__.py, app/__init__.py)
  • Prompt N°08 — Modification backend/app/services/simulation_runner.py (7 zones : champs private_*, start, monitor, read_log, check_completed, get_actions, cleanup)
  • Prompt N°09 — Frontend : api/private.js + ModeSelector.vue + PrivateImpactView.vue + route /private/:projectId
  • Prompt N°10action_logger.py : ajout get_private_logger() + suppression fallback run_private_simulation.py + intégration ModeSelector dans Home.vue

Fichiers créés / modifiés

Fichier Action
backend/scripts/run_private_simulation.py Créé — moteur de simulation privé
backend/scripts/private/ Créé — répertoire de sortie actions.jsonl
backend/app/services/private_impact_profile_generator.py Créé — générateur de profils relationnels
backend/app/services/private_impact_config_generator.py Créé — générateur de paramètres comportementaux
backend/app/services/private_impact_runner.py Créé — orchestrateur subprocess + monitoring
CONTEXT.md Créé — ce fichier
backend/app/api/private.py Créé — blueprint Flask /api/private-impact (7 routes)
backend/app/api/__init__.py Modifié — ajout private_bp + import private
backend/app/__init__.py Modifié — enregistrement private_bp
backend/app/services/simulation_runner.py Modifié — 7 zones private (champs, start, monitor, read_log, check, get_actions, cleanup)
frontend/src/api/private.js Créé — client API private impact (7 fonctions)
frontend/src/components/ModeSelector.vue Créé — sélecteur Public / Private Impact (2 cartes)
frontend/src/views/PrivateImpactView.vue Créé — wizard 5 étapes (form → prepare → run → report → chat)
frontend/src/router/index.js Modifié — route /private/:projectId ajoutée
backend/scripts/action_logger.py Modifié — ajout get_private_logger() à SimulationLogManager
backend/scripts/run_private_simulation.py Modifié — suppression fallback hasattr, appel direct log_manager.get_private_logger()
frontend/src/views/Home.vue Modifié — intégration ModeSelector (right panel) + handleModeSelected + sessionStorage pendingSimMode

Décisions d'architecture prises

  • Pas d'env OASIS (pas de Twitter/Reddit/PlatformConfig)
  • Appels LLM directs via camel-ai ChatAgent + asyncio.to_thread()
  • Graphe relationnel construit depuis cascade_influence dans agent_configs
  • REACT_PRIVATELY = invisible → ne propage pas l'exposition
  • Tous les autres actions (sauf DO_NOTHING) cascade vers cascade_influence targets
  • zep_graph_memory_updater.py réutilisé sans modification (platform="private")
  • IPC PrivateIPCHandler : interviews via LLM direct (pas de SQLite)
  • Output : private/actions.jsonl (même format JSONL que twitter/reddit)
  • RelationalAgentProfile hérite de OasisAgentProfile — 8 champs relationnels ajoutés
  • Encodage des dimensions relationnelles dans le champ persona (texte naturel)
  • Fallback rule-based par type : Employee, Manager, Client, Competitor, Partner, FamilyMember
  • to_private_format() retourne le dict lu par run_private_simulation.py
  • PrivateImpactConfigGenerator.generate_config() : entrée = liste de dicts agents (issue de profile_generator), pas d'EntityNode direct
  • PrivateTimeConfig : jours + rounds/jour (matin/midi/soir) — pas d'heures ni timezone
  • PrivateEventConfig : injection par decision_statement — pas de posts sociaux
  • RelationalActivityConfig.exposure_round : round 0 = exposition directe (distance 1)
  • Fallback rule-based : table RELATIONAL_FALLBACKS dans le générateur (6 types)
  • PrivateImpactRunner : même pattern classmethods que SimulationRunner (états en mémoire de classe)
  • Config lue depuis private_simulation_config.json (≠ simulation_config.json OASIS)
  • Log unique : {sim_dir}/private/actions.jsonl (une seule plateforme)
  • PrivateRunnerStatus : enum séparé — pas de réutilisation de RunnerStatus
  • private_simulated_days lu depuis le champ simulated_day du round_end event
  • Frontend : CSS plain (pas Tailwind — non présent dans package.json) — même style que les vues existantes
  • ModeSelector.vue : composant standalone, émet @mode-selected avec "public" ou "private", à intégrer manuellement dans Home.vue ou Process.vue
  • PrivateImpactView.vue : route /private/:projectId — charge le projet via getProject() pour récupérer graph_id
  • Step 3 : polling /api/private-impact/status/{simId} toutes les 3s + affichage recent_actions depuis to_detail_dict()
  • Step 4 : report via generatePrivateReport() → task_id → polling getReportStatus(reportId)getReport(reportId) (réutilise le ReportManager existant)
  • Step 5 : chatAgents reconstruit depuis la liste d'actions (agent_id + agent_name) ; chat via interviewAgents() (réutilise simulation.js)
  • SimulationRunState : 5 champs private_* ajoutés (current_round, simulated_days, running, actions_count, completed)
  • add_action() : elif platform=="private" → private_actions_count (évite comptage dans reddit)
  • to_dict() : private_* inclus dans total_actions_count
  • start_simulation() : elif platform=="private" → run_private_simulation.py + private_running=True
  • _monitor_simulation() : lecture private/actions.jsonl dans la boucle ET en final ; private_running=False à la fin
  • _read_action_log() : simulation_end → private_completed=True ; round_end → private_current_round + private_simulated_days (depuis simulated_day)
  • _check_all_platforms_completed() : private_log + private_enabled + check private_completed
  • get_all_actions() : bloc private après reddit (même pattern)
  • cleanup_simulation_logs() : private_simulation.db + dirs_to_clean inclut "private"
  • Blueprint private_bp enregistré sans url_prefix (les routes déclarent /api/private-impact/... en entier)
  • /prepare stocke les métadonnées (graph_id, sim_requirement, agent_count…) dans private_meta.json dans le sim_dir
  • /prepare appelle ZepEntityReader.get_entities_by_type() en boucle sur les types relationnels puis PrivateImpactProfileGenerator.generate_profiles_from_entities()
  • /start lit private_simulation_config.json via PrivateImpactRunner.start_simulation()
  • /status retourne to_detail_dict() (inclut recent_actions)
  • /report réutilise ReportAgent avec simulation_id=sim_id et graph_id lu depuis private_meta.json
  • /cleanup délègue entièrement à PrivateImpactRunner.cleanup()
  • get_private_logger() ajouté à SimulationLogManager — même pattern que get_twitter_logger() / get_reddit_logger() ; fallback supprimé dans run_private_simulation.py
  • ModeSelector intégré dans Home.vue (right panel, au-dessus de .console-box) ; mode stocké dans sessionStorage (pendingSimMode) — MainView.vue (N°11) doit lire ce flag et rediriger vers /private/:projectId après création du projet

Prochaines étapes

Prompt Fichier cible Action
N°04 backend/app/services/private_impact_profile_generator.py Terminé
N°05 backend/app/services/private_impact_config_generator.py Terminé
N°06 backend/app/services/private_impact_runner.py Terminé
N°07 backend/app/api/private.py Terminé
N°07 backend/app/api/__init__.py Terminé
N°07 backend/app/__init__.py Terminé
N°08 backend/app/services/simulation_runner.py Terminé
N°09 frontend/src/views/PrivateImpactView.vue Terminé
N°09 frontend/src/components/ModeSelector.vue Terminé
N°10 backend/scripts/action_logger.py Terminé — get_private_logger() ajouté
N°10 backend/scripts/run_private_simulation.py Terminé — fallback supprimé
N°10 frontend/src/views/Home.vue Terminé — ModeSelector intégré
N°11 frontend/src/views/MainView.vue Lire sessionStorage.pendingSimMode après création du projet → rediriger vers /private/:projectId si 'private'
N°11 Test end-to-end Préparer → Lancer → Observer actions.jsonl

Point d'attention — MainView.vue (N°11)

Status : PENDING

Home.vue stocke sessionStorage.pendingSimMode = 'private' quand l'utilisateur sélectionne Private Impact. MainView.vue doit être modifié pour lire ce flag après la création du projet + le build du graphe Zep, et rediriger vers /private/:projectId au lieu de rester sur la vue OASIS standard.

Action requise dans MainView.vue — après la séquence upload → create_project → build_graph :

const pendingMode = sessionStorage.getItem('pendingSimMode')
if (pendingMode === 'private') {
  sessionStorage.removeItem('pendingSimMode')
  router.push(`/private/${projectId}`)
}