Repository navigation
sync: develop sur l'état main (nettoyage doc #531 + SUPPORT/AUTHORS/CITATION.cff) - #532
Closed
donovan-dev-web wants to merge 1 commit into
Closed
donovan-dev-web wants to merge 1 commit into
donovan-dev-web wants to merge 1 commit into
Conversation
…nommés, filtre ADR (#531) * [GOVERNANCE] Jalon U0 — socle git flow, CI, gouvernance GitHub (#409) * feat(governance): jalon U0 — socle git flow, CI remaniée, gouvernance GitHub - branches Git Flow : develop créée depuis main - milestones dédupliqués (série canonique par composant), labels normalisés - CI: jobs filtrés par paths (syne/**, echos/**) via détection git diff, validation transverse toujours verte ; conteneurisation Docker reportée - release.yml: aligné (pas de GHCR tant que pas de conteneurisation) - ajout .gitignore/.editorconfig ; maj README, INSTALLATION, CHANGELOG * fix(governance): resserre l'heuristique anti-secrets (auto-correspondance du motif) * feat(syne): socle U0 — solution .NET, config Annexe H + CLI, PRNG déterministe, ADR-012 (#410) - Syne.sln + Simulation.Core/Simulation.Console/Simulation.Core.Tests séparés (SYNE-001) - SimulationOptions (Annexe H) + loader JSON générique (fichier partiel préservant les défauts), validation des plages, priorité défauts -> --config -> flags CLI (SYNE-006) - CliOptions.Parse : --seed/--max-ticks/--world-size/--headless/--config, erreur explicite rc=2 - PRNG xoshiro256** + splitmix64 (System.Random interdit) : vecteurs de référence épinglés depuis une implémentation indépendante (SYNE-005 via déterminisme) - ADR-012 (config JSON + CLI) fusionnée ; ARCHITECTURE.md/§4§6 + CHANGELOG SYNE à jour - 28 tests xUnit verts, build Release sans avertissement * feat(syne): noyau U0 — boucle minimale, monde + grille spatiale, entités typées + traits (#411) - SimulationLoop : 1 tick = 1 minute simulée, maxTicks respecté, PRNG ancré au tick (tête/queue affichées par la Console) — SYNE-002 - World : plan continu non-toroidal (positions clampées [0,W]x[0,H]), SpatialGrid uniforme à rayon configurable (requêtes déterministes ligne-par-ligne) — SYNE-003 - Entity : identité séquentielle, espèce, position, 8 traits [0,2] hérités d'un paramétrage (plages), validation des invariants ; fabrique déterministe — valeurs épinglées calculées par implémentation indépendante — SYNE-004 - namespace Loop (évite l'ombre portée de Simulation.Core.Simulation) - ARCHITECTURE.md + CHANGELOG SYNE à jour ; 62 tests xUnit verts * feat(echos): livraison ECHOS-1 — structure du monorepo (U0) (#412) - paquet Python echos : API FastAPI create_app() (/health), registre des 7 moteurs de métriques (METRICS_SPEC) + placeholder ingestion - echos-ui : Vite + React + TypeScript (lint, build, tests vitest/jsdom) - 13 tests pytest, couverture 100 %, flake8 (max-line-length=100) - CI : job echos-python recalé sur 'flake8 echos', echos-ui npm ci actif - docs : CHANGELOG/ARCHITECTURE ECHOS + CHANGELOG racine à jour * feat(echos): livraison ECHOS-2 — contrats d'ingestion SYNE + golden files (U0) (#413) - modèles pydantic WorldSnapshot/ExternalEvent (JSON camelCase, API_CONTRACTS.md §2) : aliases ingress, sortie by_alias, parse_message déterministe + InvalidMessageError stable - WsClient :5180 (transport injectable, réception rejouée déterministe) et ControlClient :5181 (start/pause/resume/reset, corps vérifiés) - golden files versionnés (fixtures/ + golden/) : double garde non-régression (contrat camelCase + vue interne snake_case) - deps runtime : httpx + websockets ajoutés - 43 tests pytest (couverture 98 %), flake8 propre, docs à jour * feat(syne): jalon ph1 — BDI + perception (SYNE-010 à SYNE-015) (#414) - Perception : rayon 50 (déc. 6), confiance 1−(d/r)×0.3, rotation id%4, ligne de vue obstacle cercle (ADR-013), micro-benchmark grille (< 10 ms) - Mémoire : salience exponentielle, éviction, rappel ordonné (SYNE-013) - Croyances : révision alignement/conflit/moyenne, expiration (SYNE-014) - BDI + utilité : pipeline 10/15 étapes branché, U = (b−c−r)×conf×persona+urg, mouvements déterministes sans consommation PRNG (SYNE-010) - Déterminisme : hash FNV-1a épinglé de la trajectoire (SYNE-015) - Tests : 62 → 122 (toutes catégories nouvelles), build warnaserror vert * feat(syne): émetteur WebSocket d'observabilité (SYNE-080) — snapshots + événements typés par tick (#415) * feat(echos): ECHOS-010 — consommation du flux alignée par tick (snapshots V0.1 + serveur in-process) (#416) * feat(echos): ECHOS-011/012/013 — stockage d'analyse (agrégation, SQLite, Parquet, pipeline) (#417) * docs(echos): preuve du déterminisme J1 (2 runs seed 7 → 0 divergence sur 443 ticks + 44 300 séries) (#418) * docs: site GitHub Pages DocFX + XML SYNE (#docs-site) (#419) - Landing de présentation (docs/site/index.md) + TOC DocFX - Docs clés synchronisées par sync-docs.sh (source unique monorepo) - API Simulation.Core générée par DocFX depuis le XML (Simulation.Core uniquement) - XML .NET activé sur Simulation.Core + Simulation.Console (NoWarn 1591) - Workflow docs-pages : push develop -> build XML + docfx -> gh-pages - Branche gh-pages initialisée, source Pages basculée, .nojekyll - Badge Documentation + entrée CHANGELOG Co-authored-by: DevOps LIVE X <devops@livex.local> * feat(syne): SYNE ph2 — mémoire intergénérationnelle, trustDecay, éviction 1000 + observabilité étendue (#420) * feat(echos): ECHOS-020→027 — 7 moteurs de métriques déterministes + golden files + preuve J2 (#421) * feat(syne): SYNE ph3 — délibération (fréquence/holdover), interruptions, conflits de priorités, utilité alignement + hystérésis (#SYNE-030→033) (#422) * feat(echos): ECHOS ph3 — indicateurs d'émergence (score composite, phénomènes, complexité/imprévisibilité, disclaimer) + preuve J3 (#ECHOS-030→033) (#423) * feat(syne): SYNE ph4 — catalogue d'actions déclaratif + exécuteur atomique, actions terminales Eat/Drink + réserves globales (seuils ≥ 50), déclencheur d'interruption centralisé (#SYNE-040→043) (#424) * feat(echos): ECHOS ph4 — API REST (runs, métriques/séries ?every=N + cache, export JSON/CSV reproductible, croyances/relations, groupes, phénomènes) + stockage v2 (tick_metrics, tick_contexts) + preuve J5 (#ECHOS-040→045) (#425) * feat(syne): SYNE ph5 — communication par pulsations (diffusion publique + interception, coûts émission/réception hérités configurables, relais avec dégradation de confiance ×0.9/hop), événements message_sent/message_received, engineVersion 0.4.0 (#SYNE-050→054) (#426) * feat(echos): ECHOS ph5 — logging & instrumentation (JSONL déterministe tag SSE-V2, traces decision_traces schéma v3 + endpoint /decisions, profilage bit-à-bit des 8 moteurs), SCHÉMA SCHEMA_VERSION 3, preuve J5 étendue 181 tests (#ECHOS-050→052) (#427) * feat(syne): SYNE ph6 — réseau social émergent (cohésion confiance × affinité et composantes, leader par confiance entrante, décisions collectives pondérées, LOD 10 ticks, turnover), naissance par fusion consentie (paire d'id minimal, enfant médian, mind Born), héritage fin (dominance/mutation SplitMix64, salience configurable), événements group_formed/dissolved/decision + agent_spawned, snapshot groups[], transmissionRange 55 (§ calibration ph6), engineVersion 0.5.0 (#SYNE-060→063) (#428) * feat(echos): ECHOS ph6 — analyse causale hors ligne (reconstruction Action←Intention←Objectif←Besoin←Croyance←Mémoire←Perception depuis decision_traces/events_log/agents, cycles récurrents + profondeur bornée [1,12], CausalCache LRU invalidé sur ingest_version, endpoint GET /api/runs/{id}/causal-chains/{agentId}) (#ECHOS-060→063) (#429) * feat(syne): SYNE ph7b — fidélités V0.1 (mortalité épuisement DeathSystem + agent_died, naissance consentie fidèle Qualifies/LOS/énergie/critique, décision collective → objectifs membres GroupObjective/PropagateObjectives + bonus alignement, cheminement A* déterministe grille rasterisée/voisinage ordonné/tie-break/repli sur place + PathCache LRU), preuves anti-triche SYNE-081/082, engineVersion 0.6.0 + checksum doré ré-épinglé 0x27fad50065d8c4a4 (#SYNE-074→077, #SYNE-081→082) (#430) * fix(echos): publie GET /api/runs/{id}/decisions dans le registre _ENDPOINTS (auto-description ), + test registre ECHOS-051 — alignement inventaire API_REST.md §2 (11 endpoints) (#431) * docs(syne): resegmentation U5/U6/U8 (U6 = ph8 + ph7b SYNE-074-077 + ECHOS ph6 ; U8 = ph7 + ph11 + 120-131 + packaging), tickets SYNE-074→077 livrés (jalon ph7b), agent_died documenté (payload {cause,species}, engineVersion 0.6.0), régularisation API_CONTRACTS/DETERMINISM/TESTING/CHANGELOG + épinglage checksum 0x27fad50065d8c4a4 (#432) * docs(echos): décision interface web locale React/Vite servie par FastAPI — PAS de shell Electron en V0.1 (ADR-001 ECHOS, ARCHITECTURE ECHOS/racine, CHANGELOG, FRONTEND_VISION, ISSUES, README, ROADMAP, PRISM ; résidu Electron = contexte d'abandon uniquement) (#433) * feat(syne): jalon ph9 — performance & scalabilité SYNE-090→093 (TickBudgetCollector budgets 7 sous-systèmes + part computation ≥30 %, CLI --benchmark cibles 50/500/1000 + checksum d'état FNV-1a, ObjectPool sur buffer de tri de perception pour réduire l'allocation GC, déterminisme conservé — checksum doré inchangé 0x27fad50065d8c4a4) ; tests +12 (ObjectPool 5, TickBudget 3, ScaleTargets 4) → 273 Core + 6 Console (#SYNE-090→093) (#434) * docs(syne): jalon ph9 livré — PERFORMANCE.md §9 (résultats --benchmark ≥2720/1187/505 t/s, part computation 35-68%, machine de référence, convention CI planchers 120/30/20×\~7), ISSUES.md SYNE-090→093 LIVRÉ, CHANGELOG, ROADMAP racine+docs (U7/ph9), TESTING.md (+12 → 279, planchers, §5/§6) — checksum doré inchangé 0x27fad50065d8c4a4 (#435) * feat(syne): jalon ph10 — tests & couverture SYNE-100→102 (validateur config 100%, déterminisme d'état complet) ; intégration boucle complète sans perte data; observabilité étendue ExternalEvent (#436) * feat(echos): jalon ph7 — comparaison expérimentale ECHOS-070→072 (U7) (#438) * feat(echos): jalon ph7 — comparaison expérimentale ECHOS-070→072 (GET /api/compare, méta-métriques reproductibilité ReproducibilityScore 1-(CognitiveDiff+SocialDiff)/2, empreinte SHA-256 canonique, exports json/csv alignés) ; tests +11 → 208, couverture 97,97% * style(echos): lignes test_compare.py ≤ 100 caractères (flake8 echos .flake8 max-line-length=100) — CI Python verte * docs(syne): jalon ph10 livré — SYNE-100→102 (324 tests, couverture 96,19%, baseline d'état 0x072a488aa18c05eb épinglée DETERMINISM §7), ROADMAP/TESTING/CHANGELOG/ISSUES+racine U7 (#437) * docs(echos): jalon ph7 livré — comparaison expérimentale ECHOS-070→072 (API_REST §3.9 +registre 12 endpoints, EXPERIMENT_COMPARISON §4 implémenté, METRICS_SPEC §10, ISSUES LIVRÉ, CHANGELOG, ROADMAP, TESTING +11→208/97,97%) ; ROADMAP racine U7 complet livré (#439) * docs(echos): correction Electron — conservé, implémentation différée post-V0.1 (#440) Reformulation 'PAS de shell Electron' → 'shell Electron conservé, implémentation différée à un horizon ultérieur' (décision 23/09/2026 corrigée) dans ADR-001 ECHOS (décision + log correctif), ARCHITECTURE (ECHOS + racine), FRONTEND_VISION, README, ROADMAP (phase 10 'Shell Electron'), ISSUES (ECHOS-001/080 + intro), CHANGELOG (ECHOS + racine), TRANSPORT_API (PRISM). Monographie non modifiée (snapshot figé). * feat(echos): jalon ph8 — échos-ui, les 6 Écrans (A→F) (#441) - stack : react-router-dom (routes A→F), echarts+echarts-for-react, lucide-react, zustand ; Vite proxy /api+/health → :5000 (dév.) ; code-splitting par écran + chunks vendor echarts/react. - src/api/ : client REST typé sur API_REST.md §3 (runs, métriques ?every=, export, décisions, causal-chains, croyances/relations, groups, phenomena, compare) ; 503/404 gérés ; controlClient = relais ECHOS→SYNE :5181 (jamais en direct). - src/ws/realtime.ts : client WS :5180 (reconnexion, tick, état SYNE). - src/store/ (zustand) : runs, KPI live, run sélectionné, état WS. - Écrans A→F : Dashboard (KPICards+gauges+timeline+phénomènes), Explore (Entités/Groupes/Communications, heatmap « à venir »), SocialGraph (graphe force-directed /relationships + inspecteur), Analysis (Métriques 8 moteurs / Causale profondeur ≤12 / Comparaison /compare), Control (pilotage relais + calibration + runs/export WS), Log (console 3 niveaux + limites de validité). - vues sans calcul de métrique ; 13 tests vitest/RTL verts (mock fetch+WS) ; eslint + tsc -b + build verts. - docs ECHOS : CHANGELOG ph8 + ISSUES ECHOS-080→085 → LIVRÉ (statuts). * docs(site): refonte GitHub Pages — landing LIVEX, thème DocFX surchargé (palette LIVEX, logo/favicon), Écrans A→F & FRONTEND_VISION publiés dans la navigation (#442) * docs(site): refonte GitHub Pages — landing LIVEX, thème DocFX surchargé (palette LIVEX, logo/favicon), docs Écrans A→F & FRONTEND_VISION publiées dans la navigation ### Landing (index.md) - Hero sombre + badge « Monorepo dotnet + python + typescript », tagline, description, 3 CTA (README / API REST ECHOS / Interface web pour echos-ui), **3 cartes modules** (SYNE sémantique — Simulation.Core ; ECHOS analyse ; PRISM rendu) en overlay (HTML dans le markdown DocFX), bandeau « Fonctionnalités » (6 lignes : déterminisme bit-à-bit, observation non intrusive, 7+8 moteurs de métriques, adéquation SYNE↔ECHOS, lien doc principes). ### Thème DocFX — overlay - **** : palette LIVEX () appliquée au thème DocFX (docfx.css Bootstrap) — variable-couples , fond /surface /bordure /texte /accent , navbar sombre, cartes , hero, badges, tableaux, code, footer ; police Inter + JetBrains Mono (chevauche cohérent avec ). - ** + ** (overlay : remplace DocFX par la marque LIVEX — 2 cercles reliés, palette ECHOS) ; multi-taille généré (16/32/48/64). - ** non requis** (le fournit la navbar) ; overlay appliqué via → . ### Navigation () - Section ECHOS enrichie : **FEATURE VISION orbitale & UI Désign** (les 6 Écrans A→F) publiées dans la nav, + rubriques Métriques/API REST/Tests ; section Transverse inchangée (docs clés) — étendu avec et dans le tableau ECHOS. ### Build - DocFX local : (Simulation.Core.xml → API .NET) puis error: FatalError: System.IO.FileNotFoundException: Cannot find config file /home/devops/Documents/Code/LIVEX/docfx.json at Docfx.Docset.GetConfig(String configFile) in /_/src/Docfx.App/Docset.cs:line 73 at Docfx.BuildCommand.<>c__DisplayClass0_0.<<ExecuteAsync>b__0>d.MoveNext() in /_/src/docfx/Models/BuildCommand.cs:line 25 --- End of stack trace from previous location --- at Docfx.CommandHelper.RunAsync(LogOptions options, Func`1 run) in /_/src/docfx/Models/CommandHelper.cs:line 42 at Spectre.Console.Cli.CommandExecutor.ExecuteAsync(CommandTree leaf, CommandTree tree, CommandContext context, ITypeResolver resolver, IConfiguration configuration, CancellationToken cancellationToken) in /_/src/Spectre.Console.Cli/Internal/CommandExecutor.cs:line 257 (0 erreur) ; vérifiés : index hero + 3 cards, toc.html, chaîne bootstrap clean, favicon/logo overlay au bon chemin. * docs(echos): FRONTEND_VISION — front-matter DocFX (title • accent paragraphe jalon ph8) ; aligne le h1 unique doc site ESLint conformité * docs(site): refonte complète GitHub Pages en landing SaaS — landing sur mesure hors DocFX (racine), branding LIVEX (logo, favicon, palette UI_DESIGN), sections Modules/Fonctionnalités/Performances/Roadmap/FAQ, responsive + animations JS ; document DocFX DocFX sous /docs/, assemblage assemble-pages.sh + workflow assemble-pages (landing racine + docs/) (#443) * docs(roadmap): cadrage Jalon U8 — assainissement du backlog (#444) Plage ECHOS fictive (080…093) rectifiée en 080…085 (ph8, livrés U7) + 090…092 (ph9) ; carte manquante SYNE-113 ajoutée (serveur de contrôle HTTP :5181, cible réelle du relais controlClient ECHOS) ; SYNE-110 précisé (hooks autoSaveEveryNTicks/maxBackups à brancher) ; ECHOS-085 annoté (livré côté UI, finalisation contre SYNE-113 en U8). * feat(syne): jalon U8 — persistance SQLite bit-à-bit (SYNE-110→112) (#445) - SqlitePersistenceStore : schéma V2.0 (11 tables, PRAGMA user_version=2), transactions atomiques, rotation maxBackups=5, reprise au dernier tick_states ; - SimulationSnapshot/Codec : capture déterministe monde+cognition+PRNG 4×64 (JSON stable, hash FNV-1a) ; - SimulationSnapshotRestorer : reprise exacte au tick N sans re-jouage, holdover LastDecision + réserves restaurées en place ; - Hook autoSaveEveryNTicks (défaut 1000) câblé dans SimulationLoop.AdvanceOneTick — aucun tirage PRNG ⇒ checksums épinglés inchangés ; - 5 PersistenceTests (320 Core, 329 totaux — reprise bit-à-bit, état RNG, reprise post-crash, schéma 11 tables, rotation) ; - docs : PERSISTENCE §3 recalé (health→energy/hunger/thirst/fatigue), TESTING 324→329, CHANGELOG, ISSUES SYNE-110/112 LIVRÉ * feat(syne): serveur de contrôle HTTP :5181 (SYNE-113) (#446) Serveur de contrôle non intrusif du moteur SYNE, contrat API_CONTRACTS §3 (ADR-002/003) : - SimulationFactory : résolution options (défauts → surcouche config → seed) + construction monde/entités/PRNG/boucle, identique au mode batch (bit-à-bit) ; - SimulationController : machine à états idle→running⇋paused→finished, boucle d'arrière-plan (ManualResetEventSlim + CancellationToken par run) — 0 tirage PRNG ajouté ⇒ trajectoire inaltérée (SYNE-081, DETERMINISM §3) ; - ControlServer : HttpListener BCL 127.0.0.1:5181, POST /api/control/start|pause|resume|reset + GET /status, erreurs JSON structurées ; - mode CLI --serve / --serve-port (défaut 5181) ; interop vérifiée contre le ControlClient ECHOS (finalise ECHOS-085) ; - 6 ControlServerWireTests (335 tests au total : 320 Core + 15 Console). * feat(syne): cycle des ressources — minéraux + régénération/dégradation (SYNE-070) (#447) - ResourceKind.Mineral (4e type, initial 0) + ResourceSettings enum-driven (ToStocks/Spec) - ResourceStocks.ApplyLifecycle(tick, settings) appliqué en fin de tick par SimulationLoop.AdvanceOneTick (ordre causal strict, 0 tirage PRNG) : régénération + regenerationRate/tick, dégradation périodique -regenerationRate x degradationTick a chaque degradationTick (clamp >= 0, inerte sans taux) - Persistance etendue : WorldSnapshotDto.MineralStock, codec Capture, restorer, SQLite WriteResources (4 types), observabilité resources[] (4 types) - engineVersion 0.7.0 ; checksums dores (perception + baseline ph10) inchangees, re-epingles pour pin contractuel (DETERMINISM §7) - Validation bornes resources.* (initial >= 0, regenerationRate >= 0, degradationTick > 0) - Tests : ResourceStocksTests +5, SimulationOptionsValidatorTests +1, PersistenceTests +1 (4 reserves dont mineral perseveres, regeneration restauree), assertions CognitionPipeline/Observability adaptees aux bornes de regeneration - Docs : DETERMINISM, CONFIGURATION §6.7, DATA_MODEL §8.1, SYSTEMS_SPEC §4, API_CONTRACTS §2.1, DECISIONS_V01 §2.4, ISSUES SYNE-070 LIVRE, TESTING (342), CHANGELOG (racine + SYNE), ROADMAP (racine + SYNE) Suite totale : 342 tests (327 Core + 15 Console) * feat(syne): constructions — obstacles statiques configurables + modification d'environnement tracée (SYNE-071) (#448) * test(syne): jalons de validation moteur T0-T5 (SYNE-122) (#449) T0 50 ent./1000 ticks sans crash + état valide déterministe ; T1 50/2000 croyances divergentes ; T2 traits -> décisions différentes en situation identique (curiosité [0,0] vs [2,2], divergence portée par Explore) ; T3 information locale (jamais hors portée) ; T4 reproductibilité benchmark ; T5 suite > 160 tests (370). Carte purement test : 0 tirage PRNG, engineVersion inchangé (0.8.0). MilestoneT0T5Tests (+8), suite 370 tests (353 Core + 17 Console), couverture 94.01 %. * feat(syne): cycle de saisons world.seasons (SYNE-072) (#450) world.seasons: ancien booléen mort -> bloc actif (enabled, seasonLengthTicks 360, initialSeason spring, cycle[] 4 saisons × facteurs/réserve). Saison = fonction pure du tick (0 tirage PRNG) ; SeasonFactors module régénération/dégradation (ResourceStocks.ApplyLifecycle, fin de tick) ; basculement tracé + drainé world.season_changed (tick exact) ; snapshot season/seasonIndex (additif) ; validation §6. engineVersion 0.9.0, checksums dorés inchangés (désactivé par défaut). +19 tests (SeasonTests, ObservabilitySeasonTests) — suite 389 (369 Core + 20 Console). * feat(syne): territoires world.territory_membership_changed (SYNE-073) (#451) * feat(livex): finalise le jalon U8 (#452) * feat(livex): complete U8 milestone * docs(livex): refresh project overview and setup guide * fix(ci): disable full coverage on isolated U8 smoke test * fix(echos): correction démarrage/contrôle + documentation (bundle existant) (#453) * Refactor echos startup and control mechanisms - Update installation and README documentation. - Create V0.1 audit roadmap. - Enhance API and frontend documentation. - Improve control client and ingestion logic. - Add new dev stack script for easier setup. - Update tests for analysis, API routes, and control client. * Fix startup and control issues in Echos module and update documentation - Improve CI workflow and enhance installation instructions. - Add new simulation configuration files and update related tests. - Refactor Echos API and ingestion logic for better performance. - Introduce new reporting functionality and tests for validation. - Update various components in the Echos UI for better integration. * fix(echos-ui): alignement des écrans sur le contrat snapshot SYNE (position imbriquée, ressources type/quantity, LiveAgent, garde anti-stale) (#454) * feat(echos): trace parquet dans le batch, scheduler d'analyse périodique et benchmark SYNE vs SYNE+ECHOS (#455) * fix(syne): repair test baselines and sqlite cleanup Refresh the deterministic golden values to match the reproducible current trajectory, and release pooled SQLite connections before deleting temporary databases on Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(syne): normalize deterministic logs across platforms Use explicit LF separators for hashed test logs so the pinned simulation checksums match on Windows and Linux. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(syne): expose prepared world and global snapshots Publish a versioned initial world with agents, cells, obstacles, resources, and tick rate; add the explicit prepare/ready control flow and include complete per-tick actions and world changes in the global snapshot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(echos): handle SYNE world initialization frames Validate and ignore the world_initialized prelude while aligning tick segments so the ECHOS ingestion pipeline can connect to the updated SYNE stream. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(syne-mock): simulate contracts with modular services Split world generation, agent decisions, destination selection, movement, and snapshots into services; preserve the HTTP/WebSocket contract and add deterministic scenarios and integration tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(git): répare la ligne .gitignore cassée et ignore les artefacts Unreal (#459) fix(git): répare la ligne .gitignore cassée et ignore les artefacts Unreal La ligne `*.logdocs/pages-dist/` supprimait d'un coup la règle `*.log` et l'exclusion du site DocFX généré : les logs n'étaient plus ignorés et le build de `docs-pages` réapparaissait dans `git status` à chaque publication. Ajoute aussi les exclusions des répertoires produits par Unreal (`Binaries`, `DerivedDataCache`, `Intermediate`, `Saved`, `Replays`, `StagedBuilds`, `.vs`, solutions Visual Studio) afin que l'hôte technique `prism/LDK/` puisse être versionné sans traîner ses ~10 Go de fichiers générés. * feat(prism): ajoute le plugin Unreal PRISM-LDK (PrismLdk) et son hôte technique de build (#460) feat(prism): ajoute le plugin Unreal PRISM-LDK (PrismLdk) et son hôte technique de build Première implémentation exécutable de PRISM. Le plugin `PrismLdk` expose à Blueprint le cycle de contrôle HTTP (5181) et la réception des contrats SYNE en WebSocket (5180) : `Prepare`/`Ready`/`Start`/`Pause`/`Resume`/`Stop`/`Reset`, `world_initialized`, snapshot global, deltas et événements. SYNE reste le moteur décisionnel et l'autorité de l'état ; le C++ du plugin se limite au transport, au parsing et à la conversion en types Blueprint. - `prism/LDK/` : hôte technique `LDK.uproject` (Unreal 5.8), `Config/`, module `LDK` et assets Blueprint de test. - `prism/LDK/Plugins/PrismLdk/` : module `PrismLdk` (Runtime, phase Default), `UPrismLdkSubsystem` + bibliothèque Blueprint + types de contrat. - `EngineAssociation` positionné à `5.8` : la valeur GUID d'origine (build source) empêchait l'ouverture sur une installation Unreal Launcher. - `.gitattributes` : `*.uasset`/`*.umap` déclarés binaires, une conversion de fin de ligne automatique corromprait ces assets ; LF garanti pour `*.sh`. - `docs/docs-prism/PRISM_UNREAL_IMPLEMENTATION.md` : guide d'intégration. Non validé : aucun runner Unreal 5.8 n'est disponible, la compilation du plugin reste à confirmer sur une installation Unreal locale. * docs(prism): acte l'adoption d'Unreal (ADR-002) et supersède l'ADR Godot (#461) docs(prism): acte l'adoption d'Unreal (ADR-002) et supersède l'ADR Godot L'ADR-001 (prototype Godot) était marquée « historique » sans qu'aucun ADR successeur ne prenne le relais : le choix du moteur définitif restait donc non tranché en gouvernance, alors même qu'un socle de code Unreal était livré (PR #460). - Nouvel `docs/docs-prism/adr/ADR-002-choix-unreal-prism-ldk.md` [Accepted] : contexte, décision, conséquences, risques, alternatives (Godot, Unity, non décision maintenue, ECHOS seul) et conditions de validation/réouverture. - ADR-001 marquée [Superseded] avec renvoi vers l'ADR-002 ; l'argument « Unity et Unreal surdimensionnés » est explicitement rattaché au périmètre du prototype. - Index ADR du composant mis à jour (nouveaux statuts par ADR). - ADR-003 / ADR-004 : la liste des routes et des formats est désormais explicitement celle de la proposition d'origine de la Monographie, avec renvoi vers le contrat courant. ADR-004 acte la diffusion multi-consommateur. - `ARCHITECTURE.md`, `VISION.md`, `GLOSSARY.md` : PRISM décrit comme projet Unreal final intégrant le plugin PRISM-LDK ; `prism/LDK/LDK.uproject` documenté comme hôte technique de build/test et non comme un second produit. - `CHANGELOG.md` racine : entrée de la décision d'architecture. * docs(prism): réécrit le dossier PRISM pour le projet Unreal et son plugin (#462) docs(prism): réécrit le dossier PRISM pour le projet Unreal et son plugin Le dossier `docs-prism` décrivait un prototype Godot sans rapport avec l'état réel du dépôt. Réaligné sur l'ADR-002 et sur le code livré en PR #460. - `README.md`, `ARCHITECTURE.md`, `VISION.md` : PRISM = projet Unreal final intégrant le plugin PRISM-LDK ; frontière explicite entre le plugin (interopérabilité Blueprint) et le projet PRISM (expérience et rendu) ; SYNE reste l'autorité de l'état. - `TRANSPORT_API.md` : contrats selon l'état courant — `world_initialized`, snapshot global par tick, deltas/événements, cycle `prepare`/`ready`/`start`/`pause`/`resume`/`stop`/`reset`, 5180/5181 par défaut. - `SCENE_SPEC.md`, `RENDERING_SPEC.md`, `VISUALIZATION_SPEC.md`, `UX_INTERACTION.md`, `ASSETS_CONVENTIONS.md` : spécifications recadrées en objectifs de présentation, sans prétendre que les fonctions sont livrées. - `TESTING.md` : stratégie de validation, avec la distinction explicite entre contrat (testable sans moteur) et rendu (non couvert en CI, aucun runner Unreal). - `ROADMAP.md` : 6 étapes d'évolution orientées intégration et validation, avec section de risques et réponses. - `CHANGELOG.md` du composant : réécrit en conservant les entrées plugin (PR #460) et ADR-002 (PR #461) et en restaurant la table de mises à jour. - `CHANGELOG.md` racine : entrée de la réécriture du dossier. Vérifié : aucun lien interne mort dans `docs/docs-prism/`. * docs(livex): réaligne la documentation transverse sur PRISM-Unreal et cadre syne-mock (#463) docs(livex): réaligne la documentation transverse sur PRISM-Unreal et cadre syne-mock Dernier volet documentaire de l'adoption d'Unreal (PR #461 et #462) : cohérence transverse et honnêteté sur ce qui est réellement implémenté. - `README.md`, `ARCHITECTURE.md`, `VISION.md`, `ROADMAP.md`, `FAQ.md`, `INSTALLATION.md`, `COMMUNICATION.md`, `SECURITY.md`, `CI_CD.md`, `CONTRIBUTING.md` : PRISM décrit comme projet Unreal final intégrant le plugin PRISM-LDK ; `prism/` et `syne-mock/` apparaissent dans l'arborescence ; `ARCHITECTURE.md` gagne une §2.4 (syne-mock) et une §6 réécrite. - `syne-mock` cadré explicitement comme outil de développement des contrats, pas un moteur : README, ARCHITECTURE §2.4, CONTRIBUTING §4 (checklist `npm test --prefix syne-mock`), CI_CD §2 et §5, ETHICS_AND_SCOPE §4.1. - `docs/docs-echos/{ISSUES,ROADMAP,TESTING}.md` : ECHOS-091 restreint à SYNE→ECHOS ; la validation PRISM-LDK et du projet Unreal relève d'un chantier distinct. Finit la contradiction « le runtime PRISM commence après U8 ». - `docs/docs_prototype/README.md` : bandeau d'archive. - `LIVEX-Monographie_SnapV0-1.md` : note de statut explicitant que la monographie est une référence conceptuelle historique et non prescriptive. - `docs/README.md` (nouveau) : portail séparant références courantes et archives, avec la règle de préséance en cas de divergence. - `FAQ.md` : §9 remplace « Pourquoi pas Unreal/Unity ? » par la distinction LIVEX/PRISM/PRISM-LDK, avec renvoi vers l'ADR-002 pour la justification ; §10 explique le mock ; renumérotation 1→13. - `docs/site/index.md` : carte PRISM en « Visualisation Unreal ». - `CHANGELOG.md` racine : entrées transverse et portail, sans écraser celles des PR #461 et #462. Vérifié : aucun lien interne mort hors gabarits Liquid `{{_rel}}` de `docs/site/index.md` (préexistants) ; les occurrences restantes de « Godot » sont dans des archives explicitement signalées (ADR-001, `docs_prototype`, Monographie, DECISIONS_V01 §2.28) ou dans le contexte historique de l'ADR-002. * chore(echos): verrouille les dépendances Python (uv.lock) (#464) chore(echos): verrouille les dépendances Python (uv.lock) Le lockfile était présent dans le checkout mais non suivi, ce qui rendait les résolutions locales non reproductibles alors que `echos-ui/package-lock.json` est versionné depuis le début. - 36 paquets épinglés avec empreintes SHA-256. - `requires-python = ">=3.11"`, cohérent avec `pyproject.toml`. - Le groupe de développement (flake8, pytest, pytest-cov) est verrouillé, donc les mêmes versions que celles qu'installe la CI via `requirements-dev.txt`. La CI continue d'utiliser `pip install -r requirements-dev.txt` : le lockfile sert la reproductibilité du développement local. Le passage de la CI à `uv` est hors périmètre. * fix(syne-mock): libère les ressources du test et aligne les assertions (#465) fix(syne-mock): libère les ressources du test et aligne les assertions `npm test --prefix syne-mock` ne se terminait jamais : après la fin des assertions, 2 serveurs TCP et 3 sockets restaient ouverts, si bien que `node --test` ne rendait jamais la main. La commande était donc inutilisable et masquait 4 échecs réellement présents sur `develop`. - `createServer().close()` termine les clients WebSocket connectés, purge les connexions HTTP en keep-alive et chaîne les rappels de fermeture, afin que `close()` ne promette que lorsque les sockets sont réellement libérés ; - les tests de serveur libèrent leur instance via `t.after()` (y compris en cas d'échec d'assertion) et attendent la fermeture du client WebSocket ; - les assertions d'obstacles attendent le champ `type`, que `WorldDescription` publie déjà. * fix(syne-mock): pose les agents sur les cases publiées comme franchissables (#466) fix(syne-mock): pose les agents sur les cases publiées comme franchissables `createInitialAgents` ne validait ses positions candidates que contre les obstacles, jamais contre le relief : un agent pouvait apparaître sur une cellule `sea` (`walkable: false`). La fonction évaluait aussi la position brute alors que le monde publie la position arrondie, si bien que l'arrondi pouvait faire basculer l'agent dans une case voisine bloquée. Deux critères de test disjoints faisaient désaccord : - le placement utilisait `isPositionBlocked`, qui compare le point au cercle ; - la grille publiée utilisait `isCellBlocked`, qui compare le centre de case au cercle augmenté de la demi-cellule. Un agent pouvait donc être validé au placement et déclaré non franchissable par `WorldDescription`, ce qu'exprime exactement le test `world generation places resources and agents only on walkable cells`. Le placement s'appuie désormais sur `cells[].walkable`, indicateur publié par `WorldDescription` : obstacles et mer passent par la règle exposée, et aucune divergence entre les deux n'est plus possible. `obstacles` n'est plus requis par la fonction, et la grille de terrain n'a jamais eu besoin d'être passée. Vérification : 300 graines x 5 densités x 2 configurations d'obstacles (324 600 positions) : 3 452 agents sur case non franchissable avant, 0 après, génération toujours déterministe. Test de non-régression ajouté sur 5 graines, vérifié en échec sur l'état précédent. * ci: exécute la suite syne-mock et publie le guide d'intégration Unreal (#467) ci: exécute la suite syne-mock et publie le guide d'intégration Unreal `CI_CD.md` §2 annonce un job CI `syne-mock` et `CONTRIBUTING.md` §4 rend `npm test --prefix syne-mock` obligatoire pour toute modification du composant. Aucun des deux n'était exécuté. Le job peut désormais l'être : la commande se termine (PR #465) et la suite est verte (PR #466). - `ci.yml` : `syne-mock/` rejoint la boucle de détection des composants, avec sortie `syne_mock` (le `-` est converti en `_`, une clé de sortie ne pouvant pas contenir de tiret dans une expression) ; nouveau job `Tests (SYNE-MOCK Node)` sur `ubuntu-latest`, `npm ci` puis `npm test`, avec `timeout-minutes: 5` en garde-fou contre une régression de type fuite de descripteurs ; - `sync-docs.sh` : `PRISM_UNREAL_IMPLEMENTATION.md` publié dans `articles/prism/`, et `toc.yml` l'expose sous « Intégration Unreal (PRISM-LDK) ». Le guide Blueprint du plugin, référencé par `ARCHITECTURE.md`, était inaccessible sur le site ; - `docs-pages.yml` : `prism/**` déclenche désormais le build du site, la documentation contractuelle étant écrite contre ce code ; - `syne-mock/README.md` : la commande de test renvoie vers le job CI. Au passage, la section `## [Unreleased]` du CHANGELOG cumulait des sous-sections dupliquées (`### Changed` x3, `### Added` x2) et une ligne blanche parasite ; sections regroupées et ordonnées `Added` -> `Changed` -> `Fixed` -> `Deprecated`, et coquille « formality » corrigée en « formalise ». Vérifié : `ci.yml`, `docs-pages.yml` et `toc.yml` parsent, `bash -n sync-docs.sh` passe, le script publie bien le guide, et la commande exacte du job (`node --test test/*.test.js` dans `syne-mock/`) sort en 0 avec 12 tests verts. * ci: declenche la CI sur les PR visant main (#468) La CI ne se declenchait que sur develop. La protection de branche « branche a jour + CI verte » de main ne peut donc pas etre appliquee : une PR de release ou de hotfix n-executerait aucun check, et le merge resterait bloque sur un status attendu qui n'arrive jamais. `main` est ajoute aux branches de `pull_request` et de `push`, ce qui rend la regle enforceable. Les jobs restent filtres par composant, donc une PR de release ne construit que ce qu'elle touche. Aucun changement de job ni de condition. * docs(ci-cd): documente les protections de branche actives (#469) `main` et `develop` sont desormais couverts par les rulesets `mainRules` et `developRules`, en enforcement active. Le document annoncait « echec = blocage (protection de branche) » sans jamais dire de quelle protection il s'agissait, ni quels checks sont exiges. La nouvelle section 2.1 detaille les cinq regles en vigueur, les deux checks exiges et pourquoi les jobs par composant ne le sont pas (ils rapportent `skipped` hors perimetre), ainsi que le retrait de `required_signatures` et sa raison. Consigne de maintenance ajoutee : renommer `Composants modifies` ou `Structure & conventions (transverse)` bloque tous les merges jusqu'a mise a jour du ruleset. * fix(adr-001): corrige la coquille « formality » et ajoute le saut de ligne final (#470) L'entree de CHANGELOG.md qui annoncait la correction de « qui formality ce choix » decrivait en realite la coquille du CHANGELOG lui-meme. Le fichier ADR vise, docs/docs-prism/adr/ADR-001-choix-godot.md, portait toujours « formality » et n'avait jamais ete corrige. Corrige en « formalise », et ajoute le saut de ligne final manquant sur cet ADR et sur docs/docs-prism/adr/README.md, tous deux sans terminaison. Detecte en comparant le stash de securite stash@{0} (wip-prism-unreal) aux fichiers merges sur develop : le stash est un sous-ensemble strict de develop, donc rien d'utile n'y est encore, et le rapprochement a fait ressortir la coquille. Co-authored-by: protection-test <protection-test@example.com> * fix(syne-mock): applique la carte publiee au deplacement des agents (#471) Le deploiement deplace les agents sans jamais consulter la carte que WorldDescription publie. Quatre defauts distincts : - isPositionBlocked etait appele sans cellSize, donc la branche `shape` comparait des coordonnees NaN et laissait traverser les sept formes d'obstacle, alors que la version circulaire bloquait ; - canEnter ignorait cells[].walkable, donc les agents traversaient la mer ; - le cout de terrain etait ignore : une riviere (movementCost 4) se traversait a la vitesse de la plaine ; - un deplacement refuse etait facture : l'energie baissait de moveEnergyCost meme quand l'agent n'avait pas bouge. cell-grid.js centralise l'indexation de cells[] (y * cellCountX + x), partagee par le placement et le deplacement. L'inversion x * cellCountX + y etait auto-coherente sur une carte carree mais faisait chevaucher des cles sur une carte rectangulaire. L'arrondi est desormais applique avant le test, pour que la position validee soit celle que le snapshot publie. Le cout retenu pour borner le pas est le plus eleve entre la case de depart et la case visee : entrer dans une riviere ralentit, en sortir aussi. Une case non franchissable donne un budget nul. Seul un mouvement effectif est facture ; un blocage est reporte via outcome: 'blocked'. La generation du monde est inchangee : empreintes SHA-256 identiques avant et apres sur 5 graines x 4 configurations, dont une carte rectangulaire 300x180. movement.test.js ajoute 10 tests (12 -> 22). Co-authored-by: protection-test <protection-test@example.com> * fix(syne-mock): rend le demarrage transactionnel, borne le journal et corrige l age des objectifs (#472) Trois defauts de cycle de vie, sans rapport entre eux mais tous visibles par un client de controle. 1. start() laissait un run actif apres un echec. `loadReplay` leve sur un fichier absent ou une ligne JSON malformee ; il etait appele apres `state = 'running'` mais avant `startTimer()`. Le resultat etait un run declare actif sans timer : rien ne tickait, et tout appel ulterieur a start() etait rejete au motif que le run etait deja actif. Le chargement du replay precede desormais l'entree en running, et tout ce qui le precede est reecritable sans consequence. Apres un echec, le monde reste prepare et acquitte, et un nouvel appel se comporte comme le premier. 2. `this.events` n'etait pas borne. Deux evenements par agent et par tick etaient conserves pendant toute la duree du run : 202 200 evenements sur 2 000 ticks x 50 agents, heap 66 Mo. `diagnostics.maxEvents` (defaut 2 000) borne le tampon a 2 000 evenements, soit heap 18 Mo sur le meme run. La troncature vide jusqu'a mi-capacite plutot que d'un seul element, pour ne pas decaler tout le tampon a chaque emission. Le flux diffuse (WebSocket) reste la source faisant autorite : ce tampon est un diagnostic, pas l'historique. 3. `goals[].age` valait le tick absolu. La liste etant reconstruite a chaque tick, `age` etait toujours egal au tick courant et ne disait rien de la duree d'un but. `intentionSince` suit le dernier changement d'intention et `age` devient le nombre de ticks ecoules depuis : 15 a 24 au tick 2 000 d'un run de reference, au lieu de 2 000. Le marqueur reste interne, le snapshot publiant une liste de champs explicite. lifecycle.test.js ajoute 8 tests (22 -> 30). Co-authored-by: protection-test <protection-test@example.com> * docs(syne-mock): rectifie le contrat consomme et liste les simplifications assumees (#473) Le contrat decrit ce que le mock publie, donc ce qu'un client PRISM ou ECHOS branche dessus. Deux de ses affirmations etaient fausses ou incompletes, et un consommateur pouvait s'y fier. - Le document annoncait que le mock n'expose pas de type de terrain et que les cellules utilisent `terrainType: "plains"`. C'est faux : le mock publie trois profils, `plains` (cout 1), `river` (cout 4) et `sea` (`walkable: false`, cout infini), et le pas est borne par le cout de terrain. Le tableau des profils est ajoute, avec la regle d'entree et de sortie de riviere et la frontiere mer, en distinguant ce qui appartient au mock de ce qui appartient a SYNE. - La liste des actions a mapper en `UENUM` n'en citait que 5 sur 9 : `SeekFood`, `SeekWater`, `Flee` et `Socialize` manquaient, alors que le contrat les publie des qu'elles se produisent. Les 9 sont listees, avec pour chacune sa condition de candidature et son premier tick de production, mesure sur la graine 42 avec 50 agents et non deduit du code. Deux impossibilites sont explicites : `Flee` est structurellement inatteignable, car `safetyDriftRate` est positif alors que `safety` demarre a sa borne haute et ne peut donc jamais passer sous 0.5 ; `Socialize` n'est produite qu'au tick 943, donc hors du `maxTicks: 400` par defaut. - Nouvelle section « Perimetre reel et simplifications assumees » : la mort, la perception, le contenu des communications, la decision de groupe, les livres, les territoires, les ressources locales, l'echelle temporelle et le pathfinding sont des elements decoratifs, et `simulation.events` un tampon de diagnostic borne. Ces elements sont publies dans le contrat comme s'ils portaient du sens ; la section dit desormais ce qu'un client ne doit pas encore interpreter. - Le comportement d'un `start` refuse est documente dans la section HTTP : le monde reste `ready` et reutilisable, donc un client peut reessayer sans appeler `stop`. Co-authored-by: protection-test <protection-test@example.com> * feat(syne-mock): besoins de depart configurables, fini les 15 s d'Idle initial (#474) Les agents passaient 146 ticks sans rien faire au debut d'un run. Les besoins de depart etaient codes en dur dans createInitialAgents et curiosity partait de 0 : il fallait que curiosityDriftRate (0.002) amène la valeur au seuil d'exploration de 0.3, soit 150 ticks, ou 15 s a ticksPerSecond 10. - agentSimulation.needs.initial rend les six besoins de depart configurables, avec les domaines qu'ils bornent deja (0..100 pour hunger/thirst/fatigue, 0..1 pour safety/social/curiosity). Une valeur absente retombe sur l'etat historique du mock, une valeur hors domaine est refusee a la generation du monde, comme les autres cles de configuration. - curiosity passe de 0 a 0.3 par defaut, exactement le seuil d'exploration : les agents se mettent en mouvement au tick 1 et plus aucun Idle n'est produit. Eat 100, Drink 72, Rest 234 et Socialize 943 sont inchanges. - curiosityDriftRate passe de 0.002 a 0.001, le cout de ce decalage : explorer des le premier tick sature curiosity plus vite, et un besoin sature garde une utilite superieure a celle de Rest, qui devient alors jamais produit. Mesure sur 2000 ticks, 0.002 supprime Rest du flux alors que 0.001 conserve le repertoire complet d'actions. Le placement des agents ne lit que la graine et la carte : les besoins de depart decalent la trajectoire d'un agent, pas l'endroit ou il apparait. Generation du monde byte-identique avant/apres sur 5 graines x 2 tailles dont 300x180, run deterministe a l'identique sur 2 processus distincts. +4 tests dans test/server.test.js, suite verte. Co-authored-by: protection-test <protection-test@example.com> * fix(syne-mock): diffuser le snapshot avant les evenements du tick (#475) Le mock emettait les evenements du tick avant son snapshot. SYNE (ObservabilityTickEmitter) et API_CONTRACTS.md §2 imposent l'inverse, et tout consommateur qui aligne le flux sur les ticks le refuse : ECHOS rejetait le mock des la premiere trame avec TickAlignmentError: message event invalide (conforme API_CONTRACTS.md) : evenement decision_made recu avant le premier snapshot step() regroupe desormais les evenements du tick, diffuse le snapshot puis tick_summary, puis les evenements de ce tick. L'ordre des evenements entre eux et le tampon de diagnostics sont inchanges, stepReplay() n'est pas touche, et le contenu par tick reste identique (hash canonique inchange sur 120 ticks) : seul l'ordonnancement change. Verrouille par deux tests qui echouent tous deux sur l'ancien code : - syne-mock/test/stream-order.test.js : ordre exact des trames, invariant d'alignement et invariance du tampon de diagnostics ; - echos/echos/tests/test_syne_mock_integration.py : le vrai client ECHOS ingere le mock de bout en bout (controle HTTP, WebSocket, SQLite, Parquet, API REST, calibration), sans build .NET. Le mock devient donc utilisable pour travailler sur ECHOS : pointage par SYNE_OBSERVABILITY_URL / SYNE_CONTROL_URL, procedure documentee dans syne-mock/README.md, limites de simulation assumees (beliefs/trust vides). Nouveau job CI "Integration mock -> ECHOS" sur toute PR touchant syne-mock/ ou echos/, distinct du job U8 qui reste sur le moteur .NET. Co-authored-by: protection-test <protection-test@example.com> * fix(echos): revue complète du composant (moteurs, provenance, API, interface) (#477) Deux bugs rendaient des fonctions centrales inopérantes : `/api/compare` renvoyait 500 sur tout run contenant un événement (la décompression décomptait six colonnes pour un zip de sept), donc la comparaison de reproductibilité était inaccessible sur tout run réel ; et `AnalyticsStore.runs()` levait `int(None)` sur un run sans tick, ce qui rendait l'API entière inopérante sur une base fraîche ou un run en cours d'acquisition. Sept métriques restaient à 0 sur tout run réel parce que le snapshot ne portait que le tick courant, jamais `history` ni `communityHistory` — la fixture de test les fournissait artificiellement, ce qui masquait le problème. `_RollingContext` construit et borne désormais trois fenêtres glissantes. Le dénominateur des taux de groupe ne dépend plus de la charge (il valait 1000 ticks sur un run calme et 20 sur un tick chargé, soit un facteur 50 sur la même métrique) : la fenêtre est bornée en ticks et sa durée réellement observée est publiée dans le snapshot. Les singletons n'étaient plus comptés comme communautés, `DecisionDiversity` était calculée sur les objectifs, `SystemComplexity` n'était pas borné, `_availability(100, None, 0)` renvoyait 1e11 et contaminait la moyenne du moteur de durabilité, et un cycle d'import existait entre `emergence` et le registre des moteurs. Ajout de la provenance `measured` : `analysis.provenance()` calcule par couple (moteur, métrique) si la valeur servie est une mesure ou le repli neutre du moteur faute de fenêtre, depuis les mêmes entrées que le calcul lui-même. Sans ce signal, l'interface ne pouvait pas distinguer un `0` observé d'un repli. Persisté par tick (`tick_metrics.measured`, schéma SQLite v5, migration additive) et publié par `/api/runs/{id}/metrics` et `/api/runs/{id}`. Évol adhésion MINOR : champ ajouté, aucun consommateur existant n'est cassé. Robustesse : cadences nulles qui levaient `ZeroDivisionError` ou étaient silencieusement ignorées, fuite de descripteurs (`EchosLogger` sans `close()`), reconnexion toutes les 100 ms quand SYNE est arrêté, fin de flux détectée par préfixe de libellé d'erreur, et `pyarrow` importé mais non déclaré dans `pyproject.toml` (un `pip install echos` produisait un paquet qui ne démarrait pas). `dev_ingest` valide désormais sa configuration avant toute I/O, avec sortie 2 distincte. Les identifiants de groupe (`members`, `leaderId`, entiers côté transport) sont normalisés en chaînes, sinon ils ne pouvaient jamais être joints à `Agent.id` — `"3" != 3`. Même normalisation pour `Territory.members` et `Book.author_id`/`readers`. Interface `echos-ui` : l'export « CSV » téléchargeait une enveloppe JSON illisible par tout tableur ; `beliefs`/`relationships`/`phenomena` appelaient l'API sans `run_id` et affichaient donc les données du run le plus récent sous le nom du run sélectionné ; le cache de métriques ignorait la cadence dans sa clé et fusionnait des séries d'échantillonnages différents, produisant des `NaN` rendus comme des zéros ; le graphe social relançait une requête par membre en série à chaque tick ; la jauge de vitesse de diffusion alertait en rouge un monde qui propageait bien ; `disconnect()` se reconnectait 2 s plus tard et `usePhenomena` affichait « aucun phénomène détecté » sur un échec réseau. `npm test` lance `vitest run` : le mode interactif ne termine jamais et accrochait la CI. Tests : 233 → 283 (couverture 93 %, seuil 80 %), flake8 propre ; interface 18 → 61 tests sur 14 fichiers, eslint et `tsc` propres. Les deux scénarios d'intégration (SYNE réel et syne-mock) passent et vérifient désormais la provenance et la normalisation des groupes contre les émetteurs réels. Rapport complet dans `echos/ECHOS-REVIEW.md`, qui arbitrage aussi les points laissés ouverts et leurs raisons. * chore(docs): supprime DocFX et la publication GitHub Pages (#478) Retire docs/site/ (source DocFX), docs/landing/ (landing SaaS), docs/pages-dist/ (artefact d'assemblage commite malgre .gitignore) et le workflow .github/workflows/docs-pages.yml. 51 fichiers suivis supprimes. - .gitignore : entree docs/pages-dist/ devenue inutile retiree - CHANGELOG.md : section Removed + entrees [Unreleased] obsoletes retirees - echos/ECHOS-REVIEW.md : la note sur docs/pages-dist/ est replacee dans son contexte historique Les documents markdown ecrits a la main (docs-syne, docs-echos, docs-prism, adr, governance) sont conserves : ce sont les sources, pas des artefacts. * fix(syne): revue complète du moteur (déterminisme, cycle de vie, observabilité, HTTP) (#476) Revue et refactor du moteur SYNE. Les défauts ci-dessous sont groupés par famille. Chacun est couvert par un test vérifié détecteur : le défaut est réintroduit temporairement dans le code, le test doit devenir rouge, puis le correctif est restauré. Ce que je n'ai pas su reproduire est dit comme tel plutôt que présenté comme couvert. 1. DETERMINISME SplitMix64.Gamma/Avalanche et l'implémentation FNV-1a étaient dupliqués sur six sites, constantes recopiées : une divergence future aurait produit deux hachages pour la même valeur. Centralisés dans SplitMix64 et le nouveau Fnv1a64, sans effet sur les trajectoires. La cause unique de l'écart de trajectoire était neutralisée : la garde de rejeu de la communication existait mais n'était jamais appliquée. Le destinataire d'un message le relaye donc une seconde fois. CanRelay applique désormais HasRelayed, et la file de messages devient bornée (« plus récent gagne ») au lieu de croître sans limite. Réépinglage selon DETERMINISM.md §7 : percepts 0x27fad50065d8c4a4 -> 0xdb57f58566418f5d, état Ph10 0x072a488aa18c05eb -> 0x88bbc67950002bab, EngineVersion 0.11.0 -> 0.12.0. Piège de déterminisme : la cellule de SpatialGrid était dimensionnée par agents.perception.radius. Or QueryCircle renvoie les voisins dans l'ordre de parcours des cellules, qui décide de l'ordre de considération des perceptions. Régler la portée de la perception modifiait donc silencieusement l'évolution du monde. agents.perception.spatialCellSize devient un paramètre explicite, défaut 50 (égal au rayon par défaut : trajectoire de référence inchangée, ce qui évite un réépinglage supplémentaire). 2. VALIDATION Les contrôles de plage s'écrivent « value is < 0.0 or > 1.0 ». En IEEE-754 toute comparaison avec NaN est fausse : « NaN is < 0.0 or > 1.0 » vaut false, donc un NaN franchissait la validation puis se propageait dans les distances, l'énergie et la Barclay, corrompant le monde sans lever d'erreur. Le validateur balaie maintenant tout le graphe d'options par réflexion, ce qui couvre aussi les champs ajoutés ultérieurement, et tolerate les chemins en camelCase comme le contrat de configuration. worldCellSize et le nouveau spatialCellSize n'étaient pas validés du tout. 3. CYCLE DE VIE DU CONTRÔLEUR La boucle de tick était lancée en « feu et forget » : la tâche n'était jamais conservée. Un second StartAsync superimposait une deuxième boucle sur le même monde, Stop n'annulait que la dernière CancellationTokenSource en laissant l'ancienne boucle active, cette ancienne boucle pouvait ensuite repasser l'état à Finished par-dessus un run plus récent, et DisposeAsync simulait l'attente avec Task.Delay(20). La tâche est maintenant conservée, une génération de run est vérifiée avant toute écriture d'état partagé, un second démarrage est refusé sur run actif, et StopAsync/ResetAsync/DisposeAsync attendent réellement la fin de boucle. ControlServer répond 200 sur stop après l'arrêt effectif. 4. HTTP DE CONTRÔLE RootElement était renvoyé sans Clone() ni Dispose() : propriété invalide dès la fin de vie du JsonDocument, une fuite par requête. Aucun plafond de taille n'existait : un Content-Length ou un transfert par blocs arbitrairement grand était lu intégralement en mémoire (1 Mio, 413 payload_too_large, lecture bornée pour les blocs). Un JSON malformé ou un type de configuration incompatible remontait en 500 au lieu de 400. 5. OBSERVABILITÉ Un WebSocket n'accepte qu'un SendAsync à la fois : deux diffusions concurrentes levaient InvalidOperationException, non rattrapée, et tuaient le processus. Sérialisation par client, envois bornés dans le temps, retrait des clients dans le finally du drain (auparavant un client déconnecté restait au dictionnaire et son socket n'était jamais fermé), fermeture réellement attendue, Start/DisposeAsync idempotents. L'émetteur ne faisait pas confiance au sink pour être borné : un client lent figeait la simulation, sans plafond. La capture est sautée quand aucun client n'est connecté, mais les tampons du tick sont toujours vidés : la couche d'observabilité en est le seul consommateur, sans quoi ils croissent sans borne et rejouent des événements obsolètes. 6. CONFIGURATION ET AUTRES La fusion de configuration sparse était destructive : le corps était désérialisé en SimulationOptions avant fusion, donc chaque clé absente prenait la valeur par défaut du type et un client ne pouvait surcharger un champ sans détruire silencieusement tous les autres réglages. MergeJson fusionne récursivement, et le JSON brut est transporté jusqu'à la fusion. ResourceStocks consommait partiellement face à un stock insuffisant ; ActionExecutor appliquait les bénéfices avant l'échec d'une réserve ; la grille confondait les comptes et bornes X/Y ; les IDs de naissance n'étaient pas uniques ; les territoires n'étaient pas persistés, donc une restauration perdait toutes les zones et réassignait « Communes » (SchemaVersion 4). A* autorisait une diagonale alors que les deux orthogonales étaient bloquées : le pas rase le point d'appui entre deux cellules solides. PhaseCount valait 8 pour une énumération de 7 phases. `--seed -1` produisait une trace d'appels plutôt qu'un message. 7. LE PIÈGE QUE SEUL LE TEST D'INTÉGRATION A VU Une première version de la validation CLI refusait « --observe-port sans --observe ». C'est faux : en mode --serve, Program démarre l'observability sur --observe-port, et le contrat d'intégration SYNE → ECHOS lance exactement « --serve --serve-port P --observe-port Q ». Le job CI syne-echos-u8-integration échouait alors sur un défaut de validation, pas de moteur, et SYNE refusait ses arguments sans ouvrir aucun port. Une suite unitaire entièrement verte ne prouve pas qu'un contrat transverse est préservé. Ce que j'avais laissé passer en commit est ce piège, pas un bug du moteur : la validation est correcte, c'est ma règle qui était fausse, parce que j'avais supposé que le port d'observation n'avait qu'un seul mode consommateur sans avoir vérifié qui le consommait. Corrigé, avec un test qui verrouille les deux combinaisons. C'est aussi ce qui m'a fait suspecter un auto-blocage possible du chemin stop (le client ECHOS appelle stop alors qu'il ne lit plus le WebSocket, et la requête HTTP a un timeout de 2 s) : vérifié empiriquement, 5 exécutions consécutives vertes. 132 tests ajoutés (466 -> 598) ; suite SYNE à 553 tests, verte en Release avec --warnaserror. Trois tests détectaient d'abord le bon bug pour la mauvaise raison et ont été réécrits ; deux correctifs sont défensifs et le disent (disparition intra-tick de groupe, culture invariante sur drapeaux entiers) ; aucun n'est présenté comme vérifié par mutation quand il ne l'est pas. REVIEW-REFACTOR-REPORT.md détaille chaque point. * feat(syne): implémentation des 5 ADR cognitifs acceptés|Implémente les 5 ADR acceptés du rapport éléments ouverts V0.1 : primitives atomiques Take/Give/Trade/Attack/Defend (D7), inventaire à capacité pondérée (D8), bibliothèque de plans means-end (D3), engagements communicationnels Request/Response avec confiance (D5) et politique de saillance (D2). Catalogue Agents.Actions.* à drapeaux défaut-faux : la trajectoire de référence reste bit-à-bit identique (checksums dorés intacts), engineVersion 0.14.0. 13 nouveaux tests. Closes #481 (#495) 🤖 Generated with Codebuff Co-authored-by: Codebuff <noreply@codebuff.com> * fix(syne): observabilité 0.3.0, persistance additive et cycle de vie des runs (#496) * feat(syne): implémentation des 5 ADR cognitifs acceptés|Implémente les 5 ADR acceptés du rapport éléments ouverts V0.1 : primitives atomiques Take/Give/Trade/Attack/Defend (D7), inventaire à capacité pondérée (D8), bibliothèque de plans means-end (D3), engagements communicationnels Request/Response avec confiance (D5) et politique de saillance (D2). Catalogue Agents.Actions.* à drapeaux défaut-faux : la trajectoire de référence reste bit-à-bit identique (checksums dorés intacts), engineVersion 0.14.0. 13 nouveaux tests. Closes #481 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * fix(syne): observabilité 0.3.0, persistance additive et cycle de vie des runs|Le serveur de contrôle expose le seed et un cycle de vie durci ; le contrat d'observabilité passe à 0.3.0 (inventory/commitments sous drapeaux, sortie identique drapeaux éteints) ; la persistance devient additive sans rompre les hash de snapshots ; pins de version re-calés (0.14.0/0.3.0). 569/569 tests verts, checksums dorés 0x46769cfb11c8b3a7 / 0xe62395429b50b7c1 inchangés. Closes #486 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> --------- Co-authored-by: Codebuff <noreply@codebuff.com> * chore(echos): ingestion 0.3.0, stockage et calibrage (#497) * feat(syne): implémentation des 5 ADR cognitifs acceptés|Implémente les 5 ADR acceptés du rapport éléments ouverts V0.1 : primitives atomiques Take/Give/Trade/Attack/Defend (D7), inventaire à capacité pondérée (D8), bibliothèque de plans means-end (D3), engagements communicationnels Request/Response avec confiance (D5) et politique de saillance (D2). Catalogue Agents.Actions.* à drapeaux défaut-faux : la trajectoire de référence reste bit-à-bit identique (checksums dorés intacts), engineVersion 0.14.0. 13 nouveaux tests. Closes #481 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * fix(syne): observabilité 0.3.0, persistance additive et cycle de vie des runs|Le serveur de contrôle expose le seed et un cycle de vie durci ; le contrat d'observabilité passe à 0.3.0 (inventory/commitments sous drapeaux, sortie identique drapeaux éteints) ; la persistance devient additive sans rompre les hash de snapshots ; pins de version re-calés (0.14.0/0.3.0). 569/569 tests verts, checksums dorés 0x46769cfb11c8b3a7 / 0xe62395429b50b7c1 inchangés. Closes #486 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * chore(echos): ingestion 0.3.0, stockage et calibrage|Champs optionnels inventory/commitments dans les modèles d'ingestion (rétro-compat 0.2.1 conservée), routes et service UI (echos-serve), invalidation inter-processus du cache de séries via PRAGMA data_version, calibrage de fin de run et viabilité. Suite ECHOS verte, couverture 93,16 %. Closes #485 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> --------- Co-authored-by: Codebuff <noreply@codebuff.com> * fix(echos-ui): écrans d'analyse gelés, retard croissant et contrôles Live/Actualiser (#498) * feat(syne): implémentation des 5 ADR cognitifs acceptés|Implémente les 5 ADR acceptés du rapport éléments ouverts V0.1 : primitives atomiques Take/Give/Trade/Attack/Defend (D7), inventaire à capacité pondérée (D8), bibliothèque de plans means-end (D3), engagements communicationnels Request/Response avec confiance (D5) et politique de saillance (D2). Catalogue Agents.Actions.* à drapeaux défaut-faux : la trajectoire de référence reste bit-à-bit identique (checksums dorés intacts), engineVersion 0.14.0. 13 nouveaux tests. Closes #481 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * fix(syne): observabilité 0.3.0, persistance additive et cycle de vie des runs|Le serveur de contrôle expose le seed et un cycle de vie durci ; le contrat d'observabilité passe à 0.3.0 (inventory/commitments sous drapeaux, sortie identique drapeaux éteints) ; la persistance devient additive sans rompre les hash de snapshots ; pins de version re-calés (0.14.0/0.3.0). 569/569 tests verts, checksums dorés 0x46769cfb11c8b3a7 / 0xe62395429b50b7c1 inchangés. Closes #486 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * chore(echos): ingestion 0.3.0, stockage et calibrage|Champs optionnels inventory/commitments dans les modèles d'ingestion (rétro-compat 0.2.1 conservée), routes et service UI (echos-serve), invalidation inter-processus du cache de séries via PRAGMA data_version, calibrage de fin de run et viabilité. Suite ECHOS verte, couverture 93,16 %. Closes #485 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> * fix(echos-ui): écrans d'analyse gelés, retard croissant et contrôles Live/Actualiser|Trois causes racines corrigées : cache de séries jamais invalidé entre processus (retard croissant 155→494 ticks), liste des runs chargée une seule fois (le run démarré n'apparaissait jamais), et refetch complet à chaque tick WS (tempête de requêtes). Ajout des boutons Actualiser et bascule Live/Figé. Validation réelle sur un run de 7 600 ticks : retard stable 14-35 ticks, 1 req/2 s mesurée. 62/62 tests UI. Closes #480 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com> --------- Co-authored-by: Codebuff <noreply@codebuff.com> * feat(echos): shell de bureau Electron (ADR-003), packaging et CI (#499) * feat(syne): implémentation des 5 ADR cognitifs acceptés|Implémente les 5 ADR acceptés du rapport éléments ouverts V0.1 : primitives atomiques Take/Give/Trade/Attack/Defend (D7), inventaire à capacité pondérée (D8), bibliothèque de plans means-end (D3), engagements communicationnels Request/Response avec confiance (D5) et politique de saillance (D2). Catalogue Agents.Actions.* à drapeaux défaut-faux : la trajectoire de référence reste bit-à-bit identique (checksums dorés intacts), engineVersion 0.14.0. 13 nouveaux tests. Closes #481 …
Owner
Author
|
Fermée : conflits add/add non résolvibles en ligne. Remplacée par une PR à partir de la branche de synchronisation qui porte le merge résolu. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexte
La PR #531 (nettoyage de structure documentaire) a été squash-mergée sur
main(base par défaut du dépôt). Cette PR resynchronisedevelopsur ce même état.Contenu
main— nettoyage de structure (docs/{presentation,governance,adr,syne,echos,launcher,prism,installer}), filtre ADR, fichiersSUPPORT.md/AUTHORS/CITATION.cff.main(liens réécrits).🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com