diff --git a/.github/workflows/mesh_contracts.yml b/.github/workflows/mesh_contracts.yml index 717e684..512a885 100644 --- a/.github/workflows/mesh_contracts.yml +++ b/.github/workflows/mesh_contracts.yml @@ -58,6 +58,10 @@ jobs: - name: Validate mesh contract examples run: | mkdir -p artifacts/ci + python3 tools/specs/mesh_contract_check.py \ + --schema specs/contracts/machine_registry.schema.json \ + --instance specs/contracts/machine_registry.mesh.json \ + | tee artifacts/ci/machine_registry_contract.json python3 tools/specs/mesh_contract_check.py \ --schema specs/contracts/agent_handoff.schema.json \ --instance specs/contracts/examples/agent_handoff.mesh.json \ diff --git a/docs/AGENT_HANDOFF_DISCIPLINE.md b/docs/AGENT_HANDOFF_DISCIPLINE.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MACHINE_REGISTRY_2026-03-20.md b/docs/MACHINE_REGISTRY_2026-03-20.md index d679772..df03b0b 100644 --- a/docs/MACHINE_REGISTRY_2026-03-20.md +++ b/docs/MACHINE_REGISTRY_2026-03-20.md @@ -1,6 +1,6 @@ # Registre machine/capacite — Kill_LIFE -Date: `2026-03-20` +Date: `2026-03-29` Source de verite machine-readable: - `specs/contracts/machine_registry.mesh.json` @@ -25,27 +25,29 @@ Objectif: publier un registre unique pour les roles, ports, priorites et restric ## Ordre canonique actuel 1. `tower` -> `clems@192.168.0.120` -2. `kxkm` -> `kxkm@kxkm-ai` -3. `cils` -> `cils@100.126.225.111` -4. `local` -5. `root-reserve` -> `root@192.168.0.119` +2. `photon` -> `root@192.168.0.119` +3. `kxkm-ai` -> `kxkm@100.87.54.119` +4. `grosmac` -> `electron@100.80.178.42` +5. `cils` -> `cisl@100.126.225.111` ## Regles operatoires encodees -- `cils` reste en quota et ne porte que `Kill_LIFE` en critique. -- `photon-safe` garde `cils` atteignable, mais sans charge applicative non essentielle. -- `root-reserve` reste une reserve stricte et ne remonte pas devant `local` en fonctionnement nominal. +- `tower` reste le noeud principal de collaboration, data plane et observabilite. +- `photon` doit rester edge minimal et ne pas devenir un fourre-tout applicatif. +- `kxkm-ai` porte l'inference GPU, le CAD headless et les traitements IA lourds. +- `grosmac` est un poste operateur local et un point de validation de proximite, pas un coeur de production. +- `cils` reste une reserve legacy et ne doit pas remonter en hebergement nominal. ## CLI cockpit associee - `bash tools/cockpit/machine_registry.sh --action summary --json` - `bash tools/cockpit/machine_registry.sh --action list` -- `bash tools/cockpit/machine_registry.sh --action show --machine cils --json` +- `bash tools/cockpit/machine_registry.sh --action show --machine photon --json` - `bash tools/cockpit/machine_registry.sh --action clean-logs --days 14` ## Suite prevue -- `mesh_sync_preflight.sh` consomme maintenant ce registre pour les roles, ports, priorites, placement et la reserve runtime -- `ssh_healthcheck.sh` charge maintenant ses cibles SSH directement depuis le registre et ignore automatiquement l'entree `local` (port `0`) -- `run_alignment_daily.sh` capture maintenant un resume JSON du registre et l'embarque dans ses artefacts/JSON de synthese -- externaliser ensuite les derniers candidats de chemins repo pour eliminer le drift restant cote preflight +- `mesh_sync_preflight.sh` doit consommer ce registre pour les roles, ports, priorites, placement et la reserve runtime +- `ssh_healthcheck.sh` doit charger ses cibles SSH directement depuis le registre et ignorer automatiquement les entrees non applicables +- le workflow `.github/workflows/mesh_contracts.yml` doit valider ce registre pour bloquer toute derive +- le runbook multi-machine reference ce registre comme source de verite operatoire \ No newline at end of file diff --git a/docs/MULTI_MACHINE_RUNBOOK.md b/docs/MULTI_MACHINE_RUNBOOK.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/RUNBOOK.md b/docs/RUNBOOK.md index fa910fe..15c2e9f 100644 --- a/docs/RUNBOOK.md +++ b/docs/RUNBOOK.md @@ -6,12 +6,14 @@ - Séquence locale : `docs/KILL_LIFE_WORKFLOW_LOCAL_SEQUENCE_2026-03-11.md` - Séquence GitHub : `docs/KILL_LIFE_WORKFLOW_GITHUB_SEQUENCE_2026-03-11.md` - Monitoring VPS : `docs/INFRA_VPS_RUNBOOK_2026.md` +- Runbook multi-machine : `docs/MULTI_MACHINE_RUNBOOK.md` - Audit UI/UX YiACAD : `docs/YIACAD_APPLE_UI_UX_AUDIT_2026-03-20.md` - Points d’insertion natifs YiACAD : `docs/YIACAD_NATIVE_UI_INSERTION_POINTS_2026-03-20.md` Choix opératoire rapide : - validation et exécution locale avant CI distante : séquence `workflow local` - dispatch allowlisté, checks GitHub et evidence pack CI : séquence `workflow github` +- dépendances cross-host, ordre de reprise Photon/Tower et registre machine : `runbook multi-machine` ## 1) Règles d’or - Le texte d’issue est **non fiable** → il est sanitisé avant prompt. @@ -47,7 +49,7 @@ Ajoute un label `ai:*` : ## 3) CI/CD multi-cible hardware-in-the-loop Le workflow CI/CD compile, teste et valide le firmware sur ESP et Linux. -Les scripts d’automatisation sont dans `tools/` : +Les scripts d’automatisation sont dans `tools/` : - `build_firmware.py` : build par cible - `test_firmware.py` : tests par cible - `collect_evidence.py` : génération evidence pack diff --git a/specs/contracts/api_bridge_governance_execution.schema.json b/specs/contracts/api_bridge_governance_execution.schema.json new file mode 100644 index 0000000..9a64c6d --- /dev/null +++ b/specs/contracts/api_bridge_governance_execution.schema.json @@ -0,0 +1,180 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "API Bridge: Governance and Execution Payload Separation", + "description": "Contract defining which fields may traverse the gateway between Kill_LIFE governance agents and Mascarade execution agents.", + "type": "object", + "properties": { + "metadata": { + "type": "object", + "description": "Contract metadata.", + "properties": { + "version": { + "type": "string", + "const": "1.0.0" + }, + "date": { + "type": "string", + "format": "date-time" + }, + "owner_repo": { + "type": "string", + "enum": [ + "kill_life", + "mascarade", + "crazy_life" + ] + }, + "status": { + "type": "string", + "enum": [ + "draft", + "active", + "deprecated" + ] + } + }, + "required": [ + "version", + "date", + "owner_repo", + "status" + ] + }, + "governance_payload_fields": { + "type": "array", + "description": "Fields that belong only to the governance layer.", + "items": { + "type": "string" + }, + "default": [ + "write_set", + "write_set_roots", + "owner_repo", + "owner_agent", + "evidence_paths", + "evidence_artifact_rules", + "status", + "contacts", + "handoff_contracts", + "governance_metadata" + ] + }, + "execution_payload_fields": { + "type": "array", + "description": "Fields that may traverse to the execution layer.", + "items": { + "type": "string" + }, + "default": [ + "name", + "description", + "type", + "model", + "system_prompt", + "skills", + "tools", + "max_retries", + "timeout_ms" + ] + }, + "bridge_rules": { + "type": "array", + "description": "Enforcement rules at gateway boundaries.", + "items": { + "type": "object", + "properties": { + "rule_id": { + "type": "string" + }, + "from": { + "type": "string", + "enum": [ + "kill_life", + "mascarade", + "crazy_life" + ] + }, + "to": { + "type": "string", + "enum": [ + "kill_life", + "mascarade", + "crazy_life" + ] + }, + "action": { + "type": "string", + "enum": [ + "strip", + "allow", + "block", + "reject" + ] + }, + "target_fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + } + }, + "required": [ + "rule_id", + "from", + "to", + "action", + "target_fields" + ] + }, + "default": [ + { + "rule_id": "R-BRIDGE-01", + "from": "kill_life", + "to": "crazy_life", + "action": "strip", + "target_fields": [ + "write_set", + "owner_repo", + "evidence_paths", + "status" + ], + "description": "Remove governance metadata when payloads cross to the UI." + }, + { + "rule_id": "R-BRIDGE-02", + "from": "mascarade", + "to": "crazy_life", + "action": "allow", + "target_fields": [ + "name", + "description", + "model", + "skills", + "tools" + ], + "description": "Allow execution properties to reach the UI." + }, + { + "rule_id": "R-BRIDGE-03", + "from": "crazy_life", + "to": "mascarade", + "action": "block", + "target_fields": [ + "write_set", + "owner_repo" + ], + "description": "Never allow the UI to write governance metadata." + } + ] + } + }, + "required": [ + "metadata", + "governance_payload_fields", + "execution_payload_fields", + "bridge_rules" + ] +} \ No newline at end of file diff --git a/specs/contracts/machine_registry.mesh.json b/specs/contracts/machine_registry.mesh.json index f361789..e5f0168 100644 --- a/specs/contracts/machine_registry.mesh.json +++ b/specs/contracts/machine_registry.mesh.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-20 15:45:37 CET", + "generated_at": "2026-03-29 23:59:00 CET", "default_profile": "tower-first", "profiles": [ "tower-first", @@ -11,75 +11,108 @@ "target": "clems@192.168.0.120", "host": "192.168.0.120", "port": 22, - "role": "Machine de pilotage / orchestration locale", + "role": "Serveur collaboration et data plane principal", "priority": 1, "placement": "primary", - "enabled_profiles": ["tower-first", "photon-safe"], - "critical_repos": ["Kill_LIFE", "mascarade", "crazy_life"], - "non_essential_policy": "allowed", + "enabled_profiles": [ + "tower-first", + "photon-safe" + ], + "critical_repos": [ + "Kill_LIFE", + "mascarade", + "crazy_life" + ], + "non_essential_policy": "degrade-nonessential-first", "reserve_only": false, "load_order_bias": 1000, - "notes": "Cible prioritaire de calcul et de pilotage." + "notes": "Noeud principal pour la collaboration, la Suite Numerique, l'observabilite et une partie importante du runtime Mascarade." }, { - "id": "kxkm", - "target": "kxkm@kxkm-ai", - "host": "kxkm-ai", - "port": 22, - "role": "Mac opérateur", - "priority": 2, - "placement": "secondary", - "enabled_profiles": ["tower-first", "photon-safe"], - "critical_repos": ["Kill_LIFE", "mascarade", "crazy_life"], - "non_essential_policy": "allowed", - "reserve_only": false, - "load_order_bias": 2000, - "notes": "Relais principal derrière Tower." - }, - { - "id": "cils", - "target": "cils@100.126.225.111", - "host": "100.126.225.111", - "port": 22, - "role": "Mac opérateur secondaire (photon)", - "priority": 3, - "placement": "quota", - "enabled_profiles": ["tower-first", "photon-safe"], - "critical_repos": ["Kill_LIFE"], - "non_essential_policy": "locked", - "reserve_only": false, - "load_order_bias": 3000, - "notes": "Pas de service essentiel durable; `photon-safe` force la charge applicative a zero." - }, - { - "id": "local", - "target": "local", - "host": "local", - "port": 0, - "role": "Workspace local", - "priority": 4, - "placement": "local", - "enabled_profiles": ["tower-first", "photon-safe"], - "critical_repos": ["Kill_LIFE", "mascarade", "crazy_life"], - "non_essential_policy": "allowed", - "reserve_only": false, - "load_order_bias": 4000, - "notes": "Utilisation en quatrieme position pour eviter la surcharge locale." - }, - { - "id": "root-reserve", + "id": "photon", "target": "root@192.168.0.119", "host": "192.168.0.119", "port": 22, - "role": "Serveur système / exécution matérielle", + "role": "Edge proxy, reverse proxy et services partages critiques", + "priority": 2, + "placement": "secondary", + "enabled_profiles": [ + "tower-first", + "photon-safe" + ], + "critical_repos": [ + "Kill_LIFE", + "mascarade", + "crazy_life" + ], + "non_essential_policy": "edge-minimal-only", + "reserve_only": false, + "load_order_bias": 1500, + "notes": "Point d'entree reseau de la flotte; doit rester minimal et privilegier Traefik, connectivite et services pivots." + }, + { + "id": "kxkm-ai", + "target": "kxkm@100.87.54.119", + "host": "100.87.54.119", + "port": 22, + "role": "Station IA GPU, inference lourde, CAD headless et audio", + "priority": 3, + "placement": "secondary", + "enabled_profiles": [ + "tower-first", + "photon-safe" + ], + "critical_repos": [ + "Kill_LIFE", + "mascarade" + ], + "non_essential_policy": "gpu-jobs-priority", + "reserve_only": false, + "load_order_bias": 2000, + "notes": "Noeud RTX 4090 dedie a l'inference GPU, WhisperX, CAD headless, PlatformIO et generation audio." + }, + { + "id": "grosmac", + "target": "electron@100.80.178.42", + "host": "100.80.178.42", + "port": 22, + "role": "Poste operateur local, developpement et inference de proximite", + "priority": 4, + "placement": "local", + "enabled_profiles": [ + "tower-first", + "photon-safe" + ], + "critical_repos": [ + "Kill_LIFE", + "mascarade", + "crazy_life" + ], + "non_essential_policy": "operator-workstation", + "reserve_only": false, + "load_order_bias": 4000, + "notes": "Machine de developpement et de pilotage local avec Ollama et montages SMB vers Photon." + }, + { + "id": "cils", + "target": "cisl@100.126.225.111", + "host": "100.126.225.111", + "port": 22, + "role": "Noeud legacy de secours et petits modeles", "priority": 5, "placement": "reserve", - "enabled_profiles": ["tower-first", "photon-safe"], - "critical_repos": ["Kill_LIFE", "mascarade", "crazy_life"], + "enabled_profiles": [ + "tower-first", + "photon-safe" + ], + "critical_repos": [ + "Kill_LIFE", + "mascarade" + ], "non_essential_policy": "reserve-only", "reserve_only": true, "load_order_bias": 9000, - "notes": "Réserve stricte: ne doit pas remonter devant `local` en fonctionnement nominal." + "notes": "Machine legacy stable mais non prioritaire, utilisee comme secours operateur et inference legere." } ] }