diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 67005af..a1ab3f9 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -117,6 +117,11 @@ services: PORT: "8000" INTELLIOPS_STORE_BACKEND: postgres INTELLIOPS_DATABASE_URL: postgresql+psycopg://intelliops:intelliops@postgres:5432/intelliops + # --- Semantic runbook selection. "embedding" activates cosine-similarity + # matching of incident symptoms against playbook descriptions (all-MiniLM-L6-v2). + # "off" (old default) falls back to keyword-only matching — embedding selector + # was never wired in compose, so it silently never ran. Now on by default. + INTELLIOPS_RUNBOOK_SELECTOR_MODE: "${INTELLIOPS_RUNBOOK_SELECTOR_MODE:-embedding}" # --- LLM explanation provider. Empty endpoint = the offline template, no network. # Values come from deploy/.env (gitignored); see deploy/.env.example. Any # OpenAI-compatible endpoint works (OpenAI, Groq, vLLM, Ollama). diff --git a/frontend/src/data/api.ts b/frontend/src/data/api.ts index ceb5389..4832e8a 100644 --- a/frontend/src/data/api.ts +++ b/frontend/src/data/api.ts @@ -20,6 +20,8 @@ const RCA = import.meta.env.VITE_RCA_URL ?? "http://localhost:8003"; const AUTH_TOKEN = import.meta.env.VITE_AUTH_TOKEN ?? ""; +export const OPERATOR_NAME = import.meta.env.VITE_OPERATOR_NAME || "demo-operator"; + function authHeaders(base: Record = {}): Record { return AUTH_TOKEN ? { ...base, Authorization: `Bearer ${AUTH_TOKEN}` } : base; } @@ -57,7 +59,7 @@ export const testLlmConfig = (cfg: { endpoint: string; api_key: string; model: s export async function decideApproval( approvalId: string, decision: "approved" | "rejected", - decidedBy = "oncall-alice", + decidedBy = OPERATOR_NAME, ): Promise { const r = await fetch(`${GOV}/approvals/${approvalId}/decide`, { method: "POST", diff --git a/frontend/src/views/Governance.tsx b/frontend/src/views/Governance.tsx index b36da3f..907826d 100644 --- a/frontend/src/views/Governance.tsx +++ b/frontend/src/views/Governance.tsx @@ -2,6 +2,7 @@ import { useMemo, useState } from "react"; import { Check, LockKey, Scroll, ShieldCheck, Sparkle, UserCheck, X } from "@phosphor-icons/react"; import { Bezel, PageHead, timeAgo } from "../components/primitives"; import { approveProposal, loadAudit, loadOutcomes, loadPlaybooks, loadProposals, rejectProposal } from "../data/source"; +import { OPERATOR_NAME } from "../data/api"; import { useLiveData } from "../hooks/useLiveData"; import { pushToast } from "../hooks/useToast"; import { Reveal as Section } from "../hooks/useReveal"; @@ -61,7 +62,7 @@ export function Governance() { async function decide(proposal: ProposedPlaybook, decision: "approved" | "rejected") { if (decidingId) return; setDecidingId(proposal.id); - const decidedBy = "oncall-alice"; + const decidedBy = OPERATOR_NAME; try { const updated = decision === "approved" @@ -282,7 +283,7 @@ export function Governance() { {[ { role: "operator", grant: "enrich · diagnose", who: "rca-service" }, { role: "operator", grant: "execute playbook:*", who: "action-service" }, - { role: "approver", grant: "approve · reject", who: "oncall-alice" }, + { role: "approver", grant: "approve · reject", who: OPERATOR_NAME }, { role: "coe-admin", grant: "graduate playbook:*", who: "feedback-service" }, ].map((r, i) => (
diff --git a/frontend/src/views/Incidents.tsx b/frontend/src/views/Incidents.tsx index eacaacc..3c4e5de 100644 --- a/frontend/src/views/Incidents.tsx +++ b/frontend/src/views/Incidents.tsx @@ -15,6 +15,7 @@ import { } from "@phosphor-icons/react"; import { Bezel, PageHead, SevChip, StatusChip, motion as m, timeAgo } from "../components/primitives"; import { loadSituations, loadSituationDetail, decideApproval, loadMetrics, loadOutcomes, draftAsync } from "../data/source"; +import { OPERATOR_NAME } from "../data/api"; import { useLiveData } from "../hooks/useLiveData"; import { pushToast } from "../hooks/useToast"; import type { View } from "../components/Shell"; @@ -258,7 +259,7 @@ export function Incidents({ if (proposing || !sel) return; setProposing(true); try { - const { run_id } = await draftAsync(sel, "oncall-alice"); + const { run_id } = await draftAsync(sel, OPERATOR_NAME); pushToast("success", "Drafting… see Agent Activity"); onFocusRun?.(run_id); onView?.("agent-activity");