diff --git a/ai-agentic-embedded-base/specs/03_plan.md b/ai-agentic-embedded-base/specs/03_plan.md index 8f4215f..fe4fb96 100644 --- a/ai-agentic-embedded-base/specs/03_plan.md +++ b/ai-agentic-embedded-base/specs/03_plan.md @@ -14,9 +14,13 @@ Faire tourner une boucle locale simple: ## Scope - `tools/cockpit/lot_chain.sh` +- `tools/autonomous_next_lots.py` +- `tools/run_autonomous_next_lots.sh` - `tools/specs/sync_spec_mirror.sh` - `tools/doc/readme_repo_coherence.sh` - `tools/test_python.sh` +- `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` +- `docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md` - `specs/03_plan.md` - `specs/04_tasks.md` - `specs/constraints.yaml` @@ -33,6 +37,8 @@ Faire tourner une boucle locale simple: - `bash tools/cockpit/lot_chain.sh status` - `bash tools/cockpit/lot_chain.sh all --yes` +- `bash tools/run_autonomous_next_lots.sh status` +- `bash tools/run_autonomous_next_lots.sh run` - `bash tools/specs/sync_spec_mirror.sh all --yes` - `bash tools/doc/readme_repo_coherence.sh all --yes` - `python3 tools/validate_specs.py --strict --require-mirror-sync` @@ -42,6 +48,7 @@ Faire tourner une boucle locale simple: - `specs/` reste la source de verite. - `ai-agentic-embedded-base/specs/` reste un miroir exporte. +- `docs/plans/18_*` capture la lane runtime/MCP/CAD synchronisee par la boucle locale. - Les choix manuels restants doivent etre surfaces via `artifacts/cockpit/next_question.md`. ## Statut auto @@ -50,6 +57,7 @@ Faire tourner une boucle locale simple: - Auto-fix lots pending: `0` - README/repo coherence: `done` - Spec mirror sync: `done` +- MCP/CAD runtime lane sync: `synced` - Strict spec contract: `passed` - Stable Python suite: `passed` - Next real need: ask the operator to choose the next manual lot from `artifacts/cockpit/next_question.md`. diff --git a/ai-agentic-embedded-base/specs/04_tasks.md b/ai-agentic-embedded-base/specs/04_tasks.md index 94a37e6..0c58ab5 100644 --- a/ai-agentic-embedded-base/specs/04_tasks.md +++ b/ai-agentic-embedded-base/specs/04_tasks.md @@ -6,6 +6,7 @@ Last updated: 2026-03-09 - Plan actif: `specs/03_plan.md` - Statut detaille: `artifacts/cockpit/useful_lots_status.md` +- Lane runtime/MCP/CAD: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` - Question operateur si besoin reel: `artifacts/cockpit/next_question.md` ## Execution @@ -15,10 +16,12 @@ Last updated: 2026-03-09 - Evidence: `artifacts/doc/readme_repo_audit.md` - [x] T-LC-002 - Keep the exported spec mirror synchronized with the canonical `specs/` tree. - Evidence: `artifacts/specs/mirror_sync_report.md` -- [x] T-LC-003 - Revalidate the strict spec contract after each auto-fix run. +- [x] T-LC-003 - Keep the upstream MCP/CAD runtime lane docs synchronized with the current local state. + - Evidence: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` +- [x] T-LC-004 - Revalidate the strict spec contract after each auto-fix run. - Evidence: `python3 tools/validate_specs.py --strict --require-mirror-sync` -- [x] T-LC-004 - Re-run the stable Python suite after the chained lots. +- [x] T-LC-005 - Re-run the stable Python suite after the chained lots. - Evidence: `bash tools/test_python.sh --suite stable` -- [ ] T-LC-005 - Choose the next manual lot once automation reaches a real fork. +- [ ] T-LC-006 - Choose the next manual lot once automation reaches a real fork. - Evidence: `artifacts/cockpit/next_question.md` diff --git a/ai-agentic-embedded-base/specs/README.md b/ai-agentic-embedded-base/specs/README.md index ac6fede..0058b0a 100644 --- a/ai-agentic-embedded-base/specs/README.md +++ b/ai-agentic-embedded-base/specs/README.md @@ -31,3 +31,6 @@ Synchronisation `spec_kit`: - `bash tools/specs/sync_spec_mirror.sh check` - Pour enchaîner automatiquement les lots locaux utiles: - `bash tools/cockpit/lot_chain.sh all --yes` +- Pour resynchroniser la lane runtime/MCP/CAD versionnée dans `docs/plans/18_*`: + - `bash tools/run_autonomous_next_lots.sh status` + - `bash tools/run_autonomous_next_lots.sh run` diff --git a/ai-agentic-embedded-base/specs/mcp_tasks.md b/ai-agentic-embedded-base/specs/mcp_tasks.md index 9284c5c..e92ebcb 100644 --- a/ai-agentic-embedded-base/specs/mcp_tasks.md +++ b/ai-agentic-embedded-base/specs/mcp_tasks.md @@ -64,9 +64,10 @@ Format: - AC: le smoke passe aussi sur le chemin hote, pas seulement via le fallback conteneur. - Statut: optionnel tant que le runtime canonique reste `container` et valide en production locale. - Helper pret: `python3 tools/hw/kicad_host_mcp_smoke.py --json --quick` degrade proprement si `pcbnew` est absent. - - Derniere verification: `2026-03-08` sur cette machine -> `blocked by host environment` + - Derniere verification: `2026-03-09` sur cette machine -> `blocked by host environment` - Evidence: `python3 tools/hw/kicad_host_mcp_smoke.py --json --quick` - - Resultat: `{"status":"degraded","host_pcbnew_import":"missing","error":"pcbnew not importable on host runtime"}` + - Resultat: `{"status":"degraded","requested_runtime":"host","runtime_mode":"host","quick":true,"host_pcbnew_import":"missing","error":"pcbnew not importable on host runtime"}` + - Note: `command -v pcbnew` retourne vide sur cette machine; aucun lot automatique supplementaire n'est pertinent tant que le runtime host KiCad n'est pas installe. - [x] K-013 — Décider du statut final des micro-serveurs `kicad_kic_ai` - AC: `component_database`, `kicad_tools` et `nexar_api` sont explicitement promus en surfaces auxiliaires supportées. diff --git a/ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md b/ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md index f228e17..f7d962c 100644 --- a/ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md +++ b/ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md @@ -63,8 +63,11 @@ Last updated: 2026-02-21 - [x] I-202 - Add n8n PR autotriage workflow (webhook + cron fallback). - [x] I-203 - Add local docker compose stack for n8n (`5678`). - [x] I-204 - Add runtime scripts (`integrations_up/down/status`, `import_n8n`). -- [ ] I-205 - Validate end-to-end import + activation on local Docker runtime. - - status: Deferred (post-stabilization) - - command: `tools/ai/zeroclaw_integrations_up.sh` - - command: `tools/ai/zeroclaw_integrations_status.sh` - - command: `tools/ai/zeroclaw_integrations_import_n8n.sh` +- [x] I-205 - Validate end-to-end import + activation on local Docker runtime. + - status: `2026-03-09` done (`mascarade-n8n` healthy, `kill-life-n8n-smoke` active via local CLI import/publish path). + - command: `bash tools/ai/zeroclaw_integrations_up.sh --json` + - command: `bash tools/ai/zeroclaw_integrations_status.sh --json` + - command: `bash tools/ai/zeroclaw_integrations_import_n8n.sh --json` + - evidence: + - `{"container":"mascarade-n8n","container_running":true,"internal_http_ok":true,"host_http_ok":true}` + - `{"workflow_id":"kill-life-n8n-smoke","import_action":"skipped","publish_action":"published","active":true}` diff --git a/docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md b/docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md index 9a15fed..80724be 100644 --- a/docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md +++ b/docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md @@ -1,6 +1,6 @@ # 18) Plan d'enchainement autonome des lots utiles -Last updated: 2026-03-09 06:06:59 +Last updated: 2026-03-09 06:24:48 Ce plan est regenere localement par `tools/autonomous_next_lots.py`. @@ -18,52 +18,43 @@ mettre a jour un plan/todo operateur, puis relancer les validations associees. ## Etat Git courant -- branche: `## feat/mac-mcp-cad-host-bootstrap` -- dirty paths: `16` +- branche: `## main...origin/main` +- dirty paths: `21` - ahead: `0` - behind: `0` ### Fichiers dirty detectes -- `docs/MCP_SETUP.md` -- `docs/plans/README.md` -- `mcp.json` -- `tools/bootstrap_mac_mcp.sh` -- `tools/hw/cad_stack.sh` -- `tools/hw/run_kicad_mcp.sh` -- `tools/lib/runtime_home.sh` -- `tools/mcp_smoke_common.py` -- `tools/run_github_dispatch_mcp.sh` -- `tools/run_knowledge_base_mcp.sh` -- `tools/validate_specs_mcp_smoke.py` +- `ai-agentic-embedded-base/specs/03_plan.md` +- `ai-agentic-embedded-base/specs/04_tasks.md` +- `ai-agentic-embedded-base/specs/README.md` +- `ai-agentic-embedded-base/specs/mcp_tasks.md` +- `ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md` - `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` - `docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md` +- `specs/03_plan.md` +- `specs/04_tasks.md` +- `specs/README.md` +- `specs/mcp_tasks.md` +- `specs/zeroclaw_dual_hw_todo.md` +- `tools/ai/integrations/n8n/README.md` - `tools/autonomous_next_lots.py` -- `tools/run_autonomous_next_lots.sh` -- `tools/run_validate_specs_mcp.sh` +- `tools/cockpit/README.md` +- `tools/cockpit/lot_chain.sh` +- `tools/ai/integrations/n8n/kill_life_smoke_workflow.json` +- `tools/ai/zeroclaw_integrations_down.sh` +- `tools/ai/zeroclaw_integrations_import_n8n.sh` +- `tools/ai/zeroclaw_integrations_status.sh` +- `tools/ai/zeroclaw_integrations_up.sh` ## Lots detectes -### 1. `mcp-runtime` — Alignement MCP runtime local +### 1. `zeroclaw-integrations` — Runtime local ZeroClaw / n8n -Stabiliser les launchers MCP, le bootstrap Mac, la resolution du repo compagnon et la doc operateur associee. +Fermer la lane d'integrations locales ZeroClaw/n8n, les evidences I-205 associees et la documentation/spec sync qui l'accompagne. -- references: `docs/plans/15_plan_mcp_runtime_alignment.md`, `docs/plans/17_plan_target_architecture_mcp_agentics_2028.md` -- validations: `3` done, `2` advisory, `0` blocked - -### 2. `cad-mcp-host` — Runtime CAD host-first - -Qualifier KiCad, FreeCAD et OpenSCAD en host-first sur macOS tout en gardant le fallback conteneur operable. - -- references: `docs/plans/16_plan_cad_modeling_stack.md`, `docs/plans/17_plan_target_architecture_mcp_agentics_2028.md` -- validations: `4` done, `0` advisory, `0` blocked - -### 3. `python-local` — Execution Python repo-locale - -Garder les scripts et smokes sur l'interpreteur repo-local plutot que sur le Python systeme. - -- references: `docs/plans/15_plan_mcp_runtime_alignment.md` -- validations: `1` done, `0` advisory, `0` blocked +- references: `specs/zeroclaw_dual_hw_todo.md`, `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` +- validations: `5` done, `0` advisory, `0` blocked ## Questions a poser seulement si besoin reel diff --git a/docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md b/docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md index 1a5bf54..1fe5819 100644 --- a/docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md +++ b/docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md @@ -1,38 +1,20 @@ # 18) TODO enchainement autonome des lots utiles -Last updated: 2026-03-09 06:06:59 +Last updated: 2026-03-09 06:24:48 Ce fichier est regenere localement par `tools/autonomous_next_lots.py`. -## `mcp-runtime` — Alignement MCP runtime local +## `zeroclaw-integrations` — Runtime local ZeroClaw / n8n -- done: lot detecte (Stabiliser les launchers MCP, le bootstrap Mac, la resolution du repo compagnon et la doc operateur associee.) -- done: `bash tools/bootstrap_mac_mcp.sh codex` - resume: codex mcp add openscad --env MASCARADE_DIR=/Users/electron/mascarade-main -- bash /Users/electron/Kill_LIFE/tools/run_openscad_mcp.sh | codex mcp add huggingface --url https://huggingface.co/mcp --bearer-token-env-var HUGGINGFACE_API_KEY | codex mcp add playwright -- npx -y @playwright/mcp@latest -- done: `bash tools/bootstrap_mac_mcp.sh json` - resume: } | } | } -- done: `.venv/bin/python tools/validate_specs_mcp_smoke.py --json --quick` - resume: {"status": "ready", "protocol_version": "2025-03-26", "server_name": "validate-specs", "tool_count": 2, "checks": ["initialize", "tools/list"], "error": null} -- advisory: `.venv/bin/python tools/knowledge_base_mcp_smoke.py --json --quick` - resume: {"status": "degraded", "protocol_version": "2025-03-26", "server_name": "knowledge-base", "provider": "memos", "tool_count": 4, "checks": ["initialize", "tools/list"], "secret_configured": false, "live_validation": "missing_secret", "error": "memos auth missing"} -- advisory: `.venv/bin/python tools/github_dispatch_mcp_smoke.py --json --quick` - resume: {"status": "degraded", "protocol_version": "2025-03-26", "server_name": "github-dispatch", "tool_count": 3, "checks": ["initialize", "tools/list"], "token_configured": false, "live_requested": false, "live_validation": "missing_secret", "error": "GitHub dispatch auth missing"} - -## `cad-mcp-host` — Runtime CAD host-first - -- done: lot detecte (Qualifier KiCad, FreeCAD et OpenSCAD en host-first sur macOS tout en gardant le fallback conteneur operable.) -- done: `bash tools/hw/run_kicad_mcp.sh --doctor` - resume: KICAD_PYTHON_STDERR_LOG_LEVEL=WARNING | REQUESTED_RUNTIME=auto | SELECTED_RUNTIME=host -- done: `bash tools/hw/cad_stack.sh doctor` - resume: 1.0.2 | PlatformIO Core, version 6.1.19 | OpenSCAD version 2021.01 -- done: `.venv/bin/python tools/freecad_mcp_smoke.py --quick --json` - resume: {"status": "ready", "protocol_version": "2025-03-26", "server_name": "freecad", "tool_count": 4, "checks": ["initialize", "tools/list", "get_runtime_info"], "error": null} -- done: `.venv/bin/python tools/openscad_mcp_smoke.py --quick --json` - resume: {"status": "ready", "protocol_version": "2025-03-26", "server_name": "openscad", "tool_count": 4, "checks": ["initialize", "tools/list", "get_runtime_info"], "error": null} - -## `python-local` — Execution Python repo-locale - -- done: lot detecte (Garder les scripts et smokes sur l'interpreteur repo-local plutot que sur le Python systeme.) -- done: `bash tools/test_python.sh --venv-dir .venv --suite stable` - resume: ---------------------------------------------------------------------- | Ran 3 tests in 0.014s | OK +- done: lot detecte (Fermer la lane d'integrations locales ZeroClaw/n8n, les evidences I-205 associees et la documentation/spec sync qui l'accompagne.) +- done: `bash tools/ai/zeroclaw_integrations_up.sh --json` + resume: {"container": "mascarade-n8n", "container_exists": true, "container_running": true, "container_status": "Up 16 hours (healthy)", "internal_http_ok": true, "host_http_ok": true, "n8n_url": "http://127.0.0.1:5678/", "workflow_ids": ["kill-life-n8n-smoke"], "active_workflow_ids": ["kill-life-n8n-smoke"]} +- done: `bash tools/ai/zeroclaw_integrations_status.sh --json` + resume: {"container": "mascarade-n8n", "container_exists": true, "container_running": true, "container_status": "Up 16 hours (healthy)", "internal_http_ok": true, "host_http_ok": true, "n8n_url": "http://127.0.0.1:5678/", "workflow_ids": ["kill-life-n8n-smoke"], "active_workflow_ids": ["kill-life-n8n-smoke"]} +- done: `bash tools/ai/zeroclaw_integrations_import_n8n.sh --json` + resume: {"workflow_id": "kill-life-n8n-smoke", "input_file": "/home/clems/Kill_LIFE/tools/ai/integrations/n8n/kill_life_smoke_workflow.json", "container": "mascarade-n8n", "import_action": "skipped", "publish_action": "published", "active": true} +- done: `python3 tools/validate_specs.py --strict --require-mirror-sync` + resume: - compliance stdout: OK: compliance profile 'prototype' validated. | required standards: 5 | evidence items: 4 +- done: `bash tools/test_python.sh --suite stable` + resume: ---------------------------------------------------------------------- | Ran 3 tests in 0.020s | OK diff --git a/specs/03_plan.md b/specs/03_plan.md index 8f4215f..fe4fb96 100644 --- a/specs/03_plan.md +++ b/specs/03_plan.md @@ -14,9 +14,13 @@ Faire tourner une boucle locale simple: ## Scope - `tools/cockpit/lot_chain.sh` +- `tools/autonomous_next_lots.py` +- `tools/run_autonomous_next_lots.sh` - `tools/specs/sync_spec_mirror.sh` - `tools/doc/readme_repo_coherence.sh` - `tools/test_python.sh` +- `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` +- `docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md` - `specs/03_plan.md` - `specs/04_tasks.md` - `specs/constraints.yaml` @@ -33,6 +37,8 @@ Faire tourner une boucle locale simple: - `bash tools/cockpit/lot_chain.sh status` - `bash tools/cockpit/lot_chain.sh all --yes` +- `bash tools/run_autonomous_next_lots.sh status` +- `bash tools/run_autonomous_next_lots.sh run` - `bash tools/specs/sync_spec_mirror.sh all --yes` - `bash tools/doc/readme_repo_coherence.sh all --yes` - `python3 tools/validate_specs.py --strict --require-mirror-sync` @@ -42,6 +48,7 @@ Faire tourner une boucle locale simple: - `specs/` reste la source de verite. - `ai-agentic-embedded-base/specs/` reste un miroir exporte. +- `docs/plans/18_*` capture la lane runtime/MCP/CAD synchronisee par la boucle locale. - Les choix manuels restants doivent etre surfaces via `artifacts/cockpit/next_question.md`. ## Statut auto @@ -50,6 +57,7 @@ Faire tourner une boucle locale simple: - Auto-fix lots pending: `0` - README/repo coherence: `done` - Spec mirror sync: `done` +- MCP/CAD runtime lane sync: `synced` - Strict spec contract: `passed` - Stable Python suite: `passed` - Next real need: ask the operator to choose the next manual lot from `artifacts/cockpit/next_question.md`. diff --git a/specs/04_tasks.md b/specs/04_tasks.md index 94a37e6..0c58ab5 100644 --- a/specs/04_tasks.md +++ b/specs/04_tasks.md @@ -6,6 +6,7 @@ Last updated: 2026-03-09 - Plan actif: `specs/03_plan.md` - Statut detaille: `artifacts/cockpit/useful_lots_status.md` +- Lane runtime/MCP/CAD: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` - Question operateur si besoin reel: `artifacts/cockpit/next_question.md` ## Execution @@ -15,10 +16,12 @@ Last updated: 2026-03-09 - Evidence: `artifacts/doc/readme_repo_audit.md` - [x] T-LC-002 - Keep the exported spec mirror synchronized with the canonical `specs/` tree. - Evidence: `artifacts/specs/mirror_sync_report.md` -- [x] T-LC-003 - Revalidate the strict spec contract after each auto-fix run. +- [x] T-LC-003 - Keep the upstream MCP/CAD runtime lane docs synchronized with the current local state. + - Evidence: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md` +- [x] T-LC-004 - Revalidate the strict spec contract after each auto-fix run. - Evidence: `python3 tools/validate_specs.py --strict --require-mirror-sync` -- [x] T-LC-004 - Re-run the stable Python suite after the chained lots. +- [x] T-LC-005 - Re-run the stable Python suite after the chained lots. - Evidence: `bash tools/test_python.sh --suite stable` -- [ ] T-LC-005 - Choose the next manual lot once automation reaches a real fork. +- [ ] T-LC-006 - Choose the next manual lot once automation reaches a real fork. - Evidence: `artifacts/cockpit/next_question.md` diff --git a/specs/README.md b/specs/README.md index ac6fede..0058b0a 100644 --- a/specs/README.md +++ b/specs/README.md @@ -31,3 +31,6 @@ Synchronisation `spec_kit`: - `bash tools/specs/sync_spec_mirror.sh check` - Pour enchaîner automatiquement les lots locaux utiles: - `bash tools/cockpit/lot_chain.sh all --yes` +- Pour resynchroniser la lane runtime/MCP/CAD versionnée dans `docs/plans/18_*`: + - `bash tools/run_autonomous_next_lots.sh status` + - `bash tools/run_autonomous_next_lots.sh run` diff --git a/specs/mcp_tasks.md b/specs/mcp_tasks.md index 9284c5c..e92ebcb 100644 --- a/specs/mcp_tasks.md +++ b/specs/mcp_tasks.md @@ -64,9 +64,10 @@ Format: - AC: le smoke passe aussi sur le chemin hote, pas seulement via le fallback conteneur. - Statut: optionnel tant que le runtime canonique reste `container` et valide en production locale. - Helper pret: `python3 tools/hw/kicad_host_mcp_smoke.py --json --quick` degrade proprement si `pcbnew` est absent. - - Derniere verification: `2026-03-08` sur cette machine -> `blocked by host environment` + - Derniere verification: `2026-03-09` sur cette machine -> `blocked by host environment` - Evidence: `python3 tools/hw/kicad_host_mcp_smoke.py --json --quick` - - Resultat: `{"status":"degraded","host_pcbnew_import":"missing","error":"pcbnew not importable on host runtime"}` + - Resultat: `{"status":"degraded","requested_runtime":"host","runtime_mode":"host","quick":true,"host_pcbnew_import":"missing","error":"pcbnew not importable on host runtime"}` + - Note: `command -v pcbnew` retourne vide sur cette machine; aucun lot automatique supplementaire n'est pertinent tant que le runtime host KiCad n'est pas installe. - [x] K-013 — Décider du statut final des micro-serveurs `kicad_kic_ai` - AC: `component_database`, `kicad_tools` et `nexar_api` sont explicitement promus en surfaces auxiliaires supportées. diff --git a/specs/zeroclaw_dual_hw_todo.md b/specs/zeroclaw_dual_hw_todo.md index f228e17..f7d962c 100644 --- a/specs/zeroclaw_dual_hw_todo.md +++ b/specs/zeroclaw_dual_hw_todo.md @@ -63,8 +63,11 @@ Last updated: 2026-02-21 - [x] I-202 - Add n8n PR autotriage workflow (webhook + cron fallback). - [x] I-203 - Add local docker compose stack for n8n (`5678`). - [x] I-204 - Add runtime scripts (`integrations_up/down/status`, `import_n8n`). -- [ ] I-205 - Validate end-to-end import + activation on local Docker runtime. - - status: Deferred (post-stabilization) - - command: `tools/ai/zeroclaw_integrations_up.sh` - - command: `tools/ai/zeroclaw_integrations_status.sh` - - command: `tools/ai/zeroclaw_integrations_import_n8n.sh` +- [x] I-205 - Validate end-to-end import + activation on local Docker runtime. + - status: `2026-03-09` done (`mascarade-n8n` healthy, `kill-life-n8n-smoke` active via local CLI import/publish path). + - command: `bash tools/ai/zeroclaw_integrations_up.sh --json` + - command: `bash tools/ai/zeroclaw_integrations_status.sh --json` + - command: `bash tools/ai/zeroclaw_integrations_import_n8n.sh --json` + - evidence: + - `{"container":"mascarade-n8n","container_running":true,"internal_http_ok":true,"host_http_ok":true}` + - `{"workflow_id":"kill-life-n8n-smoke","import_action":"skipped","publish_action":"published","active":true}` diff --git a/tools/ai/integrations/n8n/README.md b/tools/ai/integrations/n8n/README.md index 8e99bba..94f0df7 100644 --- a/tools/ai/integrations/n8n/README.md +++ b/tools/ai/integrations/n8n/README.md @@ -17,6 +17,18 @@ Current posture: - If you need concrete n8n workflow files again, regenerate them as explicit tracked artifacts instead of relying on dead links. +Current local validation commands: + +```bash +bash tools/ai/zeroclaw_integrations_up.sh +bash tools/ai/zeroclaw_integrations_status.sh --json +bash tools/ai/zeroclaw_integrations_import_n8n.sh --json +``` + +Tracked smoke artifact: + +- `tools/ai/integrations/n8n/kill_life_smoke_workflow.json` + Historical workflow names: - `zeroclaw_orchestrator_workflow` diff --git a/tools/ai/integrations/n8n/kill_life_smoke_workflow.json b/tools/ai/integrations/n8n/kill_life_smoke_workflow.json new file mode 100644 index 0000000..c5a0dbf --- /dev/null +++ b/tools/ai/integrations/n8n/kill_life_smoke_workflow.json @@ -0,0 +1,47 @@ +{ + "id": "kill-life-n8n-smoke", + "name": "Kill LIFE n8n smoke", + "active": false, + "nodes": [ + { + "parameters": {}, + "id": "manual-trigger", + "name": "Manual Trigger", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [ + 260, + 300 + ] + }, + { + "parameters": {}, + "id": "no-op", + "name": "No Op", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 520, + 300 + ] + } + ], + "connections": { + "Manual Trigger": { + "main": [ + [ + { + "node": "No Op", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "settings": {}, + "pinData": {}, + "meta": null, + "versionId": "11111111-1111-1111-1111-111111111111", + "tags": [] +} diff --git a/tools/ai/zeroclaw_integrations_down.sh b/tools/ai/zeroclaw_integrations_down.sh new file mode 100755 index 0000000..fe24aa8 --- /dev/null +++ b/tools/ai/zeroclaw_integrations_down.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +set -euo pipefail + +N8N_CONTAINER="${ZEROCLAW_N8N_CONTAINER:-mascarade-n8n}" +YES=0 + +usage() { + cat <<'EOF' +Usage: bash tools/ai/zeroclaw_integrations_down.sh [options] + +Stop the local n8n integration container. + +Options: + --yes Confirm the stop action + -h, --help Show this help + +Env overrides: + ZEROCLAW_N8N_CONTAINER +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --yes) + YES=1 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +[[ "${YES}" == "1" ]] || { + echo "Refusing to stop ${N8N_CONTAINER} without --yes." >&2 + exit 1 +} + +if docker ps --filter "name=^/${N8N_CONTAINER}$" --format '{{.Names}}' | grep -qx "${N8N_CONTAINER}"; then + docker stop "${N8N_CONTAINER}" >/dev/null + echo "stopped=${N8N_CONTAINER}" + exit 0 +fi + +echo "already_stopped=${N8N_CONTAINER}" diff --git a/tools/ai/zeroclaw_integrations_import_n8n.sh b/tools/ai/zeroclaw_integrations_import_n8n.sh new file mode 100755 index 0000000..69de128 --- /dev/null +++ b/tools/ai/zeroclaw_integrations_import_n8n.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd -- "${SCRIPT_DIR}/../.." && pwd)" + +N8N_CONTAINER="${ZEROCLAW_N8N_CONTAINER:-mascarade-n8n}" +INPUT_FILE="${ZEROCLAW_N8N_WORKFLOW_FILE:-${ROOT_DIR}/tools/ai/integrations/n8n/kill_life_smoke_workflow.json}" +CONTAINER_INPUT_PATH="${ZEROCLAW_N8N_CONTAINER_INPUT:-/home/node/kill-life-import.json}" +PUBLISH=1 +OUTPUT_JSON=0 + +usage() { + cat <<'EOF' +Usage: bash tools/ai/zeroclaw_integrations_import_n8n.sh [options] + +Import the tracked smoke workflow into the local n8n runtime and publish it. + +Options: + --input PATH Workflow JSON to import + --no-publish Import only + --json Emit JSON summary + -h, --help Show this help + +Env overrides: + ZEROCLAW_N8N_CONTAINER + ZEROCLAW_N8N_WORKFLOW_FILE + ZEROCLAW_N8N_CONTAINER_INPUT +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --input) + shift + [[ $# -gt 0 ]] || { echo "Missing value for --input" >&2; usage >&2; exit 2; } + INPUT_FILE="$1" + ;; + --no-publish) + PUBLISH=0 + ;; + --json) + OUTPUT_JSON=1 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +[[ -f "${INPUT_FILE}" ]] || { + echo "Missing workflow file: ${INPUT_FILE}" >&2 + exit 1 +} + +workflow_id="$( + python3 - "${INPUT_FILE}" <<'PY' +import json +import sys +from pathlib import Path + +data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8")) +workflow_id = str(data.get("id", "")).strip() +if not workflow_id: + raise SystemExit("workflow JSON must contain a non-empty id") +print(workflow_id) +PY +)" + +bash "${ROOT_DIR}/tools/ai/zeroclaw_integrations_up.sh" >/dev/null + +existing_ids="$(docker exec "${N8N_CONTAINER}" n8n list:workflow --onlyId 2>/dev/null || true)" +import_action="skipped" + +if ! printf '%s\n' "${existing_ids}" | grep -Fxq "${workflow_id}"; then + docker exec -i "${N8N_CONTAINER}" sh -lc "cat > '${CONTAINER_INPUT_PATH}'" < "${INPUT_FILE}" + docker exec "${N8N_CONTAINER}" n8n import:workflow --input="${CONTAINER_INPUT_PATH}" >/dev/null + import_action="imported" +fi + +publish_action="skipped" +if [[ "${PUBLISH}" == "1" ]]; then + docker exec "${N8N_CONTAINER}" n8n publish:workflow --id="${workflow_id}" >/dev/null + publish_action="published" +fi + +active_ids="$(docker exec "${N8N_CONTAINER}" n8n list:workflow --active=true --onlyId 2>/dev/null || true)" +is_active=false +if printf '%s\n' "${active_ids}" | grep -Fxq "${workflow_id}"; then + is_active=true +fi + +if [[ "${OUTPUT_JSON}" == "1" ]]; then + ACTIVE="${is_active}" python3 - <&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +container_line="$(docker ps -a --filter "name=^/${N8N_CONTAINER}$" --format '{{.Names}}|{{.Status}}' | head -n 1)" +running_line="$(docker ps --filter "name=^/${N8N_CONTAINER}$" --format '{{.Names}}|{{.Status}}' | head -n 1)" +container_exists=false +container_running=false +container_status="missing" +internal_http_ok=false +host_http_ok=false +workflow_ids="" +active_ids="" + +if [[ -n "${container_line}" ]]; then + container_exists=true + container_status="${container_line#*|}" +fi + +if [[ -n "${running_line}" ]]; then + container_running=true +fi + +if [[ "${container_running}" == true ]]; then + if docker exec "${N8N_CONTAINER}" sh -lc 'which wget >/dev/null 2>&1 && wget -q -O /dev/null http://127.0.0.1:5678/'; then + internal_http_ok=true + fi + + if curl -fsSI "${N8N_URL}" >/dev/null 2>&1; then + host_http_ok=true + fi + + workflow_ids="$(docker exec "${N8N_CONTAINER}" n8n list:workflow --onlyId 2>/dev/null | sed '/^$/d' | paste -sd, - || true)" + active_ids="$(docker exec "${N8N_CONTAINER}" n8n list:workflow --active=true --onlyId 2>/dev/null | sed '/^$/d' | paste -sd, - || true)" +fi + +if [[ "${OUTPUT_JSON}" == "1" ]]; then + CONTAINER_EXISTS="${container_exists}" \ + CONTAINER_RUNNING="${container_running}" \ + INTERNAL_HTTP_OK="${internal_http_ok}" \ + HOST_HTTP_OK="${host_http_ok}" \ + python3 - <&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +running_line="$(docker ps --filter "name=^/${N8N_CONTAINER}$" --format '{{.Names}}' | head -n 1)" +existing_line="$(docker ps -a --filter "name=^/${N8N_CONTAINER}$" --format '{{.Names}}' | head -n 1)" + +if [[ -n "${running_line}" ]]; then + : +elif [[ -n "${existing_line}" ]]; then + docker start "${N8N_CONTAINER}" >/dev/null +else + echo "n8n container not found: ${N8N_CONTAINER}" >&2 + echo "Expected an already-provisioned companion runtime (for example mascarade-n8n)." >&2 + exit 1 +fi + +deadline=$((SECONDS + WAIT_SECS)) +while (( SECONDS < deadline )); do + if docker exec "${N8N_CONTAINER}" sh -lc 'which wget >/dev/null 2>&1 && wget -q -O /dev/null http://127.0.0.1:5678/'; then + if [[ "${OUTPUT_JSON}" == "1" ]]; then + bash "${ROOT_DIR}/tools/ai/zeroclaw_integrations_status.sh" --json + else + bash "${ROOT_DIR}/tools/ai/zeroclaw_integrations_status.sh" + fi + exit 0 + fi + sleep 1 +done + +echo "n8n container did not become ready within ${WAIT_SECS}s: ${N8N_CONTAINER}" >&2 +exit 1 diff --git a/tools/autonomous_next_lots.py b/tools/autonomous_next_lots.py index 698085e..f33c34b 100755 --- a/tools/autonomous_next_lots.py +++ b/tools/autonomous_next_lots.py @@ -35,6 +35,63 @@ class Lot: LOTS: tuple[Lot, ...] = ( + Lot( + key="zeroclaw-integrations", + title="Runtime local ZeroClaw / n8n", + description=( + "Fermer la lane d'integrations locales ZeroClaw/n8n, les evidences " + "I-205 associees et la documentation/spec sync qui l'accompagne." + ), + priority=5, + paths=( + "specs/03_plan.md", + "specs/04_tasks.md", + "specs/README.md", + "specs/mcp_tasks.md", + "specs/zeroclaw_dual_hw_todo.md", + "ai-agentic-embedded-base/specs/03_plan.md", + "ai-agentic-embedded-base/specs/04_tasks.md", + "ai-agentic-embedded-base/specs/README.md", + "ai-agentic-embedded-base/specs/mcp_tasks.md", + "ai-agentic-embedded-base/specs/zeroclaw_dual_hw_todo.md", + "docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md", + "docs/plans/18_todo_enchainement_autonome_des_lots_utiles.md", + "tools/cockpit/README.md", + "tools/cockpit/lot_chain.sh", + "tools/ai/integrations/n8n/README.md", + "tools/ai/integrations/n8n/kill_life_smoke_workflow.json", + "tools/ai/zeroclaw_integrations_up.sh", + "tools/ai/zeroclaw_integrations_status.sh", + "tools/ai/zeroclaw_integrations_import_n8n.sh", + "tools/ai/zeroclaw_integrations_down.sh", + ), + plan_refs=( + "specs/zeroclaw_dual_hw_todo.md", + "docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md", + ), + validations=( + Validation( + name="zeroclaw_integrations_up", + cmd=("bash", "tools/ai/zeroclaw_integrations_up.sh", "--json"), + ), + Validation( + name="zeroclaw_integrations_status", + cmd=("bash", "tools/ai/zeroclaw_integrations_status.sh", "--json"), + ), + Validation( + name="zeroclaw_integrations_import_n8n", + cmd=("bash", "tools/ai/zeroclaw_integrations_import_n8n.sh", "--json"), + ), + Validation( + name="strict_spec_contract", + cmd=("python3", "tools/validate_specs.py", "--strict", "--require-mirror-sync"), + ), + Validation( + name="python_stable_suite", + cmd=("bash", "tools/test_python.sh", "--suite", "stable"), + ), + ), + ), Lot( key="mcp-runtime", title="Alignement MCP runtime local", diff --git a/tools/cockpit/README.md b/tools/cockpit/README.md index 869e3bb..5641d5d 100644 --- a/tools/cockpit/README.md +++ b/tools/cockpit/README.md @@ -5,8 +5,8 @@ Entrée unique pour piloter le repo en local. - `gate_s0` : check “spec ready” - `fw` : build/test firmware - `hw` : gates hardware (ERC/netlist/BOM) -- `lots-status` : état des lots locaux utiles + prochaine vraie question -- `lots-run` : enchaîne les lots auto-fix, validations, puis met à jour le suivi +- `lots-status` : état des lots locaux utiles + prochaine vraie question + resynchronisation de `docs/plans/18_*` +- `lots-run` : enchaîne les lots auto-fix, la lane `autonomous_next_lots`, les validations, puis met à jour le suivi Note: - `lots-run` peut sortir avec le code `3` quand la chaîne est saine mais qu'un vrai choix opérateur reste nécessaire. diff --git a/tools/cockpit/lot_chain.sh b/tools/cockpit/lot_chain.sh index ccf0513..bec0369 100755 --- a/tools/cockpit/lot_chain.sh +++ b/tools/cockpit/lot_chain.sh @@ -18,6 +18,7 @@ README_STATUS="unknown" MIRROR_STATUS="unknown" STRICT_STATUS="not_run" PYTHON_STATUS="not_run" +UPSTREAM_STATUS="unknown" NEXT_LOT="pending" QUESTION_COUNT=0 @@ -142,6 +143,14 @@ refresh_auto_lot_status() { fi } +refresh_upstream_autonomous_lane() { + if bash "${ROOT_DIR}/tools/run_autonomous_next_lots.sh" status >/dev/null 2>&1; then + UPSTREAM_STATUS="synced" + else + UPSTREAM_STATUS="failed" + fi +} + collect_manual_questions() { local file match line_no line_text clean_text item_id recommended recommended_text @@ -219,6 +228,9 @@ write_status_report() { printf -- '- Spec mirror sync: `%s`\n' "${MIRROR_STATUS}" printf -- ' - Command: `bash tools/specs/sync_spec_mirror.sh all --yes`\n' printf -- ' - Evidence: `artifacts/specs/mirror_sync_report.md`\n\n' + printf -- '- MCP/CAD runtime lane sync: `%s`\n' "${UPSTREAM_STATUS}" + printf -- ' - Command: `bash tools/run_autonomous_next_lots.sh status`\n' + printf -- ' - Evidence: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md`\n\n' printf '## Validations\n\n' printf -- '- Strict spec contract: `%s`' "${STRICT_STATUS}" @@ -262,6 +274,7 @@ update_plan_files() { fi printf -- '- README/repo coherence: `%s`\n' "${README_STATUS}" printf -- '- Spec mirror sync: `%s`\n' "${MIRROR_STATUS}" + printf -- '- MCP/CAD runtime lane sync: `%s`\n' "${UPSTREAM_STATUS}" printf -- '- Strict spec contract: `%s`\n' "${STRICT_STATUS}" printf -- '- Stable Python suite: `%s`\n' "${PYTHON_STATUS}" if [[ "${NEXT_LOT}" == "question" ]]; then @@ -282,31 +295,38 @@ update_plan_files() { printf -- ' - Evidence: `artifacts/doc/readme_repo_audit.md`\n' if [[ "${MIRROR_STATUS}" == "done" ]]; then - printf -- '- [x] T-LC-002 - Keep the exported spec mirror synchronized with the canonical `specs/` tree.\n' + printf -- '- [x] T-LC-002 - Keep the exported spec mirror synchronized with the canonical `specs/` tree.\n' else printf -- '- [ ] T-LC-002 - Keep the exported spec mirror synchronized with the canonical `specs/` tree.\n' fi printf -- ' - Evidence: `artifacts/specs/mirror_sync_report.md`\n' - if [[ "${STRICT_STATUS}" == "passed" ]]; then - printf -- '- [x] T-LC-003 - Revalidate the strict spec contract after each auto-fix run.\n' + if [[ "${UPSTREAM_STATUS}" == "synced" ]]; then + printf -- '- [x] T-LC-003 - Keep the upstream MCP/CAD runtime lane docs synchronized with the current local state.\n' else - printf -- '- [ ] T-LC-003 - Revalidate the strict spec contract after each auto-fix run.\n' + printf -- '- [ ] T-LC-003 - Keep the upstream MCP/CAD runtime lane docs synchronized with the current local state.\n' + fi + printf -- ' - Evidence: `docs/plans/18_plan_enchainement_autonome_des_lots_utiles.md`\n' + + if [[ "${STRICT_STATUS}" == "passed" ]]; then + printf -- '- [x] T-LC-004 - Revalidate the strict spec contract after each auto-fix run.\n' + else + printf -- '- [ ] T-LC-004 - Revalidate the strict spec contract after each auto-fix run.\n' fi printf -- ' - Evidence: `python3 tools/validate_specs.py --strict --require-mirror-sync`\n' if [[ "${PYTHON_STATUS}" == "passed" ]]; then - printf -- '- [x] T-LC-004 - Re-run the stable Python suite after the chained lots.\n' + printf -- '- [x] T-LC-005 - Re-run the stable Python suite after the chained lots.\n' else - printf -- '- [ ] T-LC-004 - Re-run the stable Python suite after the chained lots.\n' + printf -- '- [ ] T-LC-005 - Re-run the stable Python suite after the chained lots.\n' fi printf -- ' - Evidence: `bash tools/test_python.sh --suite stable`\n' if [[ "${NEXT_LOT}" == "question" ]]; then - printf -- '- [ ] T-LC-005 - Choose the next manual lot once automation reaches a real fork.\n' + printf -- '- [ ] T-LC-006 - Choose the next manual lot once automation reaches a real fork.\n' printf -- ' - Evidence: `%s`\n' "${QUESTION_FILE#${ROOT_DIR}/}" else - printf -- '- [x] T-LC-005 - Choose the next manual lot once automation reaches a real fork.\n' + printf -- '- [x] T-LC-006 - Choose the next manual lot once automation reaches a real fork.\n' printf -- ' - Evidence: `%s`\n' "${QUESTION_FILE#${ROOT_DIR}/}" fi } > "${tasks_tmp}" @@ -325,6 +345,10 @@ run_auto_lots() { log "Running spec mirror sync loop" bash "${ROOT_DIR}/tools/specs/sync_spec_mirror.sh" all --yes MIRROR_STATUS="done" + + log "Refreshing upstream autonomous next-lots lane" + bash "${ROOT_DIR}/tools/run_autonomous_next_lots.sh" run >/dev/null + UPSTREAM_STATUS="synced" } run_validations() { @@ -375,6 +399,7 @@ finalize_tracked_updates() { refresh_state() { load_validation_state refresh_auto_lot_status + refresh_upstream_autonomous_lane collect_manual_questions write_status_report }