feat(cockpit): integrate Mascarade v2 features + Langfuse health

mascarade_runtime_health.sh:
- Voice pipeline, eval harness, machine profile, Langfuse, KiCad Seeed MCP checks
- New capabilities object in cockpit-v1 artifact

mascarade_dispatch_mesh.sh:
- MACHINE_AWARE routing strategy
- github-copilot + litellm providers
- LiteLLM universal models (6 models)
- resolve_strategy() + apply_machine_aware_routing()

langfuse_health.sh (new):
- Standalone Langfuse health checker
- cockpit-v1 contract JSON output

runtime_ai_gateway.sh:
- Langfuse as source component
- mascarade_capabilities surface
- Updated summary with Langfuse status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
L'électron rare
2026-03-26 09:57:58 +01:00
parent a9487a84e9
commit 23459e9e37
4 changed files with 397 additions and 6 deletions
+173
View File
@@ -0,0 +1,173 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
LANGFUSE_URL="${LANGFUSE_URL:-https://langfuse.saillant.cc}"
ARTIFACT_DIR="${ROOT_DIR}/artifacts/ops/langfuse_health"
OUTPUT_MODE="text"
TIMEOUT_SEC=10
usage() {
cat <<'EOF'
Usage: langfuse_health.sh [options]
Options:
--url <langfuse-url> Langfuse instance URL (default: https://langfuse.saillant.cc)
--artifact-dir <path> Artifact directory (default: artifacts/ops/langfuse_health)
--json Emit cockpit-v1 JSON to stdout
--help Show this help
EOF
}
timestamp_utc() {
date -u +"%Y-%m-%dT%H:%M:%SZ"
}
timestamp_slug() {
date -u +"%Y%m%dT%H%M%SZ"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--url)
[[ $# -ge 2 ]] || { echo "Missing value for --url" >&2; exit 2; }
LANGFUSE_URL="$2"
shift 2
;;
--artifact-dir)
[[ $# -ge 2 ]] || { echo "Missing value for --artifact-dir" >&2; exit 2; }
ARTIFACT_DIR="$2"
shift 2
;;
--json)
OUTPUT_MODE="json"
shift
;;
--help|-h)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 2
;;
esac
done
mkdir -p "$ARTIFACT_DIR"
RUN_ID="$(timestamp_slug)"
RUN_JSON="$ARTIFACT_DIR/$RUN_ID.json"
RUN_AT="$(timestamp_utc)"
HEALTH_STATUS="unknown"
HEALTH_BODY=""
DEGRADED_REASONS=()
NEXT_STEPS=()
# Check Langfuse public health endpoint
HEALTH_BODY="$(curl -s --max-time "$TIMEOUT_SEC" "${LANGFUSE_URL}/api/public/health" 2>/dev/null || true)"
if printf "%s" "$HEALTH_BODY" | grep -qi '"status"\s*:\s*"OK"'; then
HEALTH_STATUS="ok"
elif [[ -n "$HEALTH_BODY" ]] && printf "%s" "$HEALTH_BODY" | grep -q '{'; then
HEALTH_STATUS="degraded"
DEGRADED_REASONS+=("Langfuse health endpoint responded but status is not OK")
NEXT_STEPS+=("Inspect Langfuse instance at ${LANGFUSE_URL} for service issues.")
else
HEALTH_STATUS="unreachable"
DEGRADED_REASONS+=("Langfuse instance at ${LANGFUSE_URL} is unreachable")
NEXT_STEPS+=("Verify Langfuse is running and accessible at ${LANGFUSE_URL}.")
fi
# Build the cockpit-v1 contract JSON
python3 - \
"$RUN_AT" \
"$LANGFUSE_URL" \
"$HEALTH_STATUS" \
"$HEALTH_BODY" \
"$RUN_JSON" \
--reasons \
"${DEGRADED_REASONS[@]}" \
--next-steps \
"${NEXT_STEPS[@]}" \
<<'PY' >"$RUN_JSON"
import json
import sys
run_at = sys.argv[1]
langfuse_url = sys.argv[2]
health_status = sys.argv[3]
health_body = sys.argv[4]
run_json = sys.argv[5]
tail = sys.argv[6:]
def split_sections(values):
reasons = []
next_steps = []
mode = None
for value in values:
if value == "--reasons":
mode = "reasons"
continue
if value == "--next-steps":
mode = "next_steps"
continue
if mode == "reasons":
reasons.append(value)
elif mode == "next_steps":
next_steps.append(value)
return reasons, next_steps
degraded_reasons, next_steps = split_sections(tail)
# Parse health body if valid JSON
health_data = {}
try:
health_data = json.loads(health_body) if health_body else {}
except Exception:
pass
contract_status = "ok" if health_status == "ok" else ("degraded" if health_status == "degraded" else "error")
payload = {
"contract_version": "cockpit-v1",
"component": "langfuse-health",
"action": "health-check",
"status": health_status,
"contract_status": contract_status,
"checked_at": run_at,
"langfuse_url": langfuse_url,
"owner": "Runtime-Companion",
"health_response": health_data,
"langfuse_status": health_data.get("status", "unknown"),
"langfuse_version": health_data.get("version", "unknown"),
"artifacts": [run_json],
"degraded_reasons": degraded_reasons,
"next_steps": next_steps,
"json_file": run_json,
}
print(json.dumps(payload, ensure_ascii=False, indent=2))
PY
# Copy to latest
cp "$RUN_JSON" "$ARTIFACT_DIR/latest.json"
if [[ "$OUTPUT_MODE" == "json" ]]; then
cat "$RUN_JSON"
else
cat <<EOF
Langfuse health
url: $LANGFUSE_URL
status: $HEALTH_STATUS
checked_at: $RUN_AT
artifacts:
- $RUN_JSON
EOF
if [[ ${#DEGRADED_REASONS[@]} -gt 0 ]]; then
printf 'degraded reasons:\n'
printf ' - %s\n' "${DEGRADED_REASONS[@]}"
fi
fi
+49
View File
@@ -104,6 +104,23 @@ profile_overrides = dispatch.get("profile_overrides", {})
family_defaults = dispatch.get("family_defaults", {})
keyword_families = dispatch.get("keyword_families", {})
ROUTING_STRATEGIES = [
"cheapest", "fastest", "best", "specific",
"round-robin", "machine-aware",
]
KNOWN_PROVIDERS = [
"openai", "anthropic", "mistral", "google", "ollama",
"groq", "deepseek", "openrouter", "together", "fireworks",
"github-copilot", "litellm",
]
LITELLM_UNIVERSAL_MODELS = [
"litellm/gpt-4o", "litellm/claude-sonnet-4-20250514",
"litellm/gemini-2.5-pro", "litellm/mistral-large-latest",
"litellm/deepseek-chat", "litellm/llama-3.3-70b",
]
def infer_family(profile_name):
profile_name = (profile_name or "").lower()
for family_name, keywords in keyword_families.items():
@@ -119,11 +136,36 @@ def resolve_family(profile_name, family_name):
return profile_overrides[profile_name]["family"]
return infer_family(profile_name)
def resolve_strategy(profile_name, family_name):
"""Resolve routing strategy: profile override > family default > cheapest."""
override = profile_overrides.get(profile_name, {})
strategy = override.get("strategy")
if not strategy:
strategy = family_defaults.get(family_name, {}).get("strategy")
if not strategy:
strategy = dispatch.get("default_strategy", "cheapest")
return strategy
def apply_machine_aware_routing(host_order, target_map):
"""MACHINE_AWARE strategy: prefer hosts with machine_profile available."""
scored = []
for host_id in host_order:
meta = target_map.get(host_id, {})
has_profile = bool(meta.get("machine_profile") or meta.get("gpu") or meta.get("accelerator"))
priority = meta.get("priority", 99)
scored.append((0 if has_profile else 1, priority, host_id))
scored.sort()
return [item[2] for item in scored]
family = resolve_family(profile, family_override)
strategy = resolve_strategy(profile, family)
override = profile_overrides.get(profile, {})
host_order = override.get("host_order") or family_defaults.get(family, {}).get("host_order") or default_order
host_order = [host for host in host_order if host in target_map] + [host for host in default_order if host not in host_order and host in target_map]
if strategy == "machine-aware":
host_order = apply_machine_aware_routing(host_order, target_map)
selected_target = host_order[0] if host_order else None
selected_meta = target_map.get(selected_target, {})
@@ -132,6 +174,7 @@ summary = {
"action": action,
"profile": profile or None,
"family": family,
"strategy": strategy,
"dispatch_file": sys.argv[1],
"registry_file": sys.argv[2],
"default_host_order": default_order,
@@ -141,6 +184,9 @@ summary = {
"selected_priority": selected_meta.get("priority"),
"selected_placement": selected_meta.get("placement"),
"notes": family_defaults.get(family, {}).get("notes"),
"known_providers": KNOWN_PROVIDERS,
"routing_strategies": ROUTING_STRATEGIES,
"litellm_universal_models": LITELLM_UNIVERSAL_MODELS,
}
if json_output:
@@ -149,8 +195,11 @@ else:
print("Mascarade dispatch mesh")
print(f"- action: {summary['action']}")
print(f"- family: {summary['family']}")
print(f"- strategy: {summary['strategy']}")
if summary["profile"]:
print(f"- profile: {summary['profile']}")
print(f"- route: {' -> '.join(summary['resolved_host_order'])}")
print(f"- selected: {summary['selected_target']} ({summary['selected_host']})")
print(f"- providers: {', '.join(summary['known_providers'])}")
print(f"- litellm models: {len(summary['litellm_universal_models'])}")
PY
+94 -1
View File
@@ -122,6 +122,11 @@ AGENT_SMOKE_MODEL=""
ROUTING_STATUS="unknown"
MEMORY_STATUS="unknown"
TRUST_LEVEL="inferred"
VOICE_PIPELINE_STATUS="unknown"
EVAL_HARNESS_STATUS="unknown"
MACHINE_PROFILE=""
LANGFUSE_STATUS="unknown"
KICAD_SEEED_TOOL_COUNT=0
RESUME_REF="kill-life:mascarade-runtime-health:${RUN_ID}:${HOST}:${AGENT}"
STATUS="ok"
CONTRACT_STATUS="ready"
@@ -172,6 +177,36 @@ if curl -fsS --max-time 5 http://127.0.0.1:11434/api/tags >/dev/null 2>&1; then
else
echo "ollama_tags=ko"
fi
voice_resp="$(curl -s --max-time 5 http://127.0.0.1:3100/voice/pipeline 2>/dev/null || true)"
if printf "%s" "$voice_resp" | grep -qi '"enabled"'; then
echo "voice_pipeline=ok"
voice_enabled="$(printf "%s" "$voice_resp" | python3 -c "import sys,json; print(json.load(sys.stdin).get(\"enabled\",False))" 2>/dev/null || echo "false")"
echo "voice_pipeline_enabled=$voice_enabled"
else
echo "voice_pipeline=ko"
fi
eval_resp="$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://127.0.0.1:3100/v1/eval/runs 2>/dev/null || true)"
if [[ "$eval_resp" == "200" || "$eval_resp" == "401" ]]; then
echo "eval_harness=ok"
else
echo "eval_harness=ko"
fi
machine_profile="$(curl -s --max-time 5 http://127.0.0.1:3100/api/machine-profile 2>/dev/null || true)"
if printf "%s" "$machine_profile" | grep -q '{'; then
echo "machine_profile=ok"
echo "machine_profile_data=$machine_profile"
else
echo "machine_profile=ko"
fi
langfuse_resp="$(curl -s --max-time 5 http://127.0.0.1:3100/api/langfuse/status 2>/dev/null || true)"
if printf "%s" "$langfuse_resp" | grep -qi '"active"\|"enabled"\|"ok"'; then
echo "langfuse=ok"
else
echo "langfuse=ko"
fi
kicad_tools="$(curl -s --max-time 5 http://127.0.0.1:3100/api/mcp/tools 2>/dev/null || true)"
kicad_count="$(printf "%s" "$kicad_tools" | python3 -c "import sys,json; tools=json.load(sys.stdin); print(len([t for t in tools if \"kicad\" in t.get(\"name\",\"\").lower() or \"seeed\" in t.get(\"name\",\"\").lower()]))" 2>/dev/null || echo "0")"
echo "kicad_seeed_tool_count=$kicad_count"
'
if ssh -o BatchMode=yes -o ConnectTimeout="$SSH_CONNECT_TIMEOUT" "$HOST" "bash -s" >"$REMOTE_CAPTURE" 2>>"$RUN_LOG" <<<"$REMOTE_SCRIPT"; then
@@ -212,6 +247,36 @@ if ssh -o BatchMode=yes -o ConnectTimeout="$SSH_CONNECT_TIMEOUT" "$HOST" "bash -
append_reason "le runtime Ollama ne répond pas sur $HOST"
append_next_step "Contrôler mascarade-ollama-runtime et l'endpoint 127.0.0.1:11434."
;;
voice_pipeline=ok)
VOICE_PIPELINE_STATUS="ok"
;;
voice_pipeline=ko)
VOICE_PIPELINE_STATUS="ko"
;;
eval_harness=ok)
EVAL_HARNESS_STATUS="ok"
;;
eval_harness=ko)
EVAL_HARNESS_STATUS="ko"
;;
machine_profile=ok)
MACHINE_PROFILE="available"
;;
machine_profile=ko)
MACHINE_PROFILE="unavailable"
;;
machine_profile_data=*)
MACHINE_PROFILE="${line#machine_profile_data=}"
;;
langfuse=ok)
LANGFUSE_STATUS="ok"
;;
langfuse=ko)
LANGFUSE_STATUS="ko"
;;
kicad_seeed_tool_count=*)
KICAD_SEEED_TOOL_COUNT="${line#kicad_seeed_tool_count=}"
;;
esac
done <"$REMOTE_CAPTURE"
else
@@ -422,6 +487,11 @@ json_from_py \
"$MEMORY_STATUS" \
"$TRUST_LEVEL" \
"$RESUME_REF" \
"$VOICE_PIPELINE_STATUS" \
"$EVAL_HARNESS_STATUS" \
"$MACHINE_PROFILE" \
"$LANGFUSE_STATUS" \
"$KICAD_SEEED_TOOL_COUNT" \
"${ARTIFACTS[@]}" \
--reasons \
"${DEGRADED_REASONS[@]}" \
@@ -432,7 +502,7 @@ import json
import sys
from pathlib import Path
run_at, host, agent, status, contract_status, ssh_ok, docker_status, api_agents_status, ollama_tags_status, agent_smoke_status, agent_smoke_provider, agent_smoke_model, run_log, run_json, api_container, core_container, ollama_container, routing_capture, routing_status, memory_capture, memory_status, trust_level, resume_ref, *tail = sys.argv[1:]
run_at, host, agent, status, contract_status, ssh_ok, docker_status, api_agents_status, ollama_tags_status, agent_smoke_status, agent_smoke_provider, agent_smoke_model, run_log, run_json, api_container, core_container, ollama_container, routing_capture, routing_status, memory_capture, memory_status, trust_level, resume_ref, voice_pipeline_status, eval_harness_status, machine_profile, langfuse_status, kicad_seeed_tool_count, *tail = sys.argv[1:]
def split_sections(values):
artifacts = []
@@ -509,6 +579,25 @@ payload = {
"mascarade-core": core_container,
"mascarade-ollama-runtime": ollama_container,
},
"voice_pipeline": {
"status": voice_pipeline_status,
},
"eval_harness": {
"status": eval_harness_status,
},
"langfuse": {
"status": langfuse_status,
},
"kicad_seeed_mcp": {
"tool_count": int(kicad_seeed_tool_count) if kicad_seeed_tool_count.isdigit() else 0,
},
},
"machine_profile": json.loads(machine_profile) if machine_profile.startswith("{") else {"status": machine_profile or "unknown"},
"capabilities": {
"voice_pipeline": voice_pipeline_status == "ok",
"eval_harness": eval_harness_status == "ok",
"langfuse_tracing": langfuse_status == "ok",
"kicad_seeed_mcp": int(kicad_seeed_tool_count) > 0 if kicad_seeed_tool_count.isdigit() else False,
},
"artifacts": artifacts,
"degraded_reasons": degraded_reasons,
@@ -531,6 +620,10 @@ host: $HOST
status: $STATUS
agent smoke: $AGENT_SMOKE_STATUS (${AGENT_SMOKE_PROVIDER:-unknown}/${AGENT_SMOKE_MODEL:-unknown})
containers: api=${CONTAINERS[mascarade-api]} core=${CONTAINERS[mascarade-core]} ollama=${CONTAINERS[mascarade-ollama-runtime]}
voice_pipeline: $VOICE_PIPELINE_STATUS
eval_harness: $EVAL_HARNESS_STATUS
langfuse: $LANGFUSE_STATUS
kicad_seeed_tools: $KICAD_SEEED_TOOL_COUNT
artifacts:
- $RUN_LOG
- $RUN_JSON
+81 -5
View File
@@ -21,9 +21,12 @@ MESH_REPORT=""
INTELLIGENCE_SCRIPT="${RUNTIME_GATEWAY_INTELLIGENCE_SCRIPT:-${ROOT_DIR}/tools/cockpit/intelligence_tui.sh}"
MESH_SCRIPT="${RUNTIME_GATEWAY_MESH_SCRIPT:-${ROOT_DIR}/tools/cockpit/mesh_health_check.sh}"
MASCARADE_SCRIPT="${RUNTIME_GATEWAY_MASCARADE_SCRIPT:-${ROOT_DIR}/tools/cockpit/mascarade_runtime_health.sh}"
LANGFUSE_SCRIPT="${RUNTIME_GATEWAY_LANGFUSE_SCRIPT:-${ROOT_DIR}/tools/cockpit/langfuse_health.sh}"
LANGFUSE_REPORT="${ROOT_DIR}/artifacts/ops/langfuse_health/latest.json"
INTELLIGENCE_TIMEOUT_SEC="${RUNTIME_GATEWAY_INTELLIGENCE_TIMEOUT_SEC:-15}"
MESH_TIMEOUT_SEC="${RUNTIME_GATEWAY_MESH_TIMEOUT_SEC:-15}"
MASCARADE_TIMEOUT_SEC="${RUNTIME_GATEWAY_MASCARADE_TIMEOUT_SEC:-15}"
LANGFUSE_TIMEOUT_SEC="${RUNTIME_GATEWAY_LANGFUSE_TIMEOUT_SEC:-10}"
usage() {
cat <<'EOF'
@@ -118,6 +121,14 @@ def fallback(reason: str, detail: str) -> dict[str, object]:
"host": "unknown",
}
)
elif label == "langfuse":
payload.update(
{
"langfuse_status": "unknown",
"langfuse_version": "unknown",
"langfuse_url": "unknown",
}
)
return payload
@@ -183,10 +194,16 @@ refresh_sources() {
run_refresh_probe mascarade "${MASCARADE_TIMEOUT_SEC}" "${mascarade_out}" "${LOAD_PROFILE}" \
bash "${MASCARADE_SCRIPT}" --json
MASCARADE_REPORT="${mascarade_out}"
local langfuse_out="${ARTIFACT_DIR}/langfuse-${STAMP}.json"
log_line "INFO" "refreshing Langfuse health"
run_refresh_probe langfuse "${LANGFUSE_TIMEOUT_SEC}" "${langfuse_out}" "${LOAD_PROFILE}" \
bash "${LANGFUSE_SCRIPT}" --json
LANGFUSE_REPORT="${langfuse_out}"
}
emit_status_json() {
python3 - "${ROOT_DIR}" "${INTELLIGENCE_REPORT}" "${MESH_REPORT}" "${MASCARADE_REPORT}" "${RUN_LOG}" <<'PY'
python3 - "${ROOT_DIR}" "${INTELLIGENCE_REPORT}" "${MESH_REPORT}" "${MASCARADE_REPORT}" "${LANGFUSE_REPORT}" "${RUN_LOG}" <<'PY'
from __future__ import annotations
import json
@@ -198,7 +215,8 @@ root = Path(sys.argv[1])
intelligence_path = Path(sys.argv[2]) if sys.argv[2] else None
mesh_path = Path(sys.argv[3]) if sys.argv[3] else None
mascarade_path = Path(sys.argv[4]) if sys.argv[4] else None
run_log = Path(sys.argv[5])
langfuse_path = Path(sys.argv[5]) if sys.argv[5] else None
run_log = Path(sys.argv[6])
def read_json(path: Path | None) -> dict[str, object] | None:
@@ -416,6 +434,45 @@ def build_web_platform_surface(ia_payload: dict[str, object] | None) -> tuple[di
return surface, next_steps
def build_langfuse_surface(payload: dict[str, object] | None, path: Path | None) -> tuple[dict[str, object], list[str]]:
status = normalize((payload or {}).get("status"))
langfuse_status = (payload or {}).get("langfuse_status", "unknown")
langfuse_version = (payload or {}).get("langfuse_version", "unknown")
langfuse_url = (payload or {}).get("langfuse_url", "unknown")
degraded = listify((payload or {}).get("degraded_reasons"))
if status != "ready" and not degraded:
degraded = [f"langfuse-{status}"]
next_steps = collect_next_steps(payload)
if status != "ready" and not next_steps:
next_steps = ["Check Langfuse instance health and verify tracing connectivity."]
surface = {
"status": status,
"summary_short": compact(
f"Langfuse {status}; version={langfuse_version}; url={langfuse_url}.",
220,
),
"evidence": path_evidence("langfuse", path),
"degraded_reasons": degraded,
"upstreams": ["tools/cockpit/langfuse_health.sh"],
"langfuse_status": langfuse_status,
"langfuse_version": langfuse_version,
"langfuse_url": langfuse_url,
"path": relative_path(path),
}
return surface, next_steps
def build_mascarade_capabilities(mascarade_payload: dict[str, object] | None) -> dict[str, object]:
"""Extract Mascarade capabilities from the runtime health payload."""
caps = (mascarade_payload or {}).get("capabilities", {})
return {
"voice_pipeline": bool(caps.get("voice_pipeline")),
"eval_harness": bool(caps.get("eval_harness")),
"langfuse_tracing": bool(caps.get("langfuse_tracing")),
"kicad_seeed_mcp": bool(caps.get("kicad_seeed_mcp")),
}
def build_firmware_cad_surface(root: Path) -> tuple[dict[str, object], dict[str, object], list[str]]:
firmware_main = root / "firmware" / "src" / "main.cpp"
firmware_platformio = root / "firmware" / "platformio.ini"
@@ -569,12 +626,15 @@ def build_firmware_cad_surface(root: Path) -> tuple[dict[str, object], dict[str,
intelligence = read_json(intelligence_path)
mesh = read_json(mesh_path)
mascarade = read_json(mascarade_path)
langfuse = read_json(langfuse_path)
runtime_surface, runtime_next = build_runtime_surface(mascarade, mascarade_path)
mcp_surface, mcp_next = build_mcp_surface(mesh, mesh_path)
ia_surface, ia_next = build_ia_surface(intelligence, intelligence_path)
firmware_cad_surface, firmware_cad_summary, firmware_cad_next = build_firmware_cad_surface(root)
web_platform_surface, web_platform_next = build_web_platform_surface(intelligence)
langfuse_surface, langfuse_next = build_langfuse_surface(langfuse, langfuse_path)
mascarade_capabilities = build_mascarade_capabilities(mascarade)
source_states = [runtime_surface["status"], mcp_surface["status"], ia_surface["status"], web_platform_surface["status"]]
if any(state == "blocked" for state in source_states):
@@ -592,6 +652,7 @@ for label, path, surface, extra_next in (
("runtime", mascarade_path, runtime_surface, runtime_next),
("mcp", mesh_path, mcp_surface, mcp_next),
("ia", intelligence_path, ia_surface, ia_next),
("langfuse", langfuse_path, langfuse_surface, langfuse_next),
):
if path and path.exists():
rel = relative_path(path)
@@ -629,8 +690,9 @@ summary_short = compact(
f"mcp={mcp_surface['status']} ({mcp_surface['summary_short']}) | "
f"ia={ia_surface['status']} ({ia_surface['summary_short']}) | "
f"firmware_cad={firmware_cad_surface['status']} ({firmware_cad_surface['summary_short']}) | "
f"web_platform={web_platform_surface['status']} ({web_platform_surface['summary_short']})",
420,
f"web_platform={web_platform_surface['status']} ({web_platform_surface['summary_short']}) | "
f"langfuse={langfuse_surface['status']} ({langfuse_surface['summary_short']})",
500,
)
payload = {
@@ -647,6 +709,7 @@ payload = {
"tools/cockpit/intelligence_tui.sh",
"tools/cockpit/mesh_health_check.sh",
"tools/cockpit/mascarade_runtime_health.sh",
"tools/cockpit/langfuse_health.sh",
"docs/AI_WORKFLOWS.md",
],
"summary_short": summary_short,
@@ -654,7 +717,7 @@ payload = {
"degraded_reasons": degraded_reasons,
"next_steps": next_steps[:5],
"goal": "Publier une sante canonique runtime/MCP/IA exploitable par cockpit, docs et extensions.",
"state": f"runtime={runtime_surface['status']} mcp={mcp_surface['status']} ia={ia_surface['status']} web_platform={web_platform_surface['status']}",
"state": f"runtime={runtime_surface['status']} mcp={mcp_surface['status']} ia={ia_surface['status']} web_platform={web_platform_surface['status']} langfuse={langfuse_surface['status']}",
"blockers": degraded_reasons,
"next": next_steps[:3],
"owner": "Runtime-Companion/MCP-Health",
@@ -667,7 +730,9 @@ payload = {
"ia": ia_surface,
"firmware_cad": firmware_cad_surface,
"web_platform": web_platform_surface,
"langfuse": langfuse_surface,
},
"mascarade_capabilities": mascarade_capabilities,
"sources": {
"intelligence": {
"path": relative_path(intelligence_path),
@@ -702,6 +767,13 @@ payload = {
"queue_depth": web_platform_surface.get("queue_depth"),
"probes": web_platform_surface.get("probes", {}),
},
"langfuse": {
"path": relative_path(langfuse_path),
"status": langfuse_surface["status"],
"langfuse_status": langfuse_surface.get("langfuse_status", "unknown"),
"langfuse_version": langfuse_surface.get("langfuse_version", "unknown"),
"langfuse_url": langfuse_surface.get("langfuse_url", "unknown"),
},
},
"summary_short_artifacts": {
"firmware_cad": {
@@ -839,6 +911,10 @@ while [ "$#" -gt 0 ]; do
MASCARADE_REPORT="${2:-}"
shift 2
;;
--langfuse-report)
LANGFUSE_REPORT="${2:-}"
shift 2
;;
-h|--help)
usage
exit 0