// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-25-p0-web-probe-sentinel.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p8-web-probe-sentinel-recovery.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-multi-web-probe-sentinel.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p10-monitor-web-aggregation.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p11-monitor-web-observability-dashboard.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p12-cadence-scheduler-monitor-web.
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-28-p13-1206-multi-runner-boundaries.
// Responsibility: YAML-first CI/CD, image, GitOps and Argo command plan for the web-probe sentinel.
import { createHash, randomUUID } from "node:crypto";
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { repoRoot, rootPath } from "./config";
import { runCommand, type CommandResult } from "./command";
import { startJob } from "./jobs";
import { webProbeSentinelConfigPlan, withWebProbeSentinelConfigRendered } from "./hwlab-node-web-sentinel-config";
import { effectiveWebProbeSentinelPublicExposure, requireSentinelIdForRegistry, resolveWebProbeSentinel } from "./hwlab-node-web-sentinel-resolver";
import type { HwlabRuntimeLaneSpec } from "./hwlab-node-lanes";
import type { RenderedCliResult } from "./output";
import { runWebProbeRemoteArtifactJob } from "./web-probe-remote-artifact";

export type WebProbeSentinelConfigAction = "plan" | "status";
export type WebProbeSentinelImageAction = "status" | "build";
export type WebProbeSentinelControlPlaneAction = "plan" | "apply" | "status" | "trigger-current";
export type WebProbeSentinelMaintenanceAction = "status" | "start" | "stop";
export type WebProbeSentinelDashboardAction = "verify" | "screenshot";
export type WebProbeSentinelReportView = "summary" | "turn-summary" | "findings" | "trace-frame" | "auth-session-switch-summary";

export type WebProbeSentinelOptions =
  | {
    readonly kind: "config";
    readonly action: WebProbeSentinelConfigAction;
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly dryRun: boolean;
  }
  | {
    readonly kind: "image";
    readonly action: WebProbeSentinelImageAction;
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly dryRun: boolean;
    readonly confirm: boolean;
    readonly wait: boolean;
    readonly timeoutSeconds: number;
  }
  | {
    readonly kind: "control-plane";
    readonly action: WebProbeSentinelControlPlaneAction;
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly dryRun: boolean;
    readonly confirm: boolean;
    readonly wait: boolean;
    readonly timeoutSeconds: number;
  }
  | {
    readonly kind: "maintenance";
    readonly action: WebProbeSentinelMaintenanceAction;
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly dryRun: boolean;
    readonly confirm: boolean;
    readonly wait: boolean;
    readonly timeoutSeconds: number;
    readonly releaseId: string | null;
    readonly reason: string | null;
    readonly quickVerify: boolean;
  }
  | {
    readonly kind: "validate";
    readonly action: "validate";
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly dryRun: boolean;
    readonly confirm: boolean;
    readonly wait: boolean;
    readonly timeoutSeconds: number;
    readonly quickVerify: boolean;
  }
  | {
    readonly kind: "report";
    readonly action: "report";
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly view: WebProbeSentinelReportView;
    readonly runId: string | null;
    readonly latest: boolean;
    readonly traceId: string | null;
    readonly sampleSeq: number | null;
    readonly raw: boolean;
    readonly timeoutSeconds: number;
  }
  | {
    readonly kind: "dashboard";
    readonly action: WebProbeSentinelDashboardAction;
    readonly node: string;
    readonly lane: string;
    readonly sentinelId: string | null;
    readonly viewport: string;
    readonly localDir: string;
    readonly name: string | null;
    readonly timeoutMs: number;
    readonly waitTimeoutMs: number;
    readonly timeoutSeconds: number;
    readonly commandTimeoutSeconds: number;
    readonly fullPage: boolean;
    readonly raw: boolean;
  };

interface SentinelCicdState {
  readonly spec: HwlabRuntimeLaneSpec;
  readonly sentinelId: string;
  readonly configRefs: Record<string, string>;
  readonly configReady: boolean;
  readonly runtime: Record<string, unknown>;
  readonly cicd: Record<string, unknown>;
  readonly scenarios: unknown;
  readonly publicExposure: Record<string, unknown>;
  readonly secrets: Record<string, unknown>;
  readonly controlPlaneTarget: Record<string, unknown>;
  readonly controlPlaneNode: Record<string, unknown>;
  readonly sourceHead: SourceHead;
  readonly image: SentinelImagePlan;
  readonly manifests: readonly Record<string, unknown>[];
  readonly manifestSha256: string;
  readonly valuesRedacted: true;
}

interface SourceHead {
  readonly ok: boolean;
  readonly repository: string;
  readonly branch: string;
  readonly commit: string | null;
  readonly localHead: string | null;
  readonly result: CompactCommandResult;
}

interface SentinelImagePlan {
  readonly repository: string;
  readonly tag: string;
  readonly ref: string;
  readonly digestRef: string | null;
  readonly baseImage: string;
  readonly buildContext: string;
  readonly entrypoint: string;
  readonly dockerfileSha256: string;
  readonly dockerfilePreview: string;
  readonly monitorWeb: Record<string, unknown>;
}

interface SentinelObservedStatus {
  readonly sourceMirror: Record<string, unknown>;
  readonly registry: Record<string, unknown>;
  readonly gitMirror: Record<string, unknown>;
  readonly gitops: Record<string, unknown>;
  readonly argo: Record<string, unknown>;
  readonly runtime: Record<string, unknown>;
}

interface SentinelObservedExpectation {
  readonly gitopsRevision: string | null;
  readonly runtimeImage: string | null;
}

interface SentinelRemoteJobResult {
  readonly ok: boolean;
  readonly phase: string;
  readonly jobName: string;
  readonly payload: Record<string, unknown>;
  readonly polls?: number;
  readonly elapsedMs?: number;
  readonly create?: Record<string, unknown>;
  readonly probe?: Record<string, unknown>;
  readonly valuesRedacted: true;
}

interface CompactCommandResult {
  readonly exitCode: number | null;
  readonly timedOut: boolean;
  readonly stdoutBytes: number;
  readonly stderrBytes: number;
  readonly stdoutPreview: string;
  readonly stderrPreview: string;
}

interface ChildCliResult {
  readonly ok: boolean;
  readonly parsed: Record<string, unknown> | null;
  readonly result: CompactCommandResult & { stdoutTail: string; stderrTail: string };
}

const SPEC_REF = "PJ2026-01060508 Web哨兵 draft-2026-06-27-p11-monitor-web-observability-dashboard";

export function runWebProbeSentinelCommand(spec: HwlabRuntimeLaneSpec, options: WebProbeSentinelOptions): RenderedCliResult {
  if (options.kind === "config") return withWebProbeSentinelConfigRendered(webProbeSentinelConfigPlan(spec, options.action, options.sentinelId));
  requireSentinelIdForRegistry(spec, options.sentinelId, `web-probe sentinel ${options.kind}`);
  const state = loadSentinelCicdState(spec, options.sentinelId, options.timeoutSeconds);
  if (options.kind === "image") return runSentinelImage(state, options);
  if (options.kind === "control-plane") return runSentinelControlPlane(state, options);
  if (options.kind === "maintenance") return runSentinelMaintenance(state, options);
  if (options.kind === "validate") return runSentinelValidate(state, options);
  if (options.kind === "dashboard") return runSentinelDashboard(state, options);
  return runSentinelReport(state, options);
}

function runSentinelImage(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "image" }>): RenderedCliResult {
  const command = `web-probe sentinel image ${options.action}`;
  if (options.action === "build" && options.confirm) {
    if (!options.wait) return renderAsyncSentinelJob(state, "image", "build", options.timeoutSeconds);
    return runSentinelImageBuildConfirmed(state, options);
  }
  const sourceMirror = options.action === "status" ? probeSourceMirror(state, options.timeoutSeconds) : null;
  const registry = options.action === "status" ? probeImageRegistry(state, options.timeoutSeconds) : null;
  const sourceMirrorReady = options.action !== "status" || record(sourceMirror).ok === true;
  const registryReady = options.action !== "status" || record(registry?.probe).present === true;
  const result = {
    ok: state.configReady && state.sourceHead.ok && sourceMirrorReady && registryReady,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    sentinelId: state.sentinelId,
    mode: options.action === "status" ? "status" : options.confirm ? "confirm" : "dry-run",
    mutation: false,
    specRef: SPEC_REF,
    source: state.sourceHead,
    sourceMirror,
    image: state.image,
    registry,
    blocker: sourceMirrorReady
      ? registryReady ? null : { code: "sentinel-image-missing", reason: "expected sentinel image tag is not present in the node-local registry" }
      : { code: "sentinel-source-mirror-not-ready", reason: "source.gitMirrorReadUrl does not expose the selected source commit yet" },
    next: {
      status: `bun scripts/cli.ts web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)}`,
      dryRun: `bun scripts/cli.ts web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --dry-run`,
      confirm: `bun scripts/cli.ts web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --confirm`,
      controlPlanePlan: `bun scripts/cli.ts web-probe sentinel control-plane plan --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --dry-run`,
    },
    valuesRedacted: true,
  };
  return rendered(result.ok, command, renderImageResult(result));
}

function runSentinelControlPlane(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "control-plane" }>): RenderedCliResult {
  const command = `web-probe sentinel control-plane ${options.action}`;
  const mutationAction = options.action === "apply" || options.action === "trigger-current";
  if (options.confirm && mutationAction) {
    if (!options.wait) return renderAsyncSentinelJob(state, "control-plane", options.action, options.timeoutSeconds);
    return runSentinelControlPlaneConfirmed(state, options);
  }
  const observed = options.action === "status" ? collectSentinelObservedStatus(state, options.timeoutSeconds) : null;
  const observedReady = options.action !== "status" || sentinelObservedReady(record(observed));
  const observedWarnings = options.action === "status" ? sentinelObservedWarnings(record(observed)) : [];
  const pipelineRun = sentinelPipelineRunName(state);
  const result = {
    ok: state.configReady && state.sourceHead.ok && observedReady,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    sentinelId: state.sentinelId,
    mode: options.action === "status" ? "status" : options.confirm ? "confirm" : "dry-run",
    mutation: false,
    specRef: SPEC_REF,
    source: state.sourceHead,
    image: state.image,
    pipelineRun,
    gitops: {
      path: stringField(state.cicd, "gitopsPath"),
      targetRevision: stringAt(state.cicd, "argo.targetRevision"),
      manifestObjects: state.manifests.length,
      manifestSha256: state.manifestSha256,
    },
    argo: {
      namespace: stringAt(state.cicd, "argo.namespace"),
      projectName: stringAt(state.cicd, "argo.projectName"),
      applicationName: stringAt(state.cicd, "argo.applicationName"),
    },
    maintenance: {
      startCommand: stringAt(state.cicd, "maintenance.startCommand"),
      stopCommand: stringAt(state.cicd, "maintenance.stopCommand"),
      serviceUnavailablePolicy: stringAt(state.cicd, "targetValidation.serviceUnavailablePolicy"),
    },
    validation: {
      scenarioId: stringAt(state.cicd, "targetValidation.scenarioId"),
      maxSeconds: numberAt(state.cicd, "targetValidation.maxSeconds"),
      controlPlaneWaitMaxSeconds: controlPlaneWaitWarningSeconds(state),
      quickVerifyMode: "manual-validate",
      automaticSecondPath: false,
    },
    manifests: {
      objects: manifestObjectSummary(state.manifests),
      sha256: state.manifestSha256,
    },
    observed,
    warnings: observedWarnings,
    blocker: null,
    next: controlPlaneNext(state, options.action),
    valuesRedacted: true,
  };
  return rendered(result.ok, command, renderControlPlaneResult(result));
}

function loadSentinelCicdState(spec: HwlabRuntimeLaneSpec, sentinelId: string | null, timeoutSeconds: number): SentinelCicdState {
  const sentinel = resolveWebProbeSentinel(spec, sentinelId);
  const configPlan = webProbeSentinelConfigPlan(spec, "status", sentinel.id);
  const runtime = recordTarget(readConfigRefTarget(sentinel.configRefs.runtime), sentinel.configRefs.runtime);
  const cicd = recordTarget(readConfigRefTarget(sentinel.configRefs.cicd), sentinel.configRefs.cicd);
  const scenarios = readConfigRefTarget(sentinel.configRefs.scenarios);
  const rawPublicExposure = recordTarget(readConfigRefTarget(sentinel.configRefs.publicExposure), sentinel.configRefs.publicExposure);
  const publicExposure = effectiveWebProbeSentinelPublicExposure(spec, sentinel.id, rawPublicExposure);
  const secrets = recordTarget(readConfigRefTarget(sentinel.configRefs.secrets), sentinel.configRefs.secrets);
  const controlPlaneRef = stringField(cicd, "controlPlaneConfigRef");
  const controlPlaneTarget = recordTarget(readConfigRefTarget(controlPlaneRef), controlPlaneRef);
  const controlPlaneConfig = recordTarget(readConfigFile(configRefFile(controlPlaneRef)), configRefFile(controlPlaneRef));
  const nodeId = stringField(controlPlaneTarget, "node");
  const controlPlaneNode = recordTarget(valueAtPath(controlPlaneConfig, `nodes.${nodeId}`), `${configRefFile(controlPlaneRef)}#nodes.${nodeId}`);
  const sourceHead = resolveSourceHead(cicd, timeoutSeconds);
  const image = sentinelImagePlan(cicd, sourceHead);
  const manifests = renderSentinelManifests(spec, sentinel.id, runtime, cicd, scenarios, publicExposure, secrets, image);
  const manifestYaml = `${manifests.map((item) => Bun.YAML.stringify(item).trim()).join("\n---\n")}\n`;
  return {
    spec,
    sentinelId: sentinel.id,
    configRefs: sentinel.configRefs,
    configReady: configPlan.ok,
    runtime,
    cicd,
    scenarios,
    publicExposure,
    secrets,
    controlPlaneTarget,
    controlPlaneNode,
    sourceHead,
    image,
    manifests,
    manifestSha256: sha256(manifestYaml),
    valuesRedacted: true,
  };
}

function resolveSourceHead(cicd: Record<string, unknown>, timeoutSeconds: number): SourceHead {
  const repository = stringAt(cicd, "source.repository");
  const branch = stringAt(cicd, "source.branch");
  const remote = runCommand(["git", "ls-remote", "origin", `refs/heads/${branch}`], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const local = runCommand(["git", "rev-parse", "HEAD"], repoRoot, { timeoutMs: 10_000 });
  const commit = /^[0-9a-f]{40}\b/iu.exec(remote.stdout.trim())?.[0].toLowerCase() ?? null;
  const localHead = /^[0-9a-f]{40}$/iu.test(local.stdout.trim()) ? local.stdout.trim().toLowerCase() : null;
  return {
    ok: remote.exitCode === 0 && commit !== null,
    repository,
    branch,
    commit,
    localHead,
    result: compactCommand(remote),
  };
}

function sentinelImagePlan(cicd: Record<string, unknown>, sourceHead: SourceHead): SentinelImagePlan {
  const repository = stringAt(cicd, "image.repository");
  const tag = sourceHead.commit === null ? "source-unresolved" : sourceHead.commit.slice(0, 12);
  const baseImageRef = stringAt(cicd, "image.baseImageRef");
  const baseImage = stringTarget(readConfigRefTarget(baseImageRef), baseImageRef);
  const entrypoint = stringAt(cicd, "source.entrypoint");
  const dockerfile = sentinelDockerfile(baseImage, entrypoint);
  return {
    repository,
    tag,
    ref: `${repository}:${tag}`,
    digestRef: null,
    baseImage,
    buildContext: stringAt(cicd, "source.buildContext"),
    entrypoint,
    dockerfileSha256: sha256(dockerfile),
    dockerfilePreview: dockerfile,
    monitorWeb: monitorWebCicdPlan(cicd),
  };
}

function sentinelDockerfile(baseImage: string, entrypoint: string): string {
  return [
    `FROM ${baseImage}`,
    "WORKDIR /app",
    "COPY . /app",
    "RUN if [ -d /opt/hwlab-ci-node-deps/node_modules ]; then mkdir -p /app/node_modules; for dep in /opt/hwlab-ci-node-deps/node_modules/*; do ln -sf \"$dep\" \"/app/node_modules/$(basename \"$dep\")\"; done; fi",
    "RUN printf '%s\\n' '#!/bin/sh' 'exec bun /app/scripts/ssh-cli.ts \"$@\"' > /usr/local/bin/trans && chmod 0755 /usr/local/bin/trans",
    "RUN bun scripts/verify-web-probe-sentinel-monitor-web.ts",
    "ENV NODE_ENV=production",
    `ENTRYPOINT ["bun", "${entrypoint}"]`,
    "",
  ].join("\n");
}

function monitorWebCicdPlan(cicd: Record<string, unknown>): Record<string, unknown> {
  return {
    stack: stringAtNullable(cicd, "monitorWeb.frontendStack") ?? "vue3-vendored-browser-build",
    runtimeMode: stringAtNullable(cicd, "monitorWeb.runtimeMode") ?? "runner-served-bridge",
    assetRoot: stringAtNullable(cicd, "monitorWeb.assetRoot") ?? "scripts/assets/web-probe-sentinel-monitor-web",
    verifyCommand: "bun scripts/verify-web-probe-sentinel-monitor-web.ts",
    gitMirrorReadUrl: stringAt(cicd, "source.gitMirrorReadUrl"),
    sourceMode: stringAt(cicd, "builder.sourceMode"),
    envReuseMode: stringAtNullable(cicd, "monitorWeb.envReuse.mode") ?? "docker-layer-and-ci-node-deps",
    envReuseNodeDepsPath: stringAtNullable(cicd, "monitorWeb.envReuse.nodeDepsPath") ?? "/opt/hwlab-ci-node-deps/node_modules",
    ciBudgetSeconds: numberAtNullable(cicd, "monitorWeb.ciBudget.maxSeconds") ?? numberAt(cicd, "confirmWait.maxSeconds"),
    valuesRedacted: true,
  };
}

function renderSentinelManifests(
  spec: HwlabRuntimeLaneSpec,
  sentinelId: string,
  runtime: Record<string, unknown>,
  cicd: Record<string, unknown>,
  scenarios: unknown,
  publicExposure: Record<string, unknown>,
  secrets: Record<string, unknown>,
  image: SentinelImagePlan,
): readonly Record<string, unknown>[] {
  const namespace = stringAt(runtime, "namespace");
  const labels = {
    "app.kubernetes.io/name": stringAt(runtime, "deploymentName"),
    "app.kubernetes.io/part-of": "hwlab-web-probe-sentinel",
    "app.kubernetes.io/managed-by": "unidesk",
    "unidesk.ai/spec-ref": "PJ2026-01060508",
    "unidesk.ai/node": spec.nodeId,
    "unidesk.ai/lane": spec.lane,
    "unidesk.ai/web-probe-sentinel-id": sentinelId,
  };
  const deploymentName = stringAt(runtime, "deploymentName");
  const serviceName = stringAt(runtime, "serviceName");
  const servicePort = numberAt(runtime, "servicePort");
  const pvcStorage = stringAt(runtime, "pvcStorage");
  const stateRoot = stringAt(runtime, "stateRoot");
  const sentinelEnv = sentinelContainerEnv(sentinelId, secrets);
  const cadenceJob = sentinelCadenceCronJobPlan(spec, sentinelId, runtime, cicd, scenarios, image.ref, sentinelEnv);
  return [
    {
      apiVersion: "v1",
      kind: "ServiceAccount",
      metadata: { name: stringAt(runtime, "serviceAccountName"), namespace, labels },
    },
    {
      apiVersion: "v1",
      kind: "PersistentVolumeClaim",
      metadata: { name: stringAt(runtime, "pvcName"), namespace, labels },
      spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: pvcStorage } } },
    },
    {
      apiVersion: "v1",
      kind: "ConfigMap",
      metadata: { name: `${deploymentName}-config`, namespace, labels },
      data: {
        "config-summary.json": JSON.stringify({
          specRef: SPEC_REF,
          node: spec.nodeId,
          lane: spec.lane,
          sentinelId,
          publicBaseUrl: stringAt(publicExposure, "publicBaseUrl"),
          routePrefix: stringAtNullable(publicExposure, "routePrefix") ?? "/",
          gitopsPath: stringAt(cicd, "gitopsPath"),
          valuesRedacted: true,
        }, null, 2),
      },
    },
    {
      apiVersion: "apps/v1",
      kind: "Deployment",
      metadata: { name: deploymentName, namespace, labels },
      spec: {
        replicas: numberAt(runtime, "replicas"),
        selector: { matchLabels: { "app.kubernetes.io/name": deploymentName } },
        template: {
          metadata: { labels },
          spec: {
            serviceAccountName: stringAt(runtime, "serviceAccountName"),
            containers: [{
              name: "sentinel",
              image: image.ref,
              imagePullPolicy: "IfNotPresent",
              args: [
                "--node",
                spec.nodeId,
                "--lane",
                spec.lane,
                "--sentinel",
                sentinelId,
                "--state-root",
                stateRoot,
                "--host",
                stringAt(runtime, "listenHost"),
                "--port",
                String(servicePort),
              ],
              env: sentinelEnv,
              ports: [{ name: "http", containerPort: servicePort }],
              readinessProbe: { httpGet: { path: stringAt(runtime, "healthPath"), port: "http" } },
              livenessProbe: { httpGet: { path: stringAt(runtime, "healthPath"), port: "http" } },
              volumeMounts: [{ name: "state", mountPath: stateRoot }],
            }],
            volumes: [{ name: "state", persistentVolumeClaim: { claimName: stringAt(runtime, "pvcName") } }],
          },
        },
      },
    },
    {
      apiVersion: "v1",
      kind: "Service",
      metadata: { name: serviceName, namespace, labels },
      spec: { type: "ClusterIP", selector: { "app.kubernetes.io/name": deploymentName }, ports: [{ name: "http", port: servicePort, targetPort: "http" }] },
    },
    ...(cadenceJob === null ? [] : [cadenceJob]),
    {
      apiVersion: "apps/v1",
      kind: "Deployment",
      metadata: { name: stringAt(publicExposure, "frpc.deploymentName"), namespace, labels: { ...labels, "app.kubernetes.io/component": "tunnel" } },
      spec: {
        replicas: 1,
        selector: { matchLabels: { "app.kubernetes.io/name": stringAt(publicExposure, "frpc.deploymentName") } },
        template: {
          metadata: {
            labels: { ...labels, "app.kubernetes.io/name": stringAt(publicExposure, "frpc.deploymentName"), "app.kubernetes.io/component": "tunnel" },
            annotations: {
              "unidesk.ai/public-base-url": stringAt(publicExposure, "publicBaseUrl"),
              "unidesk.ai/frp-server": `${stringAt(publicExposure, "frpc.serverAddr")}:${numberAt(publicExposure, "frpc.serverPort")}`,
              "unidesk.ai/frp-remote-port": String(numberAt(publicExposure, "frpc.httpProxy.remotePort")),
            },
          },
          spec: {
            containers: [{
              name: "frpc",
              image: stringAt(publicExposure, "frpc.image"),
              imagePullPolicy: "IfNotPresent",
              args: ["-c", "/etc/frp/frpc.toml"],
              volumeMounts: [{ name: "frpc-config", mountPath: "/etc/frp/frpc.toml", subPath: stringAt(publicExposure, "frpc.secretKey"), readOnly: true }],
            }],
            volumes: [{ name: "frpc-config", secret: { secretName: stringAt(publicExposure, "frpc.secretName") } }],
          },
        },
      },
    },
    {
      apiVersion: "networking.k8s.io/v1",
      kind: "NetworkPolicy",
      metadata: { name: `${deploymentName}-egress`, namespace, labels },
      spec: {
        podSelector: { matchLabels: { "app.kubernetes.io/name": deploymentName } },
        policyTypes: ["Ingress", "Egress"],
        ingress: [{ from: [{ namespaceSelector: {} }], ports: [{ protocol: "TCP", port: servicePort }] }],
        egress: [{ to: [{ namespaceSelector: {} }] }],
      },
    },
    {
      apiVersion: "argoproj.io/v1alpha1",
      kind: "Application",
      metadata: { name: stringAt(cicd, "argo.applicationName"), namespace: stringAt(cicd, "argo.namespace"), labels },
      spec: {
        project: stringAt(cicd, "argo.projectName"),
        source: {
          repoURL: stringAt(cicd, "argo.repoURL"),
          targetRevision: stringAt(cicd, "argo.targetRevision"),
          path: stringAt(cicd, "gitopsPath"),
        },
        destination: { server: "https://kubernetes.default.svc", namespace },
        syncPolicy: { automated: { prune: true, selfHeal: true } },
      },
    },
  ];
}

function sentinelContainerEnv(sentinelId: string, secrets: Record<string, unknown>): readonly Record<string, unknown>[] {
  const env: Record<string, unknown>[] = [{ name: "UNIDESK_WEB_PROBE_SENTINEL_ID", value: sentinelId }];
  const sourcesByPurpose = new Map<string, Record<string, unknown>>();
  for (const source of arrayAt(secrets, "sources").map(record)) {
    const purpose = stringAtNullable(source, "purpose");
    if (purpose !== null) sourcesByPurpose.set(purpose, source);
  }
  const used = new Set(env.map((item) => String(item.name ?? "")));
  const pushEnv = (item: Record<string, unknown>): void => {
    const name = String(item.name ?? "");
    if (name.length === 0 || used.has(name)) return;
    used.add(name);
    env.push(item);
  };
  for (const runtimeSecret of arrayAt(secrets, "runtimeSecrets").map(record)) {
    const secretName = stringAtNullable(runtimeSecret, "name");
    if (secretName === null) continue;
    for (const item of arrayAt(runtimeSecret, "data").map(record)) {
      const targetKey = stringAtNullable(item, "targetKey");
      const sourcePurpose = stringAtNullable(item, "sourcePurpose");
      const sourceKey = sourcePurpose === null ? null : stringAtNullable(sourcesByPurpose.get(sourcePurpose), "sourceKey");
      const sourceKeyEnvName = sourcePurpose === "bootstrap-admin" || sourcePurpose === "prompt-set" ? sourceKey : null;
      if (targetKey !== null && sourceKeyEnvName !== null && /^[A-Za-z_][A-Za-z0-9_]*$/u.test(sourceKeyEnvName)) {
        pushEnv({ name: sourceKeyEnvName, valueFrom: { secretKeyRef: { name: secretName, key: targetKey } } });
      }
      const envName = sourcePurpose === null || targetKey === null ? null : accountSecretEnvName(sourcePurpose, targetKey);
      if (envName === null) continue;
      pushEnv({ name: envName, valueFrom: { secretKeyRef: { name: secretName, key: targetKey } } });
    }
  }
  return env;
}

function sentinelCadenceCronJobPlan(
  spec: HwlabRuntimeLaneSpec,
  sentinelId: string,
  runtime: Record<string, unknown>,
  cicd: Record<string, unknown>,
  scenarios: unknown,
  imageRef: string,
  sentinelEnv: readonly Record<string, unknown>[],
): Record<string, unknown> | null {
  const scenarioId = stringAtNullable(cicd, "targetValidation.scenarioId");
  if (scenarioId === null) return null;
  const scenario = scenarioRows(scenarios).find((item) => item.id === scenarioId && item.enabled !== false) ?? null;
  if (scenario === null) return null;
  const cadenceSeconds = typeof scenario.cadence === "string" ? parseDurationSeconds(scenario.cadence) : null;
  const schedule = cadenceSeconds === null ? null : cronScheduleForCadenceSeconds(cadenceSeconds);
  if (schedule === null) return null;
  const namespace = stringAt(runtime, "namespace");
  const deploymentName = stringAt(runtime, "deploymentName");
  const serviceAccountName = stringAt(runtime, "serviceAccountName");
  const timeoutSeconds = numberAtNullable(cicd, "targetValidation.maxSeconds") ?? numberAtNullable(scenario, "maxRunSeconds") ?? 300;
  const mainServerHost = stringAtNullable(cicd, "scheduler.mainServerHost");
  const name = safeKubernetesSegment(`${deploymentName}-quick-verify`, 52);
  const labels = {
    "app.kubernetes.io/name": name,
    "app.kubernetes.io/part-of": "hwlab-web-probe-sentinel",
    "app.kubernetes.io/component": "cadence-scheduler",
    "app.kubernetes.io/managed-by": "unidesk",
    "unidesk.ai/spec-ref": "PJ2026-01060508",
    "unidesk.ai/node": spec.nodeId,
    "unidesk.ai/lane": spec.lane,
    "unidesk.ai/web-probe-sentinel-id": sentinelId,
  };
  return {
    apiVersion: "batch/v1",
    kind: "CronJob",
    metadata: {
      name,
      namespace,
      labels,
      annotations: {
        "unidesk.ai/cadence": String(scenario.cadence),
        "unidesk.ai/target-validation-max-seconds": String(timeoutSeconds),
      },
    },
    spec: {
      schedule,
      concurrencyPolicy: "Forbid",
      successfulJobsHistoryLimit: 3,
      failedJobsHistoryLimit: 5,
      startingDeadlineSeconds: Math.max(60, cadenceSeconds),
      jobTemplate: {
        spec: {
          activeDeadlineSeconds: timeoutSeconds + 60,
          ttlSecondsAfterFinished: 86400,
          backoffLimit: 0,
          template: {
            metadata: { labels },
            spec: {
              restartPolicy: "Never",
              serviceAccountName,
              containers: [{
                name: "quick-verify",
                image: imageRef,
                imagePullPolicy: "IfNotPresent",
                command: ["bun", "scripts/cli.ts"],
                args: [
                  "web-probe",
                  "sentinel",
                  "validate",
                  "--node",
                  spec.nodeId,
                  "--lane",
                  spec.lane,
                  "--sentinel",
                  sentinelId,
                  "--quick-verify",
                  "--confirm",
                  "--wait",
                  "--timeout-seconds",
                  String(timeoutSeconds),
                ],
                env: [
                  ...sentinelEnv,
                  { name: "UNIDESK_WEB_PROBE_SENTINEL_DIRECT_SERVICE", value: "1" },
                  ...(mainServerHost === null ? [] : [{ name: "UNIDESK_MAIN_SERVER_HOST", value: mainServerHost }]),
                ],
              }],
            },
          },
        },
      },
    },
  };
}

function scenarioRows(value: unknown): Record<string, unknown>[] {
  if (Array.isArray(value)) return value.map(record);
  if (!isRecord(value)) return [];
  if (Array.isArray(value.scenarios)) return value.scenarios.map(record);
  if (isRecord(value.workflow)) return [value.workflow];
  return [value];
}

function parseDurationSeconds(value: string): number | null {
  const match = /^(\d+)(ms|s|m|h)$/u.exec(value.trim());
  if (match === null) return null;
  const amount = Number(match[1]);
  const unit = match[2];
  if (unit === "ms") return Math.max(60, Math.ceil(amount / 1000));
  if (unit === "s") return Math.max(60, amount);
  if (unit === "m") return amount * 60;
  if (unit === "h") return amount * 3600;
  return null;
}

function cronScheduleForCadenceSeconds(seconds: number): string | null {
  if (!Number.isFinite(seconds) || seconds <= 0) return null;
  if (seconds <= 60) return "* * * * *";
  if (seconds % 60 === 0) {
    const minutes = Math.trunc(seconds / 60);
    if (minutes >= 1 && minutes <= 59) return `*/${minutes} * * * *`;
    if (minutes % 60 === 0) {
      const hours = Math.trunc(minutes / 60);
      if (hours >= 1 && hours <= 23) return `0 */${hours} * * *`;
      if (hours === 24) return "0 0 * * *";
    }
  }
  return null;
}

function accountSecretEnvName(sourcePurpose: string, targetKey: string): string | null {
  if (!/^account-[a-z0-9-]+$/u.test(sourcePurpose) || !targetKey.endsWith(".json")) return null;
  const segment = sourcePurpose.toUpperCase().replace(/[^A-Z0-9]+/gu, "_").replace(/^_+|_+$/gu, "");
  return segment.length === 0 ? null : `HWLAB_WEB_${segment}_JSON`;
}

function quickVerifyAccountEnv(state: SentinelCicdState): { ok: boolean; env: NodeJS.ProcessEnv; summary: Record<string, unknown> } {
  const sourcesByPurpose = new Map<string, Record<string, unknown>>();
  for (const source of arrayAt(state.secrets, "sources").map(record)) {
    const purpose = stringAtNullable(source, "purpose");
    if (purpose !== null) sourcesByPurpose.set(purpose, source);
  }
  const env: NodeJS.ProcessEnv = {};
  const items: Record<string, unknown>[] = [];
  const missing: Record<string, unknown>[] = [];
  for (const runtimeSecret of arrayAt(state.secrets, "runtimeSecrets").map(record)) {
    const secretName = stringAtNullable(runtimeSecret, "name");
    for (const item of arrayAt(runtimeSecret, "data").map(record)) {
      const targetKey = stringAtNullable(item, "targetKey");
      const sourcePurpose = stringAtNullable(item, "sourcePurpose");
      const envName = sourcePurpose === null || targetKey === null ? null : accountSecretEnvName(sourcePurpose, targetKey);
      if (envName === null || sourcePurpose === null || targetKey === null) continue;
      const source = sourcesByPurpose.get(sourcePurpose);
      const runtimeValue = process.env[envName];
      if (source === undefined) {
        if (runtimeValue !== undefined && runtimeValue.length > 0) {
          env[envName] = runtimeValue;
          items.push({
            envName,
            secretName,
            targetKey,
            sourcePurpose,
            sourceMode: "runtime-env",
            fingerprint: `sha256:${createHash("sha256").update(runtimeValue).digest("hex").slice(0, 16)}`,
            valuesRedacted: true,
          });
          continue;
        }
        missing.push({ envName, secretName, targetKey, sourcePurpose, reason: "source-purpose-missing", valuesRedacted: true });
        continue;
      }
      const sourceRef = stringAt(source, "sourceRef");
      const sourceKey = stringAt(source, "sourceKey");
      const material = readSentinelSecretSourceValue(source);
      if (!material.ok) {
        if (runtimeValue !== undefined && runtimeValue.length > 0) {
          env[envName] = runtimeValue;
          items.push({
            envName,
            secretName,
            targetKey,
            sourcePurpose,
            sourceRef,
            sourceKey,
            sourceMode: "runtime-env",
            fingerprint: `sha256:${createHash("sha256").update(runtimeValue).digest("hex").slice(0, 16)}`,
            valuesRedacted: true,
          });
          continue;
        }
        missing.push({ envName, secretName, targetKey, sourcePurpose, sourceRef, sourceKey, reason: material.error, sourcePath: material.sourcePath, valuesRedacted: true });
        continue;
      }
      const value = stringAt(material, "value");
      env[envName] = value;
      items.push({
        envName,
        secretName,
        targetKey,
        sourcePurpose,
        sourceRef,
        sourceKey,
        fingerprint: `sha256:${createHash("sha256").update(value).digest("hex").slice(0, 16)}`,
        valuesRedacted: true,
      });
    }
  }
  const summary = {
    ok: missing.length === 0,
    envCount: items.length,
    items,
    missing,
    valuesRedacted: true,
  };
  return { ok: missing.length === 0, env, summary };
}

function normalizeRoutePrefix(value: string | null): string {
  if (value === null || value.trim() === "" || value.trim() === "/") return "/";
  const prefixed = value.trim().startsWith("/") ? value.trim() : `/${value.trim()}`;
  return prefixed.replace(/\/+$/u, "") || "/";
}

function probeImageRegistry(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const endpoint = stringAt(state.controlPlaneNode, "registry.endpoint");
  const repoTag = state.image.ref.replace(`${endpoint}/`, "");
  const repo = repoTag.slice(0, repoTag.lastIndexOf(":"));
  const tag = repoTag.slice(repoTag.lastIndexOf(":") + 1);
  const route = stringAt(state.controlPlaneNode, "route");
  const script = [
    "set +e",
    `url=${shellQuote(`http://${endpoint}/v2/${repo}/manifests/${tag}`)}`,
    "headers=$(mktemp)",
    "if command -v curl >/dev/null 2>&1 && curl -fsSI --max-time 5 \"$url\" >\"$headers\" 2>/tmp/web-probe-sentinel-image.err; then present=true; else present=false; fi",
    "digest=$(awk 'BEGIN{IGNORECASE=1} /^docker-content-digest:/ {gsub(/\\r/,\"\",$2); print $2; exit}' \"$headers\" 2>/dev/null)",
    "python3 - \"$present\" \"$digest\" \"$url\" <<'PY'",
    "import json, sys",
    "print(json.dumps({'present': sys.argv[1] == 'true', 'digest': sys.argv[2] or None, 'url': sys.argv[3], 'valuesRedacted': True}))",
    "PY",
  ].join("\n");
  const result = runCommand(["trans", route, "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  return {
    ok: result.exitCode === 0,
    probe: parseJsonObject(result.stdout),
    result: compactCommand(result),
  };
}

function runSentinelImageBuildConfirmed(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "image" }>): RenderedCliResult {
  const startedAt = Date.now();
  const command = "web-probe sentinel image build";
  const sourceMirrorProbe = probeSourceMirror(state, Math.min(options.timeoutSeconds, 20));
  const sourceMirrorSync = record(sourceMirrorProbe).ok === true ? sentinelSourceMirrorAlreadyPresentResult(state, sourceMirrorProbe) : runSentinelSourceMirrorSyncJob(state, options.timeoutSeconds);
  const sourceMirrorReady = sourceMirrorSync.ok === true;
  const publish = sourceMirrorReady
    ? runSentinelPublishJob(state, false, options.timeoutSeconds)
    : sentinelBlockedRemoteResult("source-mirror-sync-blocked", "sentinel source mirror sync failed; publish job was not started");
  const registry = probeImageRegistry(state, options.timeoutSeconds);
  const registryReady = record(registry.probe).present === true;
  const ok = state.configReady && state.sourceHead.ok && sourceMirrorReady && publish.ok === true && registryReady;
  const elapsedMs = Date.now() - startedAt;
  const cicdWaitWarningSeconds = controlPlaneWaitWarningSeconds(state);
  const result = {
    ok,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: "confirm-wait",
    mutation: true,
    specRef: SPEC_REF,
    source: state.sourceHead,
    image: state.image,
    registry,
    sourceMirrorSync,
    publish,
    elapsedMs,
    warnings: [
      ...sentinelCicdElapsedWarnings(elapsedMs, "sentinel image build confirm-wait", cicdWaitWarningSeconds),
      ...sentinelCicdElapsedWarnings(record(sourceMirrorSync).elapsedMs, "sentinel source mirror sync", cicdWaitWarningSeconds),
      ...sentinelCicdElapsedWarnings(record(publish).elapsedMs, "sentinel publish", cicdWaitWarningSeconds),
      ...sourceMirrorAlreadyReadyWarnings(state, sourceMirrorSync),
    ],
    blocker: ok
      ? null
      : !sourceMirrorReady
        ? { code: "sentinel-source-mirror-sync-failed", reason: "source mirror sync did not complete; investigate git mirror/proxy before image publish" }
        : publish.ok !== true
          ? { code: "sentinel-image-publish-failed", reason: "remote image publish job failed before registry validation" }
          : { code: "sentinel-image-registry-missing", reason: "image publish completed but expected registry tag is not visible" },
    next: {
      status: `bun scripts/cli.ts web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)}`,
      controlPlaneTrigger: `bun scripts/cli.ts web-probe sentinel control-plane trigger-current --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --confirm`,
    },
    valuesRedacted: true,
  };
  return rendered(result.ok, command, renderImageResult(result));
}

function runSentinelControlPlaneConfirmed(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "control-plane" }>): RenderedCliResult {
  const startedAt = Date.now();
  const command = `web-probe sentinel control-plane ${options.action}`;
  const applyOnly = options.action === "apply";
  const cicdWaitWarningSeconds = controlPlaneWaitWarningSeconds(state);
  const deadline = startedAt + cicdWaitWarningSeconds * 1000;
  const remainingCicdWaitSeconds = () => remainingSeconds(deadline, Math.min(options.timeoutSeconds, cicdWaitWarningSeconds));
  const sourceMirrorProbe = applyOnly ? null : probeSourceMirror(state, Math.min(remainingCicdWaitSeconds(), 20));
  const sourceMirrorSync = applyOnly ? null : record(sourceMirrorProbe).ok === true ? sentinelSourceMirrorAlreadyPresentResult(state, sourceMirrorProbe) : runSentinelSourceMirrorSyncJob(state, remainingCicdWaitSeconds());
  const sourceMirrorReady = applyOnly || record(sourceMirrorSync).ok === true;
  const publish = applyOnly
    ? null
    : sourceMirrorReady
      ? runSentinelPublishJob(state, true, remainingCicdWaitSeconds())
      : sentinelBlockedRemoteResult("source-mirror-sync-blocked", "sentinel source mirror sync failed; publish job was not started");
  const flush = !applyOnly && record(publish).ok === true
    ? startSentinelGitMirrorFlushAsync(state)
    : null;
  const runtimeSecretsApply = applySentinelRuntimeSecrets(state, remainingCicdWaitSeconds());
  const publicExposureApply = applySentinelPublicExposure(state, remainingCicdWaitSeconds());
  const argoApply = applySentinelArgoApplication(state, remainingCicdWaitSeconds());
  const observed = waitForSentinelObservedStatus(state, remainingCicdWaitSeconds(), undefined, false);
  const observedReady = sentinelObservedReady(observed);
  const targetValidation = null;
  const targetValidationBlocked = false;
  const ok = state.configReady
    && state.sourceHead.ok
    && sourceMirrorReady
    && (applyOnly || record(publish).ok === true)
    && (applyOnly || record(flush).ok === true)
    && record(runtimeSecretsApply).ok === true
    && record(publicExposureApply).ok === true
    && record(argoApply).ok === true
    && observedReady;
  const elapsedMs = Date.now() - startedAt;
  const blocker = ok ? null : {
    code: !sourceMirrorReady ? "sentinel-source-mirror-sync-failed" : record(runtimeSecretsApply).ok === false ? "sentinel-runtime-secret-sync-failed" : "sentinel-control-plane-not-ready",
    reason: !sourceMirrorReady
      ? "source mirror sync did not complete; investigate git mirror/proxy before control-plane publish"
      : record(runtimeSecretsApply).ok === false
        ? "one or more YAML-declared runtime Secrets were not synced from sourceRef"
      : "one or more publish, publicExposure, Argo or runtime observation checks did not pass",
  };
  const result = {
    ok,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: "confirm-wait",
    mutation: true,
    specRef: SPEC_REF,
    source: state.sourceHead,
    image: state.image,
    pipelineRun: sentinelPipelineRunName(state),
    gitops: {
      path: stringAt(state.cicd, "gitopsPath"),
      targetRevision: stringAt(state.cicd, "argo.targetRevision"),
      manifestObjects: state.manifests.length,
      manifestSha256: state.manifestSha256,
    },
    argo: {
      namespace: stringAt(state.cicd, "argo.namespace"),
      projectName: stringAt(state.cicd, "argo.projectName"),
      applicationName: stringAt(state.cicd, "argo.applicationName"),
    },
    validation: {
      scenarioId: stringAt(state.cicd, "targetValidation.scenarioId"),
      maxSeconds: numberAt(state.cicd, "targetValidation.maxSeconds"),
      controlPlaneWaitMaxSeconds: cicdWaitWarningSeconds,
      quickVerifyMode: applyOnly ? "not-applicable" : "manual-validate",
      automaticSecondPath: false,
    },
    manifests: {
      objects: manifestObjectSummary(state.manifests),
      sha256: state.manifestSha256,
    },
    sourceMirrorSync,
    publish,
    flush,
    runtimeSecretsApply,
    publicExposureApply,
    argoApply,
    observed,
    targetValidation,
    elapsedMs,
    warnings: Array.from(new Set([
      ...sentinelCicdElapsedWarnings(elapsedMs, "sentinel control-plane confirm-wait", cicdWaitWarningSeconds),
      ...sentinelCicdElapsedWarnings(record(sourceMirrorSync).elapsedMs, "sentinel source mirror sync", cicdWaitWarningSeconds),
      ...sentinelCicdElapsedWarnings(record(publish).elapsedMs, "sentinel publish", cicdWaitWarningSeconds),
      ...sentinelCicdElapsedWarnings(record(flush).result === undefined ? null : record(record(flush).result).durationMs, "sentinel git-mirror flush", cicdWaitWarningSeconds),
      ...asyncGitMirrorFlushWarnings(flush),
      ...sourceMirrorAlreadyReadyWarnings(state, sourceMirrorSync),
      ...sentinelObservedWarnings(observed),
      ...targetValidationDeferredWarnings(state, applyOnly, cicdWaitWarningSeconds),
      ...(Array.isArray(record(targetValidation).warnings) ? record(targetValidation).warnings.map(text) : []),
      ...(targetValidationBlocked ? ["targetValidation is blocked; top-level STATUS only covers sentinel control-plane rollout. HWLAB business recovery remains pending; rerun quick verify after internal DB switch completes, without public fallback or a second execution path."] : []),
    ])),
    blocker,
    next: controlPlaneNext(state, options.action),
    valuesRedacted: true,
  };
  return rendered(ok, command, renderControlPlaneResult(result));
}

function renderAsyncSentinelJob(state: SentinelCicdState, domain: "image" | "control-plane", action: string, timeoutSeconds: number): RenderedCliResult {
  const args = domain === "image"
    ? ["web-probe", "sentinel", "image", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--sentinel", state.sentinelId, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)]
    : ["web-probe", "sentinel", "control-plane", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--sentinel", state.sentinelId, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
  const job = startJob(`hwlab_nodes_${state.spec.lane}_web_probe_sentinel_${safeJobSegment(state.sentinelId)}_${domain}_${action}`, ["bun", "scripts/cli.ts", ...args], `Run HWLAB ${state.spec.lane} web-probe sentinel ${state.sentinelId} ${domain} ${action} for node ${state.spec.nodeId}`);
  const command = `web-probe sentinel ${domain} ${action}`;
  const result = {
    ok: true,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: "async-job",
    mutation: true,
    reason: "confirmed sentinel publish/build can exceed the short interactive window; use job status for bounded progress.",
    job,
    next: {
      status: `bun scripts/cli.ts job status ${job.id} --tail-bytes 12000`,
      wait: ["bun", "scripts/cli.ts", ...args].join(" "),
    },
    valuesRedacted: true,
  };
  return rendered(true, command, renderAsyncJobResult(result));
}

function startSentinelGitMirrorFlushAsync(state: SentinelCicdState): Record<string, unknown> {
  const args = ["hwlab", "nodes", "git-mirror", "flush", "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait"];
  const job = startJob(
    `hwlab_nodes_${state.spec.lane}_web_probe_sentinel_${safeJobSegment(state.sentinelId)}_git_mirror_flush`,
    ["bun", "scripts/cli.ts", ...args],
    `Flush HWLAB ${state.spec.lane} git mirror after web-probe sentinel ${state.sentinelId} GitOps publish for node ${state.spec.nodeId}`,
  );
  return {
    ok: true,
    mode: "async-job",
    job,
    next: {
      status: `bun scripts/cli.ts job status ${job.id} --tail-bytes 12000`,
      wait: ["bun", "scripts/cli.ts", ...args].join(" "),
      gitMirrorStatus: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
    },
    valuesRedacted: true,
  };
}

function asyncGitMirrorFlushWarnings(flush: unknown): string[] {
  const item = record(flush);
  if (item.mode !== "async-job") return [];
  const next = record(item.next);
  return [`sentinel git-mirror flush is running asynchronously to keep control-plane confirm-wait under 120s; follow ${next.status ?? next.gitMirrorStatus ?? "the reported job status"} for GitHub mirror closeout.`];
}

function collectSentinelObservedStatus(state: SentinelCicdState, timeoutSeconds: number, expectation?: SentinelObservedExpectation, includeGitMirror = true): SentinelObservedStatus {
  const registry = probeImageRegistry(state, timeoutSeconds);
  const gitops = probeGitopsRuntimeManifest(state, timeoutSeconds);
  const effectiveExpectation = {
    gitopsRevision: expectation?.gitopsRevision ?? nonEmptyString(gitops.revision),
    runtimeImage: expectation?.runtimeImage ?? nonEmptyString(gitops.image) ?? expectedRuntimeImageFromRegistry(state, registry),
  };
  return {
    sourceMirror: probeSourceMirror(state, timeoutSeconds),
    registry,
    gitMirror: includeGitMirror
      ? runChildCli(["hwlab", "nodes", "git-mirror", "status", "--node", state.spec.nodeId, "--lane", state.spec.lane], timeoutSeconds)
      : { ok: true, skipped: true, reason: "deferred-to-async-flush", valuesRedacted: true },
    gitops,
    argo: probeArgoApplication(state, timeoutSeconds, effectiveExpectation.gitopsRevision),
    runtime: probeRuntimeObjects(state, timeoutSeconds, effectiveExpectation.runtimeImage),
  };
}

function waitForSentinelObservedStatus(state: SentinelCicdState, timeoutSeconds: number, expectation?: SentinelObservedExpectation, includeGitMirror = true): SentinelObservedStatus {
  const startedAt = Date.now();
  const timeoutMs = Math.max(1_000, Math.min(timeoutSeconds * 1000, controlPlaneWaitWarningSeconds(state) * 1000));
  let observed = collectSentinelObservedStatus(state, timeoutSeconds, expectation, includeGitMirror);
  while (!sentinelObservedReady(observed) && Date.now() - startedAt < timeoutMs) {
    runCommand(["sleep", "2"], repoRoot, { timeoutMs: 3_000 });
    observed = collectSentinelObservedStatus(state, timeoutSeconds, expectation, includeGitMirror);
  }
  return observed;
}

function sentinelObservedReady(value: Record<string, unknown> | SentinelObservedStatus): boolean {
  const observed = record(value);
  const gitMirror = record(observed.gitMirror);
  const gitMirrorReady = gitMirror.skipped === true || gitMirror.ok === true;
  return record(observed.sourceMirror).ok === true
    && record(record(observed.registry).probe).present === true
    && gitMirrorReady
    && record(observed.gitops).ok === true
    && record(observed.argo).ok === true
    && record(observed.runtime).ok === true;
}

function sentinelObservedWarnings(value: Record<string, unknown> | SentinelObservedStatus | null): string[] {
  const observed = record(value);
  const argo = record(observed.argo);
  return mergeWarnings(argo.warning);
}

function probeSourceMirror(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const repository = stringAt(state.cicd, "source.repository");
  const branch = stringAt(state.cicd, "source.branch");
  const expectedCommit = state.sourceHead.commit;
  const script = [
    "set +e",
    `repo_path=${shellQuote(`/cache/${repository}.git`)}`,
    `branch=${shellQuote(branch)}`,
    `expected=${shellQuote(expectedCommit ?? "")}`,
    "commit=$(kubectl -n " + shellQuote(namespace) + " exec deploy/git-mirror-http -- sh -lc \"git --git-dir=\\\"$repo_path\\\" rev-parse \\\"refs/heads/$branch\\\" 2>/dev/null\" 2>/dev/null)",
    "rc=$?",
    "object_rc=1",
    "if [ \"$rc\" -eq 0 ]; then",
    "  kubectl -n " + shellQuote(namespace) + " exec deploy/git-mirror-http -- sh -lc \"git --git-dir=\\\"$repo_path\\\" cat-file -e \\\"$commit^{commit}\\\" 2>/dev/null\" >/dev/null 2>&1",
    "  object_rc=$?",
    "fi",
    "node - \"$rc\" \"$object_rc\" \"$commit\" \"$expected\" \"$repo_path\" \"$branch\" <<'NODE'",
    "const [rc, objectRc, commit, expected, repoPath, branch] = process.argv.slice(2);",
    "const present = Number(rc) === 0 && /^[0-9a-f]{40}$/i.test(commit || '');",
    "const objectPresent = present && Number(objectRc) === 0;",
    "console.log(JSON.stringify({ ok: objectPresent && (!expected || commit === expected), mode: 'internal-git-mirror', present, objectPresent, commit: present ? commit : null, expectedCommit: expected || null, branch, repoPath, persistentMirrorPresent: objectPresent, readUrl: process.env.SOURCE_GIT_MIRROR_READ_URL || null, valuesRedacted: true }));",
    "NODE",
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", `export SOURCE_GIT_MIRROR_READ_URL=${shellQuote(stringAt(state.cicd, "source.gitMirrorReadUrl"))}\n${script}`], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  return { ok: result.exitCode === 0 && parseJsonObject(result.stdout)?.ok === true, probe: parseJsonObject(result.stdout), result: compactCommand(result) };
}

function probeArgoApplication(state: SentinelCicdState, timeoutSeconds: number, expectedRevision: string | null): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "argo.namespace");
  const applicationName = stringAt(state.cicd, "argo.applicationName");
  const jsonpath = "{.status.sync.status}{\"\\n\"}{.status.health.status}{\"\\n\"}{.status.sync.revision}{\"\\n\"}";
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "kubectl", "-n", namespace, "get", "application", applicationName, "-o", `jsonpath=${jsonpath}`], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const [syncStatusRaw, healthStatusRaw, revisionRaw] = result.stdout.trim().split(/\r?\n/u);
  const syncStatus = nonEmptyString(syncStatusRaw);
  const healthStatus = nonEmptyString(healthStatusRaw);
  const revision = nonEmptyString(revisionRaw);
  const revisionMatches = expectedRevision === null || revision === expectedRevision;
  const healthy = result.exitCode === 0 && syncStatus === "Synced" && healthStatus === "Healthy";
  return {
    ok: healthy,
    present: result.exitCode === 0,
    syncStatus,
    healthStatus,
    revision,
    expectedRevision,
    revisionMatches,
    revisionPolicy: "non-blocking-branch-head-drift",
    warning: healthy && !revisionMatches
      ? "Argo app is Synced/Healthy but status.sync.revision differs from current GitOps branch HEAD; in multi-sentinel GitOps this can happen when another sentinel path advances the branch. Runtime image/manifest checks remain authoritative for rollout readiness."
      : null,
    result: compactCommand(result),
  };
}

function probeGitopsRuntimeManifest(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const repository = stringAt(state.controlPlaneTarget, "source.repository");
  const branch = stringAt(state.cicd, "argo.targetRevision");
  const manifestPath = `${stringAt(state.cicd, "gitopsPath")}/web-probe-sentinel.yaml`;
  const repoPath = `/cache/${repository}.git`;
  const inner = [
    "set -eu",
    `git --git-dir=${shellQuote(repoPath)} rev-parse ${shellQuote(`refs/heads/${branch}`)}`,
    `git --git-dir=${shellQuote(repoPath)} show ${shellQuote(`refs/heads/${branch}:${manifestPath}`)}`,
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "kubectl", "-n", namespace, "exec", "deploy/git-mirror-http", "--", "sh", "-lc", inner], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const [revisionLine, ...manifestLines] = result.stdout.split(/\r?\n/u);
  const revision = /^[0-9a-f]{40}$/iu.test(revisionLine?.trim() ?? "") ? revisionLine.trim() : null;
  const manifest = manifestLines.join("\n");
  const image = nonEmptyString(manifest.match(/image:\s*([^,\s}\]]+)/u)?.[1]);
  const imageMatchesRepository = image !== null && image.startsWith(`${state.image.repository}@sha256:`);
  const compact = compactCommand(result);
  return {
    ok: result.exitCode === 0 && revision !== null && imageMatchesRepository,
    revision,
    branch,
    manifestPath,
    image,
    imageMatchesRepository,
    result: { ...compact, stdoutPreview: `${revision ?? "-"} ${image ?? "-"}` },
    valuesRedacted: true,
  };
}

function probeRuntimeObjects(state: SentinelCicdState, timeoutSeconds: number, expectedImage: string | null): Record<string, unknown> {
  const namespace = stringAt(state.runtime, "namespace");
  const deploymentName = stringAt(state.runtime, "deploymentName");
  const serviceName = stringAt(state.runtime, "serviceName");
  const pvcName = stringAt(state.runtime, "pvcName");
  const configMapName = `${deploymentName}-config`;
  const serviceAccountName = stringAt(state.runtime, "serviceAccountName");
  const script = [
    "set +e",
    `namespace=${shellQuote(namespace)}`,
    `deployment=${shellQuote(deploymentName)}`,
    `service=${shellQuote(serviceName)}`,
    `pvc=${shellQuote(pvcName)}`,
    `configmap=${shellQuote(configMapName)}`,
    `serviceaccount=${shellQuote(serviceAccountName)}`,
    "tmp=$(mktemp -d)",
    "kubectl -n \"$namespace\" get deploy \"$deployment\" -o json >\"$tmp/deploy.json\" 2>/dev/null; echo $? >\"$tmp/deploy.rc\"",
    "kubectl -n \"$namespace\" get svc \"$service\" -o json >\"$tmp/svc.json\" 2>/dev/null; echo $? >\"$tmp/svc.rc\"",
    "kubectl -n \"$namespace\" get pvc \"$pvc\" -o json >\"$tmp/pvc.json\" 2>/dev/null; echo $? >\"$tmp/pvc.rc\"",
    "kubectl -n \"$namespace\" get cm \"$configmap\" -o json >\"$tmp/cm.json\" 2>/dev/null; echo $? >\"$tmp/cm.rc\"",
    "kubectl -n \"$namespace\" get sa \"$serviceaccount\" -o json >\"$tmp/sa.json\" 2>/dev/null; echo $? >\"$tmp/sa.rc\"",
    `expected_image=${shellQuote(expectedImage ?? "")}`,
    "node - \"$tmp\" \"$expected_image\" <<'NODE'",
    "const fs = require('node:fs');",
    "const dir = process.argv[2];",
    "const expectedImage = process.argv[3] || null;",
    "function rc(name){ return Number(fs.readFileSync(`${dir}/${name}.rc`, 'utf8').trim()); }",
    "function json(name){ try { return JSON.parse(fs.readFileSync(`${dir}/${name}.json`, 'utf8')); } catch { return null; } }",
    "const dep = json('deploy');",
    "const deploymentPresent = rc('deploy') === 0;",
    "const desired = Number(dep?.spec?.replicas ?? 0);",
    "const ready = Number(dep?.status?.readyReplicas ?? 0);",
    "const updated = Number(dep?.status?.updatedReplicas ?? 0);",
    "const image = dep?.spec?.template?.spec?.containers?.[0]?.image ?? null;",
    "const imageMatches = expectedImage === null || image === expectedImage;",
    "const payload = {",
    "  deployment: { present: deploymentPresent, desiredReplicas: desired, readyReplicas: ready, updatedReplicas: updated, image, expectedImage, imageMatches },",
    "  service: { present: rc('svc') === 0 },",
    "  pvc: { present: rc('pvc') === 0, phase: json('pvc')?.status?.phase ?? null },",
    "  configMap: { present: rc('cm') === 0 },",
    "  serviceAccount: { present: rc('sa') === 0 },",
    "  valuesRedacted: true",
    "};",
    "payload.ok = payload.deployment.present && imageMatches && ready >= Math.max(1, desired) && updated >= Math.max(1, desired) && payload.service.present && payload.pvc.present && payload.pvc.phase === 'Bound' && payload.configMap.present && payload.serviceAccount.present;",
    "console.log(JSON.stringify(payload));",
    "NODE",
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const probe = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && probe?.ok === true, probe, result: compactCommand(result) };
}

function expectedRuntimeImageFromRegistry(state: SentinelCicdState, registry: Record<string, unknown>): string | null {
  const digest = nonEmptyString(record(record(registry).probe).digest);
  if (digest === null) return null;
  return `${state.image.repository}@${digest}`;
}

function runSentinelSourceMirrorSyncJob(state: SentinelCicdState, timeoutSeconds: number): SentinelRemoteJobResult {
  const prefix = `${stringAt(state.cicd, "builder.jobPrefix")}-source-sync`;
  const jobName = `${prefix}-${Date.now().toString(36)}`.replace(/[^a-z0-9-]/giu, "-").toLowerCase().slice(0, 63);
  const manifest = sentinelSourceMirrorSyncJobManifest(state, jobName);
  const namespace = stringAt(state.cicd, "builder.namespace");
  sentinelProgressEvent("sentinel.source-mirror.progress", { phase: "create-job", status: "submitting", jobName, sourceCommit: state.sourceHead.commit, node: state.spec.nodeId, lane: state.spec.lane });
  const created = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", createK8sJobScript(namespace, manifest)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  if (created.exitCode !== 0) {
    sentinelProgressEvent("sentinel.source-mirror.progress", { phase: "create-job", status: "failed", jobName, node: state.spec.nodeId, lane: state.spec.lane });
    return { ok: false, phase: "create-job", jobName, payload: { ok: false, status: "create-failed", valuesRedacted: true }, create: compactCommand(created), valuesRedacted: true };
  }
  const startedAt = Date.now();
  const timeoutMs = Math.max(5_000, Math.min(timeoutSeconds * 1000, controlPlaneWaitWarningSeconds(state) * 1000));
  const warningBudgetMs = Math.max(1, Math.trunc(controlPlaneWaitWarningSeconds(state))) * 1000;
  let slowWarningSent = false;
  let polls = 0;
  let lastProbe: Record<string, unknown> = {};
  while (Date.now() - startedAt < timeoutMs) {
    polls += 1;
    const probeCapture = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", probeK8sJobScript(namespace, jobName)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
    const probe = parseJsonObject(probeCapture.stdout) ?? {};
    lastProbe = { ...probe, capture: compactCommand(probeCapture) };
    const payload = sentinelPayloadFromLogs(String(probe.logsTail ?? ""));
    sentinelProgressEvent("sentinel.source-mirror.progress", {
      phase: "remote-job",
      status: probe.succeeded === true ? "succeeded" : probe.failed === true ? "failed" : "running",
      jobName,
      polls,
      elapsedMs: Date.now() - startedAt,
      pod: probe.pod ?? null,
      sourceCommit: state.sourceHead.commit,
      node: state.spec.nodeId,
      lane: state.spec.lane,
    });
    if (probe.succeeded === true) {
      const ok = payload.ok === true;
      return { ok, phase: "job-succeeded", jobName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "result-missing", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
    }
    if (probe.failed === true) {
      return { ok: false, phase: "job-failed", jobName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "failed", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
    }
    if (!slowWarningSent && Date.now() - startedAt > warningBudgetMs) {
      slowWarningSent = true;
      sentinelProgressEvent("sentinel.source-mirror.warning", { warning: `source mirror sync exceeded configured ${Math.round(warningBudgetMs / 1000)}s timing budget; non-blocking timing alert`, jobName, elapsedMs: Date.now() - startedAt, node: state.spec.nodeId, lane: state.spec.lane });
    }
    runCommand(["sleep", "2"], repoRoot, { timeoutMs: 3_000 });
  }
  return { ok: false, phase: "job-timeout", jobName, payload: { ok: false, status: "timeout", valuesRedacted: true }, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
}

function sentinelBlockedRemoteResult(phase: string, reason: string): SentinelRemoteJobResult {
  return {
    ok: false,
    phase,
    jobName: "-",
    payload: { ok: false, status: phase, reason, valuesRedacted: true },
    valuesRedacted: true,
  };
}

function sentinelSourceMirrorSyncJobManifest(state: SentinelCicdState, jobName: string): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const labels = {
    "app.kubernetes.io/name": "web-probe-sentinel-source-mirror",
    "app.kubernetes.io/part-of": "hwlab-web-probe-sentinel",
    "unidesk.ai/spec-ref": "PJ2026-01060508",
    "unidesk.ai/node": state.spec.nodeId,
    "unidesk.ai/lane": state.spec.lane,
  };
  return {
    apiVersion: "batch/v1",
    kind: "Job",
    metadata: { name: jobName, namespace, labels },
    spec: {
      backoffLimit: 0,
      activeDeadlineSeconds: numberAt(state.cicd, "builder.activeDeadlineSeconds"),
      ttlSecondsAfterFinished: numberAt(state.cicd, "builder.ttlSecondsAfterFinished"),
      template: {
        metadata: { labels },
        spec: {
          restartPolicy: "Never",
          volumes: [
            { name: "cache", hostPath: { path: stringAt(state.controlPlaneTarget, "gitMirror.cacheHostPath"), type: "DirectoryOrCreate" } },
            { name: "git-ssh", secret: { secretName: stringAt(state.cicd, "builder.gitSshSecretName"), defaultMode: 256 } },
          ],
          containers: [{
            name: "sync",
            image: state.image.baseImage,
            imagePullPolicy: "IfNotPresent",
            command: ["/bin/sh", "-ec", sentinelSourceMirrorSyncShell(state, jobName)],
            volumeMounts: [
              { name: "cache", mountPath: "/cache" },
              { name: "git-ssh", mountPath: "/git-ssh", readOnly: true },
            ],
          }],
        },
      },
    },
  };
}

function sentinelSourceMirrorSyncShell(state: SentinelCicdState, jobName: string): string {
  return [
    "set -eu",
    `job_name=${shellQuote(jobName)}`,
    `source_repository=${shellQuote(stringAt(state.cicd, "source.repository"))}`,
    `source_branch=${shellQuote(stringAt(state.cicd, "source.branch"))}`,
    `source_git_url=${shellQuote(stringAt(state.cicd, "source.gitSshUrl"))}`,
    `source_commit=${shellQuote(state.sourceHead.commit ?? "")}`,
    "started_ms=$(node -e 'console.log(Date.now())')",
    "emit_failed() { code=$?; if [ \"$code\" -ne 0 ]; then node - \"$code\" \"$job_name\" <<'NODE'\nconst [code, jobName] = process.argv.slice(2); console.log(JSON.stringify({ ok:false, status:'failed', exitCode:Number(code), jobName, valuesRedacted:true }));\nNODE\nfi; exit \"$code\"; }",
    "trap emit_failed EXIT",
    "test -n \"$source_commit\"",
    ...sentinelSourceMirrorSshSetupShellLines(state),
    "repo=\"/cache/${source_repository}.git\"",
    "mkdir -p \"$(dirname \"$repo\")\"",
    "if [ -d \"$repo/objects\" ] && [ -f \"$repo/HEAD\" ]; then",
    "  git --git-dir=\"$repo\" remote set-url origin \"$source_git_url\" || git --git-dir=\"$repo\" remote add origin \"$source_git_url\"",
    "else",
    "  rm -rf \"$repo\"",
    "  git init --bare \"$repo\"",
    "  git --git-dir=\"$repo\" remote add origin \"$source_git_url\"",
    "fi",
    "git --git-dir=\"$repo\" config uploadpack.allowReachableSHA1InWant true",
    "git --git-dir=\"$repo\" config uploadpack.allowAnySHA1InWant true",
    "git --git-dir=\"$repo\" config http.uploadpack true",
    "git --git-dir=\"$repo\" config http.receivepack true",
    "fetch_ok=0",
    "for attempt in 1 2 3; do",
    "  if timeout 240 git --git-dir=\"$repo\" fetch origin \"+refs/heads/$source_branch:refs/mirror-stage/heads/$source_branch\"; then fetch_ok=1; break; fi",
    "  code=$?",
    "  printf '%s\\n' \"sentinel source-mirror fetch attempt ${attempt}/3 failed exit=${code}; retrying\" >&2",
    "  sleep $((attempt * 5))",
    "done",
    "test \"$fetch_ok\" = 1",
    "mirror_commit=$(git --git-dir=\"$repo\" rev-parse --verify \"refs/mirror-stage/heads/$source_branch^{commit}\")",
    "test \"$mirror_commit\" = \"$source_commit\"",
    "git --git-dir=\"$repo\" update-ref \"refs/heads/$source_branch\" \"$mirror_commit\"",
    "git --git-dir=\"$repo\" update-server-info",
    "finished_ms=$(node -e 'console.log(Date.now())')",
    "node - \"$job_name\" \"$source_repository\" \"$source_branch\" \"$source_commit\" \"$mirror_commit\" \"$started_ms\" \"$finished_ms\" <<'NODE'",
    "const [jobName, repository, branch, sourceCommit, mirrorCommit, startedMs, finishedMs] = process.argv.slice(2);",
    "console.log(JSON.stringify({ ok:true, status:'succeeded', jobName, repository, branch, sourceCommit, mirrorCommit, elapsedMs:Number(finishedMs)-Number(startedMs), valuesRedacted:true }));",
    "NODE",
    "trap - EXIT",
  ].join("\n");
}

function sentinelSourceMirrorSshSetupShellLines(state: SentinelCicdState): string[] {
  const proxy = record(valueAtPath(state.controlPlaneNode, "egressProxy"));
  const serviceName = nonEmptyString(proxy.serviceName);
  const namespace = nonEmptyString(proxy.namespace);
  const port = typeof proxy.port === "number" && Number.isFinite(proxy.port) ? proxy.port : null;
  const noProxy = Array.isArray(proxy.noProxy) ? proxy.noProxy.filter((item): item is string => typeof item === "string" && item.length > 0).join(",") : "";
  const useProxy = serviceName !== null && namespace !== null && port !== null;
  if (!useProxy) {
    return [
      "mkdir -p /root/.ssh",
      "cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa",
      "chmod 0400 /root/.ssh/id_rsa",
      "printf '%s\\n' 'sentinel source-mirror-egress-proxy mode=direct transport=ssh source=yaml' >&2",
      "unset HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy",
      "export NO_PROXY='*'",
      "export no_proxy='*'",
      "cat > /tmp/sentinel-git-ssh-proxy.sh <<'SH_PROXY'",
      "#!/bin/sh",
      "exec ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts -o ConnectTimeout=30 -o ConnectionAttempts=2 -o ServerAliveInterval=10 -o ServerAliveCountMax=3 \"$@\"",
      "SH_PROXY",
      "chmod 0700 /tmp/sentinel-git-ssh-proxy.sh",
      "export GIT_SSH=/tmp/sentinel-git-ssh-proxy.sh",
      "unset GIT_SSH_COMMAND",
    ];
  }
  const proxyHost = `${serviceName}.${namespace}.svc.cluster.local`;
  const proxyUrl = `http://${proxyHost}:${port}`;
  const proxyCommand = `ProxyCommand=node /tmp/sentinel-github-proxy-connect.cjs ${proxyHost} ${port} %h %p`;
  return [
    "mkdir -p /root/.ssh",
    "cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa",
    "chmod 0400 /root/.ssh/id_rsa",
    `printf '%s\\n' ${shellQuote(`sentinel source-mirror-egress-proxy host=${proxyHost} port=${port} transport=ssh ssh=GIT_SSH-wrapper source=yaml`)} >&2`,
    `export HTTP_PROXY=${shellQuote(proxyUrl)}`,
    `export HTTPS_PROXY=${shellQuote(proxyUrl)}`,
    `export ALL_PROXY=${shellQuote(proxyUrl)}`,
    `export http_proxy=${shellQuote(proxyUrl)}`,
    `export https_proxy=${shellQuote(proxyUrl)}`,
    `export all_proxy=${shellQuote(proxyUrl)}`,
    `export NO_PROXY=${shellQuote(noProxy)}`,
    `export no_proxy=${shellQuote(noProxy)}`,
    "cat > /tmp/sentinel-github-proxy-connect.cjs <<'NODE_PROXY'",
    "#!/usr/bin/env node",
    "const net = require('node:net');",
    "const [proxyHost, proxyPortRaw, targetHost, targetPortRaw] = process.argv.slice(2);",
    "const proxyPort = Number.parseInt(proxyPortRaw || '', 10);",
    "const targetPort = Number.parseInt(targetPortRaw || '', 10);",
    "if (!proxyHost || !Number.isInteger(proxyPort) || !targetHost || !Number.isInteger(targetPort)) {",
    "  console.error('sentinel source-mirror proxy-connect: invalid ProxyCommand arguments');",
    "  process.exit(64);",
    "}",
    "let settled = false;",
    "let tunnelEstablished = false;",
    "function finish(code, message) {",
    "  if (settled) return;",
    "  settled = true;",
    "  if (message) console.error('sentinel source-mirror proxy-connect: ' + message);",
    "  process.exit(code);",
    "}",
    "const socket = net.createConnection({ host: proxyHost, port: proxyPort });",
    "let buffer = Buffer.alloc(0);",
    "socket.setTimeout(30000, () => { socket.destroy(); finish(65, 'timeout connecting via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); });",
    "socket.on('connect', () => socket.write('CONNECT ' + targetHost + ':' + targetPort + ' HTTP/1.1\\r\\nHost: ' + targetHost + ':' + targetPort + '\\r\\nProxy-Connection: Keep-Alive\\r\\n\\r\\n'));",
    "socket.on('error', (error) => finish(tunnelEstablished ? 69 : 66, (tunnelEstablished ? 'tunnel socket error: ' : 'tcp error connecting to proxy: ') + (error && error.message ? error.message : String(error))));",
    "socket.on('close', () => { if (!tunnelEstablished) finish(68, 'proxy closed before CONNECT completed via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); else finish(0); });",
    "function onData(chunk) {",
    "  buffer = Buffer.concat([buffer, chunk]);",
    "  const headerEnd = buffer.indexOf('\\r\\n\\r\\n');",
    "  if (headerEnd === -1 && buffer.length < 8192) return;",
    "  if (headerEnd === -1) { socket.destroy(); finish(68, 'proxy response header exceeded 8192 bytes before CONNECT status via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort); return; }",
    "  const head = buffer.slice(0, headerEnd + 4).toString('latin1');",
    "  const statusLine = head.split('\\r\\n', 1)[0] || '';",
    "  const statusCode = Number.parseInt(statusLine.split(' ')[1] || '', 10);",
    "  if (!statusLine.startsWith('HTTP/1.') || !Number.isInteger(statusCode) || statusCode < 200 || statusCode > 299) {",
    "    const safeStatus = statusLine.replace(/[^\\x20-\\x7e]/g, '?').slice(0, 160);",
    "    socket.destroy();",
    "    finish(67, 'proxy CONNECT failed via ' + proxyHost + ':' + proxyPort + ' to ' + targetHost + ':' + targetPort + ': ' + safeStatus);",
    "    return;",
    "  }",
    "  socket.off('data', onData);",
    "  socket.setTimeout(0);",
    "  tunnelEstablished = true;",
    "  const rest = buffer.slice(headerEnd + 4);",
    "  if (rest.length) process.stdout.write(rest);",
    "  process.stdin.on('error', () => {});",
    "  process.stdout.on('error', () => {});",
    "  process.stdin.pipe(socket);",
    "  socket.pipe(process.stdout);",
    "}",
    "socket.on('data', onData);",
    "NODE_PROXY",
    "chmod 0700 /tmp/sentinel-github-proxy-connect.cjs",
    "cat > /tmp/sentinel-git-ssh-proxy.sh <<'SH_PROXY'",
    "#!/bin/sh",
    `exec ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts -o ConnectTimeout=30 -o ConnectionAttempts=2 -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -o ${shellQuote(proxyCommand)} "$@"`,
    "SH_PROXY",
    "chmod 0700 /tmp/sentinel-git-ssh-proxy.sh",
    "export GIT_SSH=/tmp/sentinel-git-ssh-proxy.sh",
    "unset GIT_SSH_COMMAND",
  ];
}

function runSentinelPublishJob(state: SentinelCicdState, publishGitops: boolean, timeoutSeconds: number): SentinelRemoteJobResult {
  const jobName = `${stringAt(state.cicd, "builder.jobPrefix")}-${Date.now().toString(36)}`.replace(/[^a-z0-9-]/giu, "-").toLowerCase().slice(0, 63);
  const manifest = sentinelPublishJobManifest(state, jobName, publishGitops);
  const namespace = stringAt(state.cicd, "builder.namespace");
  sentinelProgressEvent("sentinel.publish.progress", { phase: "create-job", status: "submitting", jobName, publishGitops, sourceCommit: state.sourceHead.commit, node: state.spec.nodeId, lane: state.spec.lane });
  const created = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", createK8sJobScript(namespace, manifest)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  if (created.exitCode !== 0) {
    sentinelProgressEvent("sentinel.publish.progress", { phase: "create-job", status: "failed", jobName, publishGitops, node: state.spec.nodeId, lane: state.spec.lane });
    return { ok: false, phase: "create-job", jobName, payload: { ok: false, status: "create-failed", valuesRedacted: true }, create: compactCommand(created), valuesRedacted: true };
  }
  sentinelProgressEvent("sentinel.publish.progress", { phase: "create-job", status: "succeeded", jobName, publishGitops, node: state.spec.nodeId, lane: state.spec.lane });
  const startedAt = Date.now();
  const timeoutMs = Math.max(5_000, Math.min(timeoutSeconds * 1000, controlPlaneWaitWarningSeconds(state) * 1000));
  const warningBudgetMs = Math.max(1, Math.trunc(controlPlaneWaitWarningSeconds(state))) * 1000;
  let slowWarningSent = false;
  let polls = 0;
  let lastProbe: Record<string, unknown> = {};
  while (Date.now() - startedAt < timeoutMs) {
    polls += 1;
    const probeCapture = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", probeK8sJobScript(namespace, jobName)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
    const probe = parseJsonObject(probeCapture.stdout) ?? {};
    lastProbe = { ...probe, capture: compactCommand(probeCapture) };
    const payload = sentinelPayloadFromLogs(String(probe.logsTail ?? ""));
    sentinelProgressEvent("sentinel.publish.progress", {
      phase: "remote-job",
      status: probe.succeeded === true ? "succeeded" : probe.failed === true ? "failed" : "running",
      jobName,
      publishGitops,
      polls,
      elapsedMs: Date.now() - startedAt,
      pod: probe.pod ?? null,
      sourceCommit: state.sourceHead.commit,
      node: state.spec.nodeId,
      lane: state.spec.lane,
    });
    if (probe.succeeded === true) {
      const ok = payload.ok === true;
      return { ok, phase: "job-succeeded", jobName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "result-missing", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
    }
    if (probe.failed === true) {
      return { ok: false, phase: "job-failed", jobName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "failed", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
    }
    if (!slowWarningSent && Date.now() - startedAt > warningBudgetMs) {
      slowWarningSent = true;
      sentinelProgressEvent("sentinel.publish.warning", { warning: `remote publish job exceeded configured ${Math.round(warningBudgetMs / 1000)}s timing budget; non-blocking timing alert`, jobName, elapsedMs: Date.now() - startedAt, node: state.spec.nodeId, lane: state.spec.lane });
    }
    runCommand(["sleep", "2"], repoRoot, { timeoutMs: 3_000 });
  }
  return { ok: false, phase: "job-timeout", jobName, payload: { ok: false, status: "timeout", valuesRedacted: true }, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true };
}

function sentinelPublishJobManifest(state: SentinelCicdState, jobName: string, publishGitops: boolean): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const labels = {
    "app.kubernetes.io/name": "web-probe-sentinel-publish",
    "app.kubernetes.io/part-of": "hwlab-web-probe-sentinel",
    "unidesk.ai/spec-ref": "PJ2026-01060508",
    "unidesk.ai/node": state.spec.nodeId,
    "unidesk.ai/lane": state.spec.lane,
  };
  return {
    apiVersion: "batch/v1",
    kind: "Job",
    metadata: { name: jobName, namespace, labels },
    spec: {
      backoffLimit: 0,
      activeDeadlineSeconds: numberAt(state.cicd, "builder.activeDeadlineSeconds"),
      ttlSecondsAfterFinished: numberAt(state.cicd, "builder.ttlSecondsAfterFinished"),
      template: {
        metadata: { labels },
        spec: {
          restartPolicy: "Never",
          volumes: [
            { name: "cache", hostPath: { path: stringAt(state.controlPlaneTarget, "gitMirror.cacheHostPath"), type: "DirectoryOrCreate" } },
            { name: "git-ssh", secret: { secretName: stringAt(state.cicd, "builder.gitSshSecretName"), defaultMode: 256 } },
            { name: "docker-sock", hostPath: { path: stringAt(state.cicd, "builder.dockerSocketPath"), type: "Socket" } },
          ],
          containers: [{
            name: "publish",
            image: state.image.baseImage,
            imagePullPolicy: "IfNotPresent",
            command: ["/bin/sh", "-ec", sentinelPublishShell(state, jobName, publishGitops)],
            volumeMounts: [
              { name: "cache", mountPath: "/cache" },
              { name: "git-ssh", mountPath: "/git-ssh", readOnly: true },
              { name: "docker-sock", mountPath: stringAt(state.cicd, "builder.dockerSocketPath") },
            ],
          }],
        },
      },
    },
  };
}

function sentinelPublishShell(state: SentinelCicdState, jobName: string, publishGitops: boolean): string {
  const gitopsFiles = publishGitops ? sentinelGitopsFiles(state) : [];
  const filesB64 = Buffer.from(JSON.stringify(gitopsFiles.map((file) => ({
    path: file.path,
    contentBase64: Buffer.from(file.content, "utf8").toString("base64"),
  }))), "utf8").toString("base64");
  const checkoutPathsB64 = Buffer.from(JSON.stringify(arrayAt(state.cicd, "source.checkoutPaths").map((item) => {
    if (typeof item !== "string" || item.length === 0 || item.startsWith("/") || item.includes("..")) throw new Error("source.checkoutPaths must contain safe relative paths");
    return item;
  })), "utf8").toString("base64");
  const dockerfileB64 = Buffer.from(state.image.dockerfilePreview, "utf8").toString("base64");
  return [
    "set -eu",
    `job_name=${shellQuote(jobName)}`,
    `source_repository=${shellQuote(stringAt(state.cicd, "source.repository"))}`,
    `source_branch=${shellQuote(stringAt(state.cicd, "source.branch"))}`,
    `source_git_url=${shellQuote(stringAt(state.cicd, "source.gitMirrorReadUrl"))}`,
    `source_commit=${shellQuote(state.sourceHead.commit ?? "")}`,
    `checkout_paths_b64=${shellQuote(checkoutPathsB64)}`,
    `image_ref=${shellQuote(state.image.ref)}`,
    `image_repository=${shellQuote(state.image.repository)}`,
    `dockerfile_b64=${shellQuote(dockerfileB64)}`,
    `gitops_repository=${shellQuote(stringAt(state.controlPlaneTarget, "source.repository"))}`,
    `gitops_branch=${shellQuote(stringAt(state.cicd, "argo.targetRevision"))}`,
    `files_b64=${shellQuote(filesB64)}`,
    "started_ms=$(node -e 'console.log(Date.now())')",
    "emit_failed() { code=$?; if [ \"$code\" -ne 0 ]; then node - \"$code\" \"$job_name\" <<'NODE'\nconst [code, jobName] = process.argv.slice(2); console.log(JSON.stringify({ ok:false, status:'failed', exitCode:Number(code), jobName, valuesRedacted:true }));\nNODE\nfi; exit \"$code\"; }",
    "trap emit_failed EXIT",
    "mkdir -p /root/.ssh",
    "cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa",
    "chmod 0400 /root/.ssh/id_rsa",
    "export GIT_SSH_COMMAND='ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts -o ConnectTimeout=15 -o ServerAliveInterval=5 -o ServerAliveCountMax=1'",
    "worktree=\"/tmp/$job_name/source\"",
    "rm -rf \"/tmp/$job_name\"",
    "mkdir -p \"/tmp/$job_name\"",
    "git init \"$worktree\"",
    "cd \"$worktree\"",
    "git remote add origin \"$source_git_url\"",
    "git config core.sparseCheckout true",
    "git config remote.origin.promisor true",
    "git config remote.origin.partialclonefilter blob:none",
    "CHECKOUT_PATHS_B64=\"$checkout_paths_b64\" node <<'NODE'",
    "const fs = require('node:fs');",
    "const paths = JSON.parse(Buffer.from(process.env.CHECKOUT_PATHS_B64 || '', 'base64').toString('utf8'));",
    "fs.mkdirSync('.git/info', { recursive: true });",
    "fs.writeFileSync('.git/info/sparse-checkout', paths.map((item) => item.endsWith('/') ? item : item + (item.includes('.') ? '' : '/')).join('\\n') + '\\n');",
    "NODE",
    "git fetch --depth=1 --filter=blob:none origin \"+refs/heads/$source_branch:refs/remotes/origin/$source_branch\"",
    "git checkout --detach \"$source_commit\"",
    "mirror_commit=$(git rev-parse HEAD)",
    "test \"$mirror_commit\" = \"$source_commit\"",
    "DOCKERFILE_B64=\"$dockerfile_b64\" node <<'NODE'",
    "const fs = require('node:fs');",
    "fs.writeFileSync('Dockerfile.web-probe-sentinel', Buffer.from(process.env.DOCKERFILE_B64 || '', 'base64'));",
    "NODE",
    "docker build -f Dockerfile.web-probe-sentinel -t \"$image_ref\" .",
    "docker push \"$image_ref\" > /tmp/web-probe-sentinel-docker-push.log 2>&1",
    "cat /tmp/web-probe-sentinel-docker-push.log",
    "tag=${image_ref##*:}",
    "repo_no_tag=${image_ref%:*}",
    "registry_path=${repo_no_tag#127.0.0.1:5000/}",
    "digest=$(awk '/digest: sha256:/ {print $3; exit}' /tmp/web-probe-sentinel-docker-push.log)",
    "if [ -z \"$digest\" ]; then digest=$(curl -fsSI --max-time 10 \"http://127.0.0.1:5000/v2/$registry_path/manifests/$tag\" 2>/dev/null | awk 'BEGIN{IGNORECASE=1} /^docker-content-digest:/ {gsub(/\\r/,\"\",$2); print $2; exit}'); fi",
    "test -n \"$digest\"",
    "digest_ref=\"$repo_no_tag@$digest\"",
    "gitops_commit=''",
    "changed=false",
    "file_count=0",
    "if [ \"$files_b64\" != \"W10=\" ]; then",
    "  gitops_cache=\"/cache/${gitops_repository}.git\"",
    "  gitops_worktree=\"/tmp/$job_name/gitops\"",
    "  git clone --no-checkout \"$gitops_cache\" \"$gitops_worktree\"",
    "  cd \"$gitops_worktree\"",
    "  git fetch origin \"$gitops_branch\" || true",
    "  if git rev-parse --verify \"refs/remotes/origin/$gitops_branch^{commit}\" >/dev/null 2>&1; then git checkout -B \"$gitops_branch\" \"refs/remotes/origin/$gitops_branch\"; else git checkout --orphan \"$gitops_branch\"; git rm -rf . >/dev/null 2>&1 || true; fi",
    "  FILES_B64=\"$files_b64\" IMAGE_REF=\"$image_ref\" DIGEST_REF=\"$digest_ref\" node <<'NODE'",
    "const fs = require('node:fs');",
    "const path = require('node:path');",
    "const files = JSON.parse(Buffer.from(process.env.FILES_B64 || '', 'base64').toString('utf8'));",
    "for (const file of files) {",
    "  const target = path.resolve(process.cwd(), file.path);",
    "  if (!target.startsWith(process.cwd() + path.sep)) throw new Error(`refuse path outside workspace: ${file.path}`);",
    "  fs.mkdirSync(path.dirname(target), { recursive: true });",
    "  const text = Buffer.from(file.contentBase64, 'base64').toString('utf8').split(process.env.IMAGE_REF).join(process.env.DIGEST_REF);",
    "  fs.writeFileSync(target, text);",
    "}",
    "console.error(JSON.stringify({event:'web-probe-sentinel-gitops-files', fileCount: files.length, valuesRedacted:true}));",
    "NODE",
    "  git add .",
    "  file_count=$(git diff --cached --name-only | wc -l | tr -d ' ')",
    "  if git diff --quiet --cached; then changed=false; else changed=true; git -c user.email=web-probe-sentinel@unidesk.local -c user.name='UniDesk Web Probe Sentinel' commit -m \"deploy: render web-probe sentinel ${source_commit}\"; fi",
    "  git push origin \"HEAD:refs/heads/$gitops_branch\"",
    "  gitops_commit=$(git rev-parse HEAD)",
    "fi",
    "finished_ms=$(node -e 'console.log(Date.now())')",
    "node - \"$job_name\" \"$source_commit\" \"$mirror_commit\" \"$image_ref\" \"$digest_ref\" \"$gitops_commit\" \"$changed\" \"$file_count\" \"$started_ms\" \"$finished_ms\" <<'NODE'",
    "const [jobName, sourceCommit, mirrorCommit, imageRef, digestRef, gitopsCommit, changed, fileCount, startedMs, finishedMs] = process.argv.slice(2);",
    "console.log(JSON.stringify({ ok:true, status:'succeeded', jobName, sourceCommit, mirrorCommit, imageRef, digestRef, gitopsCommit: gitopsCommit || null, changed: changed === 'true', fileCount: Number(fileCount || 0), elapsedMs: Number(finishedMs) - Number(startedMs), valuesRedacted:true }));",
    "NODE",
    "trap - EXIT",
  ].join("\n");
}

function sentinelGitopsFiles(state: SentinelCicdState): readonly { path: string; content: string }[] {
  const runtimeManifests = state.manifests.filter((item) => item.kind !== "Application");
  return [{
    path: `${stringAt(state.cicd, "gitopsPath")}/web-probe-sentinel.yaml`,
    content: `${runtimeManifests.map((item) => Bun.YAML.stringify(item).trim()).join("\n---\n")}\n`,
  }];
}

function applySentinelArgoApplication(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const app = state.manifests.find((item) => item.kind === "Application");
  if (app === undefined) return { ok: false, reason: "application-manifest-missing", valuesRedacted: true };
  const yaml = `${Bun.YAML.stringify(app).trim()}\n`;
  const namespace = stringAt(state.cicd, "argo.namespace");
  const applicationName = stringAt(state.cicd, "argo.applicationName");
  const script = [
    "set -eu",
    "tmp=$(mktemp)",
    `cat >"$tmp" <<'YAML'\n${yaml}YAML`,
    "kubectl apply -f \"$tmp\"",
    `kubectl -n ${shellQuote(namespace)} annotate application ${shellQuote(applicationName)} argocd.argoproj.io/refresh=hard --overwrite`,
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  return { ok: result.exitCode === 0, result: compactCommand(result), valuesRedacted: true };
}

function createK8sJobScript(namespace: string, manifest: Record<string, unknown>): string {
  const yaml = `${Bun.YAML.stringify(manifest).trim()}\n`;
  return [
    "set -eu",
    `kubectl -n ${shellQuote(namespace)} delete job ${shellQuote(stringAt(manifest, "metadata.name"))} --ignore-not-found=true >/dev/null 2>&1 || true`,
    "tmp=$(mktemp)",
    `cat >"$tmp" <<'YAML'\n${yaml}YAML`,
    "kubectl apply -f \"$tmp\"",
  ].join("\n");
}

function probeK8sJobScript(namespace: string, jobName: string): string {
  return [
    "set +e",
    `namespace=${shellQuote(namespace)}`,
    `job=${shellQuote(jobName)}`,
    "succeeded=$(kubectl -n \"$namespace\" get job \"$job\" -o jsonpath='{.status.succeeded}' 2>/dev/null)",
    "failed=$(kubectl -n \"$namespace\" get job \"$job\" -o jsonpath='{.status.failed}' 2>/dev/null)",
    "pod=$(kubectl -n \"$namespace\" get pod -l job-name=\"$job\" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)",
    "logs_tail=''",
    "if [ -n \"$pod\" ]; then logs_tail=$(kubectl -n \"$namespace\" logs \"$pod\" --tail=120 2>/dev/null | tail -c 12000 | base64 | tr -d '\\n'); fi",
    "node - \"$succeeded\" \"$failed\" \"$pod\" \"$logs_tail\" <<'NODE'",
    "const [succeeded, failed, pod, logsB64] = process.argv.slice(2);",
    "console.log(JSON.stringify({ succeeded: Number(succeeded || 0) > 0, failed: Number(failed || 0) > 0, pod: pod || null, logsTail: Buffer.from(logsB64 || '', 'base64').toString('utf8'), valuesRedacted: true }));",
    "NODE",
  ].join("\n");
}

function sentinelPayloadFromLogs(logsTail: string): Record<string, unknown> {
  const lines = logsTail.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
  for (let index = lines.length - 1; index >= 0; index -= 1) {
    const line = lines[index];
    if (!line.startsWith("{") || !line.endsWith("}")) continue;
    const parsed = parseJsonObject(line);
    if (parsed !== null && (parsed.ok === true || parsed.ok === false)) return parsed;
  }
  return {};
}

function sentinelElapsedWarnings(value: unknown, subject = "sentinel confirmed operation", budgetSeconds = 120): string[] {
  const elapsedMs = typeof value === "number" && Number.isFinite(value) ? value : null;
  const budgetMs = Math.max(1, Math.trunc(budgetSeconds)) * 1000;
  if (elapsedMs === null || elapsedMs <= budgetMs) return [];
  return [`${subject} exceeded configured ${Math.round(budgetMs / 1000)}s timing budget (${Math.round(elapsedMs / 1000)}s); non-blocking timing alert, investigate wait-stage latency without treating timing alone as HWLAB business blockage.`];
}

function controlPlaneWaitWarningSeconds(state: SentinelCicdState): number {
  return numberAt(state.cicd, "confirmWait.maxSeconds");
}

function sentinelCicdElapsedWarnings(value: unknown, subject: string, budgetSeconds: number): string[] {
  const elapsedMs = typeof value === "number" && Number.isFinite(value) ? value : null;
  const budgetMs = Math.max(1, Math.trunc(budgetSeconds)) * 1000;
  if (elapsedMs === null || elapsedMs <= budgetMs) return [];
  return [`${subject} exceeded configured ${Math.round(budgetMs / 1000)}s CI/CD wait budget (${Math.round(elapsedMs / 1000)}s); optimize wait-stage latency before rerunning long confirm-wait operations.`];
}

function sourceMirrorAlreadyReadyWarnings(state: SentinelCicdState, sourceMirrorSync: unknown): string[] {
  const sync = record(sourceMirrorSync);
  if (sync.ok === true || state.sourceHead.ok !== true) return [];
  return [`sentinel source mirror sync did not complete, but internal git mirror already contains ${short(state.sourceHead.commit)}; continuing publish from the YAML-declared read URL and treating the sync failure as a non-blocking egress warning.`];
}

function sentinelSourceMirrorAlreadyPresentResult(state: SentinelCicdState, probe: unknown): Record<string, unknown> {
  return {
    ok: true,
    phase: "already-present",
    jobName: null,
    probe: record(probe),
    payload: {
      ok: true,
      status: "already-present",
      sourceCommit: state.sourceHead.commit,
      mirrorCommit: state.sourceHead.commit,
      valuesRedacted: true,
    },
    polls: 0,
    elapsedMs: 0,
    valuesRedacted: true,
  };
}

function targetValidationDeferredWarnings(state: SentinelCicdState, applyOnly: boolean, budgetSeconds: number): string[] {
  if (applyOnly) return [];
  const next = sentinelP5Next(state);
  return [`targetValidation quick verify is deferred from control-plane confirm-wait to keep CI/CD wait under ${Math.round(budgetSeconds)}s; run ${next.quickVerify}.`];
}

function targetValidationElapsedWarnings(value: unknown, subject: string, budgetSeconds: number): string[] {
  const elapsedMs = typeof value === "number" && Number.isFinite(value) ? value : null;
  const budgetMs = Math.max(1, Math.trunc(budgetSeconds)) * 1000;
  if (elapsedMs === null || elapsedMs <= budgetMs) return [];
  return [`${subject} exceeded configured ${Math.round(budgetMs / 1000)}s targetValidation budget (${Math.round(elapsedMs / 1000)}s); non-blocking timing alert, only Code Agent multi-round business failures should block acceptance.`];
}

function mergeWarnings(...items: readonly (readonly unknown[] | unknown)[]): string[] {
  const warnings: string[] = [];
  for (const item of items) {
    const values = Array.isArray(item) ? item : [item];
    for (const value of values) {
      if (value === undefined || value === null || value === "") continue;
      const warning = text(value).trim();
      if (warning.length > 0 && warning !== "-" && !warnings.includes(warning)) warnings.push(warning);
    }
  }
  return warnings;
}

function withWarnings(payload: Record<string, unknown>, warnings: readonly unknown[]): Record<string, unknown> {
  const merged = mergeWarnings(payload.warnings, warnings);
  return merged.length === 0 ? payload : { ...payload, warnings: merged, valuesRedacted: true };
}

function sentinelProgressEvent(event: string, payload: Record<string, unknown>): void {
  console.error(JSON.stringify({ event, at: new Date().toISOString(), ...payload, valuesRedacted: true }));
}

function confirmBlocked(action: string, state: SentinelCicdState): Record<string, unknown> {
  return {
    code: "sentinel-cicd-confirm-requires-remote-publish-job",
    action,
    reason: "P4 currently provides YAML-first render/status/trigger dry-run and refuses to report a deployment mutation before the remote publish job is wired to the node-local git mirror.",
    sourceGitMirrorReadUrl: stringAt(state.cicd, "source.gitMirrorReadUrl"),
    requiredNextImplementation: [
      "clone source from source.gitMirrorReadUrl at selected commit",
      "build and push digest-pinned image on the selected node",
      "publish manifests to the HWLAB gitops branch/path through git-mirror",
      "flush/recheck git-mirror and let Argo reconcile the Application",
    ],
    valuesRedacted: true,
  };
}

function controlPlaneNext(state: SentinelCicdState, action: WebProbeSentinelControlPlaneAction): Record<string, string> {
  const node = state.spec.nodeId;
  const lane = state.spec.lane;
  const suffix = sentinelCliSuffix(state);
  return {
    plan: `bun scripts/cli.ts web-probe sentinel control-plane plan --node ${node} --lane ${lane}${suffix} --dry-run`,
    status: `bun scripts/cli.ts web-probe sentinel control-plane status --node ${node} --lane ${lane}${suffix}`,
    image: `bun scripts/cli.ts web-probe sentinel image status --node ${node} --lane ${lane}${suffix}`,
    triggerCurrent: `bun scripts/cli.ts web-probe sentinel control-plane trigger-current --node ${node} --lane ${lane}${suffix} --dry-run`,
    validate: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane}${suffix}`,
    quickVerify: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane}${suffix} --quick-verify --confirm --wait`,
    issue: "https://github.com/pikasTech/unidesk/issues/889",
    currentAction: action,
  };
}

function runSentinelMaintenance(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "maintenance" }>): RenderedCliResult {
  const command = `web-probe sentinel maintenance ${options.action}`;
  const serviceHealth = callSentinelService(state, "GET", "/api/health", null, options.timeoutSeconds);
  if (options.action === "status") {
    const maintenance = callSentinelService(state, "GET", "/api/maintenance", null, options.timeoutSeconds);
    const result = {
      ok: serviceHealth.ok && maintenance.ok,
      command,
      node: state.spec.nodeId,
      lane: state.spec.lane,
      serviceHealth,
      maintenance,
      next: sentinelP5Next(state),
      valuesRedacted: true,
    };
    return rendered(result.ok, command, renderMaintenanceResult(result));
  }
  if (!options.confirm) {
    const result = {
      ok: serviceHealth.ok,
      command,
      node: state.spec.nodeId,
      lane: state.spec.lane,
      mode: "dry-run",
      serviceHealth,
      mutation: false,
      planned: {
        action: options.action,
        releaseId: options.releaseId,
        reason: options.reason,
        quickVerify: options.action === "stop" && options.quickVerify,
      },
      next: sentinelP5Next(state),
      valuesRedacted: true,
    };
    return rendered(result.ok, command, renderMaintenanceResult(result));
  }
  if (!options.wait) return renderAsyncP5Job(state, ["maintenance", options.action], options.timeoutSeconds, options.releaseId, options.reason, options.quickVerify);
  if (!serviceHealth.ok) {
    const result = {
      ok: false,
      command,
      node: state.spec.nodeId,
      lane: state.spec.lane,
      mode: "confirm-wait",
      mutation: false,
      serviceHealth,
      blocker: serviceUnavailableBlocker(state),
      next: sentinelP5Next(state),
      valuesRedacted: true,
    };
    return rendered(false, command, renderMaintenanceResult(result));
  }
  const body = { releaseId: options.releaseId, reason: options.reason, source: "unidesk-cli", valuesRedacted: true };
  const mutation = callSentinelService(state, "POST", `/api/maintenance/${options.action}`, body, options.timeoutSeconds);
  const quickVerify = options.action === "stop" && options.quickVerify && mutation.ok
    ? runSentinelQuickVerify(state, "maintenance-stop", options.timeoutSeconds)
    : null;
  const result = {
    ok: mutation.ok && (quickVerify === null || quickVerify.ok === true),
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: "confirm-wait",
    mutation: true,
    serviceHealth,
    maintenance: mutation,
    quickVerify,
    blocker: mutation.ok ? null : serviceUnavailableBlocker(state),
    next: sentinelP5Next(state),
    valuesRedacted: true,
  };
  return rendered(result.ok, command, renderMaintenanceResult(result));
}

function runSentinelValidate(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "validate" }>): RenderedCliResult {
  const command = "web-probe sentinel validate";
  const startedAt = Date.now();
  const initialHealth = callSentinelService(state, "GET", "/api/health", null, options.timeoutSeconds);
  let quickVerify: Record<string, unknown> | null = null;
  if (options.quickVerify) {
    if (!options.confirm) {
      const result = {
        ok: initialHealth.ok,
        command,
        node: state.spec.nodeId,
        lane: state.spec.lane,
        mode: "dry-run",
        serviceHealth: initialHealth,
        planned: { quickVerify: true, waitRequired: true },
        next: sentinelP5Next(state),
        valuesRedacted: true,
      };
      return rendered(result.ok, command, renderValidateResult(result));
    }
    if (!options.wait) return renderAsyncP5Job(state, ["validate"], options.timeoutSeconds, null, "manual-validate-quick-verify", true);
    if (!initialHealth.ok) {
      const result = {
        ok: false,
        command,
        node: state.spec.nodeId,
        lane: state.spec.lane,
        mode: "confirm-wait",
        serviceHealth: initialHealth,
        blocker: serviceUnavailableBlocker(state),
        next: sentinelP5Next(state),
        valuesRedacted: true,
      };
      return rendered(false, command, renderValidateResult(result));
    }
    quickVerify = runSentinelQuickVerify(state, "manual-validate", options.timeoutSeconds);
  }
  const serviceProbeTimeoutSeconds = Math.min(options.timeoutSeconds, options.quickVerify ? 30 : 20);
  const health = callSentinelService(state, "GET", "/api/health", null, serviceProbeTimeoutSeconds);
  const metrics = callSentinelService(state, "GET", "/metrics", null, serviceProbeTimeoutSeconds);
  const report = callSentinelService(state, "GET", "/api/report?view=summary", null, serviceProbeTimeoutSeconds);
  const metricsOk = metrics.ok && metricNames(record(metrics).bodyTextPreview).includes("web_probe_sentinel_health");
  const publicHealth = health.ok ? null : probePublicSentinelService(state, "/api/health", serviceProbeTimeoutSeconds);
  const publicMetrics = metricsOk ? null : probePublicSentinelService(state, "/metrics", serviceProbeTimeoutSeconds);
  const publicReport = report.ok ? null : probePublicSentinelService(state, "/api/report?view=summary", serviceProbeTimeoutSeconds);
  const effectiveHealth = health.ok ? health : record(publicHealth).ok === true ? record(publicHealth) : health;
  const effectiveMetrics = metricsOk ? metrics : record(publicMetrics).ok === true ? record(publicMetrics) : metrics;
  const effectiveReport = report.ok ? report : record(publicReport).ok === true ? record(publicReport) : report;
  const publicExposure = probeSentinelPublicExposure(state, options.timeoutSeconds);
  const publicDashboard = probeSentinelPublicDashboard(state, options.timeoutSeconds);
  if (quickVerify !== null) {
    quickVerify = withWarnings(quickVerify, targetValidationElapsedWarnings(Date.now() - startedAt, "sentinel validate quick verify confirm-wait", Math.min(options.timeoutSeconds, numberAt(state.cicd, "targetValidation.maxSeconds"))));
  }
  const publicFallbackWarnings = [
    ...(!health.ok && record(publicHealth).ok === true ? ["internal sentinel health probe failed through D601:k3s, but public /api/health passed; treating provider transport as a non-blocking validation warning."] : []),
    ...(!metricsOk && record(publicMetrics).ok === true ? ["internal sentinel metrics probe failed through D601:k3s, but public /metrics exposed web_probe_sentinel_health; treating provider transport as a non-blocking validation warning."] : []),
    ...(!report.ok && record(publicReport).ok === true ? ["internal sentinel report probe failed through D601:k3s, but public /api/report returned the indexed report; treating provider transport as a non-blocking validation warning."] : []),
  ];
  const effectiveMetricsOk = effectiveMetrics.ok && metricNames(record(effectiveMetrics).bodyTextPreview).includes("web_probe_sentinel_health");
  const ok = effectiveHealth.ok
    && record(effectiveHealth.bodyJson).ok === true
    && effectiveMetricsOk
    && effectiveReport.ok
    && publicExposure.ok === true
    && publicDashboard.ok === true
    && (quickVerify === null || quickVerify.ok === true);
  const result = {
    ok,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: options.quickVerify ? "confirm-wait" : "status",
    serviceHealth: effectiveHealth,
    metrics: effectiveMetrics,
    report: effectiveReport,
    internalServiceHealth: health,
    internalMetrics: metrics,
    internalReport: report,
    publicServiceHealth: publicHealth,
    publicMetrics,
    publicReport,
    publicExposure,
    publicDashboard,
    quickVerify,
    warnings: mergeWarnings(publicFallbackWarnings, quickVerify === null ? [] : Array.isArray(quickVerify.warnings) ? quickVerify.warnings : []),
    blocker: ok ? null : validationBlocker(effectiveHealth, effectiveMetrics, effectiveReport, publicExposure, publicDashboard, quickVerify),
    next: sentinelP5Next(state),
    valuesRedacted: true,
  };
  return rendered(ok, command, renderValidateResult(result));
}

function runSentinelReport(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "report" }>): RenderedCliResult {
  const command = `web-probe sentinel report ${options.latest ? "--latest " : ""}--view ${options.view}`;
  const query = new URLSearchParams({ view: options.view });
  if (options.runId !== null) query.set("run", options.runId);
  if (options.traceId !== null) query.set("traceId", options.traceId);
  if (options.sampleSeq !== null) query.set("sampleSeq", String(options.sampleSeq));
  const report = callSentinelService(state, "GET", `/api/report?${query.toString()}`, null, options.timeoutSeconds);
  const body = record(report.bodyJson);
  const renderedText = typeof body.renderedText === "string" ? body.renderedText : renderReportResult({ command, node: state.spec.nodeId, lane: state.spec.lane, report, valuesRedacted: true });
  const rawPayload = Object.keys(body).length > 0 ? body : report;
  return rendered(report.ok && body.ok !== false, command, options.raw ? JSON.stringify(rawPayload, null, 2) : renderedText);
}

function runSentinelDashboard(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "dashboard" }>): RenderedCliResult {
  const command = `web-probe sentinel dashboard ${options.action}`;
  const result = probeSentinelDashboardBrowser(state, options);
  return rendered(result.ok === true, command, options.raw ? JSON.stringify(result, null, 2) : renderDashboardResult(result));
}

function probeSentinelDashboardBrowser(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "dashboard" }>): Record<string, unknown> {
  const publicBaseUrl = stringAt(state.publicExposure, "publicBaseUrl").replace(/\/$/u, "");
  const [widthRaw, heightRaw] = options.viewport.split("x");
  const screenshotName = options.action === "screenshot" ? dashboardScreenshotName(options, state) : "";
  const script = [
    "set -eu",
    `export UNIDESK_SENTINEL_DASHBOARD_URL=${shellQuote(`${publicBaseUrl}/`)}`,
    `export UNIDESK_SENTINEL_DASHBOARD_SCREENSHOT="$UNIDESK_WEB_PROBE_ARTIFACT_REMOTE_DIR"/${shellQuote(screenshotName)}`,
    `export UNIDESK_SENTINEL_DASHBOARD_CAPTURE=${shellQuote(options.action === "screenshot" ? "1" : "0")}`,
    `export UNIDESK_SENTINEL_DASHBOARD_WIDTH=${shellQuote(widthRaw ?? "1440")}`,
    `export UNIDESK_SENTINEL_DASHBOARD_HEIGHT=${shellQuote(heightRaw ?? "900")}`,
    `export UNIDESK_SENTINEL_DASHBOARD_TIMEOUT_MS=${shellQuote(String(options.timeoutMs))}`,
    `export UNIDESK_SENTINEL_DASHBOARD_FULL_PAGE=${shellQuote(options.fullPage ? "1" : "0")}`,
    `export UNIDESK_SENTINEL_DASHBOARD_EXPECTED_SENTINEL_ID=${shellQuote(state.sentinelId)}`,
    `export UNIDESK_SENTINEL_DASHBOARD_EXPECTED_ROUTE_PREFIX=${shellQuote(stringAtNullable(state.publicExposure, "routePrefix") ?? "/")}`,
    `export UNIDESK_SENTINEL_DASHBOARD_PLAYWRIGHT_MODULE=${shellQuote(`${state.spec.workspace}/node_modules/playwright/index.mjs`)}`,
    "export PLAYWRIGHT_BROWSERS_PATH=0",
    "if command -v chromium >/dev/null 2>&1; then",
    "  export UNIDESK_SENTINEL_DASHBOARD_EXECUTABLE_PATH=$(command -v chromium)",
    "elif command -v chromium-browser >/dev/null 2>&1; then",
    "  export UNIDESK_SENTINEL_DASHBOARD_EXECUTABLE_PATH=$(command -v chromium-browser)",
    "elif command -v google-chrome >/dev/null 2>&1; then",
    "  export UNIDESK_SENTINEL_DASHBOARD_EXECUTABLE_PATH=$(command -v google-chrome)",
    "else",
    "  export UNIDESK_SENTINEL_DASHBOARD_EXECUTABLE_PATH=",
    "fi",
    "cat > \"$UNIDESK_WEB_PROBE_ARTIFACT_REMOTE_DIR/web-probe-sentinel-dashboard.mjs\" <<'WEB_PROBE_SENTINEL_DASHBOARD_JS'",
    sentinelDashboardBrowserModule(),
    "WEB_PROBE_SENTINEL_DASHBOARD_JS",
    "bun \"$UNIDESK_WEB_PROBE_ARTIFACT_REMOTE_DIR/web-probe-sentinel-dashboard.mjs\"",
  ].join("\n");
  const route = `${state.spec.nodeId}:${state.spec.workspace}`;
  const job = runWebProbeRemoteArtifactJob({
    route,
    localDir: options.localDir,
    waitTimeoutMs: options.waitTimeoutMs,
    commandTimeoutMs: options.commandTimeoutSeconds * 1000,
    inactivityTimeoutMs: 30000,
    runIdPrefix: `web-probe-sentinel-dashboard-${state.spec.nodeId.toLowerCase()}-${state.spec.lane}-${state.sentinelId}`,
    stdoutTailBytes: 32768,
  }, script);
  const result = job.result;
  const transport = record(job.transport);
  const remote = record(transport.remote);
  const page = parseDashboardBrowserPayload(typeof remote.stdoutTail === "string" ? remote.stdoutTail : "");
  const artifacts = Array.isArray(transport.artifacts) ? transport.artifacts.map(record).map(compactDashboardArtifact) : [];
  const screenshot = artifacts.find((artifact) => typeof artifact.localPath === "string" && String(artifact.localPath).endsWith(".png")) ?? null;
  const browserOk = page?.ok === true;
  const screenshotOk = options.action === "verify" || screenshot !== null && screenshot.verified === true;
  const ok = result.exitCode === 0 && transport.ok === true && browserOk && screenshotOk;
  return {
    ok,
    status: ok ? "pass" : "blocked",
    command: `web-probe sentinel dashboard ${options.action}`,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    sentinelId: state.sentinelId,
    publicUrl: `${publicBaseUrl}/`,
    route,
    viewport: options.viewport,
    page,
    screenshot,
    artifacts,
    artifactCount: artifacts.length,
    remote: {
      exitCode: remote.exitCode ?? null,
      remoteDir: remote.remoteDir ?? null,
      stdoutTail: ok ? "" : typeof remote.stdoutTail === "string" ? remote.stdoutTail.slice(-1200) : "",
      stderrTail: ok ? "" : typeof remote.stderrTail === "string" ? remote.stderrTail.slice(-1200) : "",
    },
    transport: {
      ok: transport.ok ?? null,
      runId: transport.runId ?? null,
      artifactCount: transport.artifactCount ?? null,
      expectedArtifactCount: transport.expectedArtifactCount ?? null,
      downloadFailure: transport.downloadFailure ?? null,
    },
    result: compactCommand(result),
    degradedReason: ok ? null : dashboardDegradedReason(result, transport, page, screenshotOk),
    valuesRedacted: true,
  };
}

function sentinelDashboardBrowserModule(): string {
  return String.raw`import { pathToFileURL } from "node:url";

const playwrightModulePath = process.env.UNIDESK_SENTINEL_DASHBOARD_PLAYWRIGHT_MODULE || "";
const playwrightModuleSpecifier = playwrightModulePath ? pathToFileURL(playwrightModulePath).href : "playwright";
const { chromium } = await import(playwrightModuleSpecifier);

const url = process.env.UNIDESK_SENTINEL_DASHBOARD_URL;
const screenshotPath = process.env.UNIDESK_SENTINEL_DASHBOARD_SCREENSHOT || "";
const captureScreenshot = process.env.UNIDESK_SENTINEL_DASHBOARD_CAPTURE === "1";
const width = Number(process.env.UNIDESK_SENTINEL_DASHBOARD_WIDTH || 1440);
const height = Number(process.env.UNIDESK_SENTINEL_DASHBOARD_HEIGHT || 900);
const timeout = Number(process.env.UNIDESK_SENTINEL_DASHBOARD_TIMEOUT_MS || 30000);
const fullPage = process.env.UNIDESK_SENTINEL_DASHBOARD_FULL_PAGE !== "0";
const executablePath = process.env.UNIDESK_SENTINEL_DASHBOARD_EXECUTABLE_PATH || "";
const expectedSentinelId = process.env.UNIDESK_SENTINEL_DASHBOARD_EXPECTED_SENTINEL_ID || "";
const expectedRoutePrefix = process.env.UNIDESK_SENTINEL_DASHBOARD_EXPECTED_ROUTE_PREFIX || "/";

if (!url) throw new Error("missing dashboard URL");

const consoleMessages = [];
const pageErrors = [];
const requestFailures = [];
const browser = await chromium.launch({
  headless: true,
  args: ["--disable-gpu", "--no-sandbox"],
  ...(executablePath ? { executablePath } : {}),
});
const context = await browser.newContext({ viewport: { width, height }, deviceScaleFactor: 1, isMobile: width <= 560 });
const page = await context.newPage();
page.on("console", (message) => {
  if (consoleMessages.length < 30) consoleMessages.push({ type: message.type(), text: message.text().slice(0, 300) });
});
page.on("pageerror", (error) => {
  if (pageErrors.length < 20) pageErrors.push({ message: String(error?.message || error).slice(0, 500) });
});
page.on("requestfailed", (request) => {
  if (requestFailures.length < 20) requestFailures.push({ url: request.url().slice(0, 240), method: request.method(), failure: request.failure()?.errorText || null });
});

let httpStatus = null;
let navigationError = null;
let navigationAttempts = 0;
const maxNavigationAttempts = 3;
const perAttemptTimeout = Math.max(5000, Math.floor(timeout / maxNavigationAttempts));
for (let attempt = 1; attempt <= maxNavigationAttempts; attempt += 1) {
  navigationAttempts = attempt;
  navigationError = null;
  try {
    const response = await page.goto(url, { timeout: perAttemptTimeout, waitUntil: "domcontentloaded" });
    httpStatus = response?.status() ?? null;
    await page.waitForLoadState("networkidle", { timeout: Math.min(10000, perAttemptTimeout) }).catch(() => {});
    await page.waitForFunction(() => {
      const root = document.querySelector("#monitor-web-root");
      if (!root) return false;
      const ready = root.getAttribute("data-monitor-ready") === "true";
      const error = document.querySelector("#monitor-web-error");
      const runs = document.querySelectorAll(".run-list .run-row").length;
      const trend = document.querySelector("[data-monitor-trend-curve]");
      return ready && (error || runs > 0 || trend);
    }, null, { timeout: Math.min(15000, perAttemptTimeout) }).catch(() => {});
    await page.waitForTimeout(500);
    const appReady = await page.evaluate(() => document.querySelector("#monitor-web-root")?.getAttribute("data-monitor-ready") === "true").catch(() => false);
    if (appReady || attempt === maxNavigationAttempts) break;
  } catch (error) {
    navigationError = String(error?.message || error).slice(0, 500);
    if (attempt === maxNavigationAttempts) break;
  }
  await page.waitForTimeout(750 * attempt);
}

await page.evaluate(() => {
  const detailPane = document.querySelector(".workspace-grid .pane-detail");
  if (detailPane instanceof HTMLElement) detailPane.scrollTop = Math.min(96, Math.max(0, detailPane.scrollHeight - detailPane.clientHeight));
}).catch(() => {});
await page.waitForTimeout(150);

const trendHoverPoint = await page.evaluate(() => {
  const target = document.querySelector(".trend-dot-hit .trend-dot-red") || document.querySelector(".trend-dot-hit .trend-dot-warning");
  if (!(target instanceof SVGElement)) return null;
  const rect = target.getBoundingClientRect();
  if (rect.width <= 0 || rect.height <= 0) return null;
  return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
}).catch(() => null);
if (trendHoverPoint) {
  await page.mouse.move(trendHoverPoint.x, trendHoverPoint.y);
  await page.waitForTimeout(250);
}

if (captureScreenshot && screenshotPath) {
  await page.screenshot({ path: screenshotPath, fullPage, animations: "disabled" }).catch((error) => {
    pageErrors.push({ message: "screenshot failed: " + String(error?.message || error).slice(0, 400) });
  });
}

const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId }) => {
  const visible = (element) => Boolean(element && !element.hidden);
  const text = (selector) => String(document.querySelector(selector)?.textContent || "").replace(/\s+/g, " ").trim();
  const numberValue = (value) => Number.isFinite(Number(value)) ? Number(value) : 0;
  const errorSampleCount = (counts) => numberValue(counts?.red) + numberValue(counts?.critical) + numberValue(counts?.error);
  const warningSampleCount = (counts) => numberValue(counts?.warning) + numberValue(counts?.warn) + numberValue(counts?.amber);
  const allSampleCount = (counts) => Object.values(counts || {}).reduce((sum, value) => sum + numberValue(value), 0);
  const root = document.querySelector("#monitor-web-root");
  const shell = document.querySelector("[data-monitor-shell='true']");
  const error = document.querySelector("#monitor-web-error");
  const trend = document.querySelector("[data-monitor-trend-curve]");
  const trendTooltip = document.querySelector("[data-monitor-trend-tooltip='true']");
  const timeline = document.querySelector("[data-monitor-timeline='true']");
  const workspace = document.querySelector("[data-monitor-independent-scroll='true']");
  const checksPanel = document.querySelector("[data-monitor-checks='true']");
  const panes = Array.from(document.querySelectorAll(".workspace-grid .pane, [data-monitor-checks='true']"));
  const detailPane = document.querySelector(".workspace-grid .pane-detail");
  const detailHeader = detailPane?.querySelector(".pane-header");
  const checksHeader = checksPanel?.querySelector(".pane-header");
  const internalTextPattern = /水合|投影|Trace|trace|Shell|API|DOM|Console|console|Runner|runner|JSONL|steer|facts|分页|HTTP|http|requestfailed|pageerror|Final Response|Code Agent|web-probe|observe|analyzer|终态/u;
  const cards = Array.from(document.querySelectorAll(".finding-card")).slice(0, 8).map((card) => ({
    code: String(card.querySelector(".check-code")?.textContent || "").trim(),
    title: String(card.querySelector("strong")?.textContent || "").trim(),
    body: String(card.textContent || "").replace(/\s+/g, " ").trim().slice(0, 180),
  }));
  const badCardTitles = cards.filter((card) => internalTextPattern.test(card.title));
  const badCardBodies = cards.filter((card) => internalTextPattern.test(card.body));
  const legendTexts = Array.from(document.querySelectorAll(".trend-legend .legend-item")).map((item) => String(item.textContent || "").replace(/\s+/g, " ").trim());
  const legendNumber = (label) => {
    const row = legendTexts.find((item) => item.includes(label)) || "";
    const match = /(\d+)/u.exec(row);
    return match ? Number(match[1]) : null;
  };
  const chartCounts = {
    error: legendNumber("错误"),
    warning: legendNumber("警告"),
    total: legendNumber("错误+警告合计"),
  };
  chartCounts.ok = typeof chartCounts.error === "number" && typeof chartCounts.warning === "number" && typeof chartCounts.total === "number"
    ? chartCounts.total === chartCounts.error + chartCounts.warning
    : false;
  const apiUrl = (path) => {
    const basePath = root?.getAttribute("data-base-path") || expectedRoutePrefix || "";
    const prefix = basePath.replace(/\/+$/u, "");
    return (prefix + (path.startsWith("/") ? path : "/" + path)) || path;
  };
  const runsPayload = await fetch(apiUrl("/api/runs?limit=30&sort=updated"), { cache: "no-store" }).then((item) => item.json()).catch(() => null);
  const overviewPayload = await fetch(apiUrl("/api/overview"), { cache: "no-store" }).then((item) => item.json()).catch(() => null);
  const runs = Array.isArray(runsPayload?.runs) ? runsPayload.runs : Array.isArray(runsPayload?.items) ? runsPayload.items : [];
  const latestRun = runs[0] || null;
  const latestCounts = latestRun && latestRun.severityCounts && typeof latestRun.severityCounts === "object" && !Array.isArray(latestRun.severityCounts)
    ? latestRun.severityCounts
    : {};
  const latestRunCounts = {
    runId: latestRun?.id || latestRun?.runId || null,
    typeCount: numberValue(latestRun?.findingTypeCount ?? latestRun?.findingCount ?? latestRun?.finding_count),
    error: errorSampleCount(latestCounts),
    warning: warningSampleCount(latestCounts),
    total: errorSampleCount(latestCounts) + warningSampleCount(latestCounts),
    allSamples: allSampleCount(latestCounts),
  };
  const latestDetailPayload = latestRunCounts.runId
    ? await fetch(apiUrl("/api/runs/" + encodeURIComponent(latestRunCounts.runId)), { cache: "no-store" }).then((item) => item.json()).catch(() => null)
    : null;
  const latestDetailRows = Array.isArray(latestDetailPayload?.findings) ? latestDetailPayload.findings : [];
  const rowSeverity = (row) => {
    const raw = String(row?.maxSeverity || row?.checkLevel || row?.severity || row?.level || "").toLowerCase();
    if (["red", "critical", "error", "blocked", "failed"].includes(raw)) return "red";
    if (["warning", "warn", "amber"].includes(raw)) return "warning";
    if (["info", "notice"].includes(raw)) return "info";
    return "healthy";
  };
  const sampleCount = (row) => Number.isFinite(Number(row?.count)) ? Number(row.count) : 1;
  const summarizeRows = (rows) => {
    const errorRows = rows.filter((row) => rowSeverity(row) === "red");
    const warningRows = rows.filter((row) => rowSeverity(row) === "warning");
    const sum = (items) => items.reduce((total, row) => total + sampleCount(row), 0);
    return {
      typeCount: rows.length,
      alertTypeCount: errorRows.length + warningRows.length,
      errorSamples: sum(errorRows),
      warningSamples: sum(warningRows),
      alertSamples: sum(errorRows) + sum(warningRows),
    };
  };
  const latestDetailSummary = summarizeRows(latestDetailRows);
  const workspaceRect = workspace?.getBoundingClientRect();
  const checksRect = checksPanel?.getBoundingClientRect();
  const heightSummary = (rect) => {
    const viewportHeight = window.innerHeight || 1;
    const heightPx = rect ? Math.round(rect.height) : null;
    const ratio = rect ? Math.round((rect.height / viewportHeight) * 1000) / 1000 : null;
    return {
      present: Boolean(rect),
      heightPx,
      ratio,
      targetPx: Math.round(viewportHeight * 0.8),
      bounded80: Boolean(rect && rect.height <= viewportHeight * 0.82 + 1),
      near80: Boolean(rect && rect.height >= viewportHeight * 0.74 && rect.height <= viewportHeight * 0.82 + 1),
    };
  };
  const workspacePaneHeights = Array.from(document.querySelectorAll(".workspace-grid > .pane")).map((pane) => heightSummary(pane.getBoundingClientRect()));
  const stackedWorkspace = window.matchMedia("(max-width: 1120px)").matches;
  const panelHeights = {
    viewportHeight: window.innerHeight,
    stackedWorkspace,
    workspace: heightSummary(workspaceRect),
    checks: heightSummary(checksRect),
    workspacePanes: workspacePaneHeights,
    workspacePaneBounded: workspacePaneHeights.length >= 2 && workspacePaneHeights.every((item) => item.bounded80 === true),
    workspaceOk: false,
    checksOk: false,
  };
  panelHeights.workspaceOk = stackedWorkspace
    ? panelHeights.workspacePaneBounded === true
    : panelHeights.workspace.near80 === true && panelHeights.workspacePaneBounded === true;
  panelHeights.checksOk = panelHeights.checks.near80 === true;
  const checkScope = {
    present: Boolean(checksPanel),
    scope: checksPanel?.getAttribute("data-check-scope") || null,
    runId: checksPanel?.getAttribute("data-check-run-id") || null,
    typeCount: numberValue(checksPanel?.getAttribute("data-check-type-count")),
    alertTypeCount: numberValue(checksPanel?.getAttribute("data-check-alert-type-count")),
    errorSamples: numberValue(checksPanel?.getAttribute("data-check-error-samples")),
    warningSamples: numberValue(checksPanel?.getAttribute("data-check-warning-samples")),
    alertSamples: numberValue(checksPanel?.getAttribute("data-check-alert-samples")),
    visibleCardCount: document.querySelectorAll(".finding-list .finding-card").length,
    visibleAlertSamples: numberValue(checksPanel?.getAttribute("data-visible-check-alert-samples")),
    matchesLatestRun: false,
    matchesRunDetail: false,
    belowWorkspace: Boolean(workspaceRect && checksRect && checksRect.top >= workspaceRect.bottom - 2),
    fullWidth: Boolean(workspaceRect && checksRect && checksRect.width >= workspaceRect.width - 2),
  };
  checkScope.matchesLatestRun = checkScope.present === true
    && checkScope.scope === "run"
    && checkScope.runId === latestRunCounts.runId
    && checkScope.errorSamples === latestRunCounts.error
    && checkScope.warningSamples === latestRunCounts.warning
    && checkScope.alertSamples === latestRunCounts.total;
  checkScope.matchesRunDetail = checkScope.present === true
    && checkScope.typeCount === latestDetailSummary.typeCount
    && checkScope.alertTypeCount === latestDetailSummary.alertTypeCount
    && checkScope.errorSamples === latestDetailSummary.errorSamples
    && checkScope.warningSamples === latestDetailSummary.warningSamples
    && checkScope.alertSamples === latestDetailSummary.alertSamples
    && checkScope.visibleCardCount === latestDetailSummary.alertTypeCount
    && checkScope.visibleAlertSamples === latestDetailSummary.alertSamples;
  const overviewCounts = overviewPayload?.severityCounts && typeof overviewPayload.severityCounts === "object" && !Array.isArray(overviewPayload.severityCounts)
    ? overviewPayload.severityCounts
    : {};
  const overviewSamples = {
    error: errorSampleCount(overviewCounts),
    warning: warningSampleCount(overviewCounts),
    total: errorSampleCount(overviewCounts) + warningSampleCount(overviewCounts),
    allSamples: allSampleCount(overviewCounts),
  };
  chartCounts.matchesLatestRun = chartCounts.ok === true
    && chartCounts.error === latestRunCounts.error
    && chartCounts.warning === latestRunCounts.warning
    && chartCounts.total === latestRunCounts.total;
  const datasetSentinelId = root?.getAttribute("data-sentinel-id") || "";
  const finalPath = new URL(window.location.href).pathname.replace(/\/+$/u, "") || "/";
  const expectedPath = expectedRoutePrefix.replace(/\/+$/u, "") || "/";
  const routePrefixMatches = expectedPath === "/" ? finalPath === "/" : finalPath === expectedPath || finalPath.startsWith(expectedPath + "/");
  const sentinelBoundary = {
    expectedSentinelId,
    expectedRoutePrefix,
    datasetSentinelId,
    overviewSentinelId: overviewPayload?.sentinelId || null,
    runsSentinelId: runsPayload?.sentinelId || null,
    finalPath,
    routePrefixMatches,
    datasetMatches: expectedSentinelId ? datasetSentinelId === expectedSentinelId : true,
    overviewMatches: expectedSentinelId ? overviewPayload?.sentinelId === expectedSentinelId : true,
    runsPayloadMatches: expectedSentinelId ? runsPayload?.sentinelId === expectedSentinelId : true,
    runRowsMatch: expectedSentinelId ? runs.every((run) => (run?.sentinelId || expectedSentinelId) === expectedSentinelId) : true,
  };
  const statusText = text(".status-strip");
  const doc = document.documentElement;
  const body = document.body;
  const viewport = { width: window.innerWidth, height: window.innerHeight };
  const documentSize = {
    width: Math.max(doc.scrollWidth, body?.scrollWidth || 0),
    height: Math.max(doc.scrollHeight, body?.scrollHeight || 0),
  };
  const overflow = [];
  let overflowCount = 0;
  for (const element of Array.from(document.querySelectorAll("body *"))) {
    const rect = element.getBoundingClientRect();
    const overflowRight = rect.right - viewport.width;
    const overflowLeft = -rect.left;
    if (overflowRight > 1 || overflowLeft > 1) {
      overflowCount += 1;
      if (overflow.length < 5) {
        overflow.push({
          tag: element.tagName.toLowerCase(),
          className: String(element.className || "").slice(0, 40),
          x: Math.round(rect.x),
          y: Math.round(rect.y),
          width: Math.round(rect.width),
          height: Math.round(rect.height),
          overflowRight: Math.max(0, Math.round(overflowRight)),
          overflowLeft: Math.max(0, Math.round(overflowLeft)),
        });
      }
    }
  }
  return {
    shell: Boolean(root && shell),
    ready: root?.getAttribute("data-monitor-ready") === "true",
    dataset: root ? {
      node: root.getAttribute("data-node"),
      lane: root.getAttribute("data-lane"),
      sentinelId: datasetSentinelId,
      basePath: root.getAttribute("data-base-path"),
      contractVersion: root.getAttribute("data-contract-version"),
    } : {},
    sentinelBoundary,
    title: document.title,
    finalUrl: window.location.href,
    statusText: text(".topbar .pill"),
    subtitle: text(".subtitle"),
    summaryText: text(".status-strip"),
    runRows: document.querySelectorAll(".run-list .run-row").length,
    findingItems: document.querySelectorAll(".finding-list .finding-card").length,
    badCardTitleCount: badCardTitles.length,
    badCardBodyCount: badCardBodies.length,
    trendCurve: Boolean(trend),
    trendDotCount: document.querySelectorAll(".trend-dot-hit").length,
    trendTooltip: tooltipSummary(trendTooltip),
    trendPanelText: text("#trend-heading"),
    chartCounts,
    latestRunCounts,
    latestDetailSummary,
    checkScope,
    overviewSamples,
    panelHeights,
    scopeLabels: {
      latestPointLegend: legendTexts.some((item) => item.includes("最新点")),
      historicalSamples: legendTexts.some((item) => item.includes("历史样本累计")) || statusText.includes("历史错误样本"),
    },
    timelineItems: document.querySelectorAll(".timeline-list .timeline-item").length,
    timelineVisible: Boolean(timeline),
    errorVisible: visible(error),
    errorText: visible(error) ? text("#monitor-web-error").slice(0, 500) : "",
    scrollModel: {
      workspace: Boolean(workspace),
      paneCount: panes.length,
      independentScroll: panes.length >= 3 && panes.every((pane) => {
        const style = window.getComputedStyle(pane);
        return style.overflowY === "auto" || style.overflowY === "scroll";
      }),
      stickyHeader: stickyHeaderSummary(detailPane, detailHeader),
      stickyChecksHeader: stickyHeaderSummary(checksPanel, checksHeader),
    },
    layout: {
      viewport,
      documentSize,
      horizontalOverflow: documentSize.width > viewport.width + 1,
      overflowCount,
      overflow: overflow.slice(0, 2),
    },
  };

  function tooltipSummary(element) {
    const body = String(element?.textContent || "").replace(/\s+/g, " ").trim();
    return {
      visible: Boolean(element && body.length > 0),
      text: body.slice(0, 240),
      hasValues: /错误\s+\d+/u.test(body) && /警告\s+\d+/u.test(body) && /合计\s+\d+/u.test(body),
      hasTime: /UTC/u.test(body) || /\d{4}-\d{2}-\d{2}/u.test(body),
    };
  }

  function stickyHeaderSummary(pane, header) {
    if (!(pane instanceof HTMLElement) || !(header instanceof HTMLElement)) {
      return { present: false, coversScroll: false, backgroundOpaque: false, detailScrollTop: null };
    }
    const rect = header.getBoundingClientRect();
    const style = window.getComputedStyle(header);
    const sampleX = Math.round(rect.left + Math.min(32, Math.max(2, rect.width / 2)));
    const sampleY = Math.round(rect.top + Math.min(12, Math.max(2, rect.height / 2)));
    const topElement = document.elementFromPoint(sampleX, sampleY);
    return {
      present: true,
      detailScrollTop: pane.scrollTop,
      headerTop: Math.round(rect.top),
      headerBottom: Math.round(rect.bottom),
      zIndex: style.zIndex,
      backgroundColor: style.backgroundColor,
      coversScroll: Boolean(topElement && header.contains(topElement)),
      backgroundOpaque: backgroundIsOpaque(style.backgroundColor),
      topElementClass: String(topElement?.className || "").slice(0, 80),
    };
  }

  function backgroundIsOpaque(value) {
    const rgba = /rgba?\(([^)]+)\)/u.exec(value);
    if (rgba === null) return value.length > 0 && value !== "transparent";
    const parts = rgba[1].split(",").map((part) => part.trim());
    if (parts.length < 4) return true;
    return Number(parts[3]) >= 0.99;
  }
}, { expectedRoutePrefix, expectedSentinelId });

const runFilterProbe = await page.evaluate(async ({ expectedRoutePrefix }) => {
  const numberValue = (value) => Number.isFinite(Number(value)) ? Number(value) : 0;
  const root = document.querySelector("#monitor-web-root");
  const apiUrl = (path) => {
    const basePath = root?.getAttribute("data-base-path") || expectedRoutePrefix || "";
    const prefix = basePath.replace(/\/+$/u, "");
    return (prefix + (path.startsWith("/") ? path : "/" + path)) || path;
  };
  const rowSeverity = (row) => {
    const raw = String(row?.maxSeverity || row?.checkLevel || row?.severity || row?.level || "").toLowerCase();
    if (["red", "critical", "error", "blocked", "failed"].includes(raw)) return "red";
    if (["warning", "warn", "amber"].includes(raw)) return "warning";
    if (["info", "notice"].includes(raw)) return "info";
    return "healthy";
  };
  const sampleCount = (row) => Number.isFinite(Number(row?.count)) ? Number(row.count) : 1;
  const summarizeRows = (rows) => {
    const errorRows = rows.filter((row) => rowSeverity(row) === "red");
    const warningRows = rows.filter((row) => rowSeverity(row) === "warning");
    const sum = (items) => items.reduce((total, row) => total + sampleCount(row), 0);
    return {
      typeCount: rows.length,
      alertTypeCount: errorRows.length + warningRows.length,
      errorSamples: sum(errorRows),
      warningSamples: sum(warningRows),
      alertSamples: sum(errorRows) + sum(warningRows),
    };
  };
  const panelCounts = () => {
    const panel = document.querySelector("[data-monitor-checks='true']");
    return {
      present: Boolean(panel),
      runId: panel?.getAttribute("data-check-run-id") || null,
      typeCount: numberValue(panel?.getAttribute("data-check-type-count")),
      alertTypeCount: numberValue(panel?.getAttribute("data-check-alert-type-count")),
      errorSamples: numberValue(panel?.getAttribute("data-check-error-samples")),
      warningSamples: numberValue(panel?.getAttribute("data-check-warning-samples")),
      alertSamples: numberValue(panel?.getAttribute("data-check-alert-samples")),
      visibleCardCount: document.querySelectorAll(".finding-list .finding-card").length,
      visibleAlertSamples: numberValue(panel?.getAttribute("data-visible-check-alert-samples")),
    };
  };
  const waitForRun = async (runId) => {
    for (let index = 0; index < 30; index += 1) {
      const current = panelCounts();
      if (current.runId === runId && current.present === true) return true;
      await new Promise((resolve) => window.setTimeout(resolve, 100));
    }
    return false;
  };
  const select = document.querySelector("select[aria-label='选择运行记录']");
  if (!(select instanceof HTMLSelectElement)) {
    return { ok: false, requestedRunId: null, reason: "run-select-missing" };
  }
  const options = Array.from(select.options).filter((option) => option.value);
  const requestedOption = options[Math.min(2, Math.max(0, options.length - 1))] || options[0] || null;
  const requestedRunId = requestedOption?.value || null;
  const fallbackOption = requestedOption || null;
  const targetRunId = fallbackOption?.value || requestedRunId;
  if (!targetRunId) return { ok: false, requestedRunId, reason: "run-option-missing" };
  select.value = targetRunId;
  select.dispatchEvent(new Event("change", { bubbles: true }));
  const panelReady = await waitForRun(targetRunId);
  const detailPayload = await fetch(apiUrl("/api/runs/" + encodeURIComponent(targetRunId)), { cache: "no-store" }).then((item) => item.json()).catch(() => null);
  const detailRows = Array.isArray(detailPayload?.findings) ? detailPayload.findings : [];
  const expected = summarizeRows(detailRows);
  const observed = panelCounts();
  const matchesRunDetail = observed.runId === targetRunId
    && observed.typeCount === expected.typeCount
    && observed.alertTypeCount === expected.alertTypeCount
    && observed.errorSamples === expected.errorSamples
    && observed.warningSamples === expected.warningSamples
    && observed.alertSamples === expected.alertSamples
    && observed.visibleCardCount === expected.alertTypeCount
    && observed.visibleAlertSamples === expected.alertSamples;
  return {
    ok: panelReady === true && matchesRunDetail === true,
    requestedRunId,
    requestedOptionPresent: Boolean(requestedOption),
    targetRunId,
    panelReady,
    observed,
    expected,
    matchesRunDetail,
  };
}, { expectedRoutePrefix });
dom.runFilterProbe = runFilterProbe;

const consoleErrors = consoleMessages.filter((item) => item.type === "error");
const ok = !navigationError
  && httpStatus !== null
  && httpStatus >= 200
  && httpStatus < 300
  && dom.shell === true
  && dom.ready === true
  && dom.sentinelBoundary?.datasetMatches === true
  && dom.sentinelBoundary?.overviewMatches === true
  && dom.sentinelBoundary?.runsPayloadMatches === true
  && dom.sentinelBoundary?.runRowsMatch === true
  && dom.sentinelBoundary?.routePrefixMatches === true
  && dom.errorVisible !== true
  && dom.trendCurve === true
  && dom.chartCounts?.ok === true
  && dom.chartCounts?.matchesLatestRun === true
  && dom.checkScope?.matchesLatestRun === true
  && dom.checkScope?.matchesRunDetail === true
  && dom.runFilterProbe?.ok === true
  && dom.runFilterProbe?.requestedOptionPresent === true
  && dom.checkScope?.belowWorkspace === true
  && dom.checkScope?.fullWidth === true
  && dom.scopeLabels?.latestPointLegend === true
  && dom.scopeLabels?.historicalSamples === true
  && (dom.trendDotCount === 0 || (dom.trendTooltip?.visible === true && dom.trendTooltip?.hasValues === true && dom.trendTooltip?.hasTime === true))
  && dom.badCardTitleCount === 0
  && dom.badCardBodyCount === 0
  && dom.timelineVisible === true
  && dom.scrollModel?.independentScroll === true
  && dom.scrollModel?.stickyHeader?.present === true
  && dom.scrollModel?.stickyHeader?.coversScroll === true
  && dom.scrollModel?.stickyHeader?.backgroundOpaque === true
  && dom.scrollModel?.stickyChecksHeader?.present === true
  && dom.scrollModel?.stickyChecksHeader?.backgroundOpaque === true
  && dom.panelHeights?.workspaceOk === true
  && dom.panelHeights?.checksOk === true
  && dom.layout?.horizontalOverflow !== true
  && pageErrors.length === 0;

console.log("__WEB_PROBE_SENTINEL_DASHBOARD_JSON__" + JSON.stringify({
  ok,
  url,
  httpStatus,
  navigationError,
  navigationAttempts,
  executablePath: executablePath || null,
  viewport: { width, height },
  screenshotPath: captureScreenshot ? screenshotPath : null,
  dom,
  consoleCount: consoleMessages.length,
  consoleErrorCount: consoleErrors.length,
  pageErrorCount: pageErrors.length,
  requestFailureCount: requestFailures.length,
  consoleMessages: consoleMessages.slice(0, 8),
  pageErrors: pageErrors.slice(0, 8),
  requestFailures: requestFailures.slice(0, 8),
  valuesRedacted: true,
}));

await context.close().catch(() => {});
await browser.close().catch(() => {});
`;
}

function parseDashboardBrowserPayload(textValue: string): Record<string, unknown> | null {
  const marker = "__WEB_PROBE_SENTINEL_DASHBOARD_JSON__";
  const index = textValue.lastIndexOf(marker);
  if (index < 0) return null;
  try {
    return record(JSON.parse(textValue.slice(index + marker.length).trim()));
  } catch {
    return null;
  }
}

function dashboardScreenshotName(options: Extract<WebProbeSentinelOptions, { kind: "dashboard" }>, state: SentinelCicdState): string {
  const raw = options.name ?? `sentinel-dashboard-${state.spec.nodeId.toLowerCase()}-${state.spec.lane}-${state.sentinelId}.png`;
  const safe = raw.replace(/[^A-Za-z0-9._-]+/gu, "-").slice(0, 120);
  return safe.endsWith(".png") ? safe : `${safe}.png`;
}

function compactDashboardArtifact(artifact: Record<string, unknown>): Record<string, unknown> {
  const transfer = record(artifact.transfer);
  return {
    remotePath: typeof artifact.remotePath === "string" ? artifact.remotePath : null,
    localPath: typeof artifact.localPath === "string" ? artifact.localPath : null,
    bytes: Number.isFinite(Number(artifact.bytes)) ? Number(artifact.bytes) : null,
    sha256: typeof artifact.sha256 === "string" ? artifact.sha256 : null,
    verified: artifact.verified === true,
    transfer: Object.keys(transfer).length === 0 ? null : {
      strategy: transfer.strategy ?? null,
      transport: transfer.transport ?? null,
      chunks: transfer.chunks ?? null,
      elapsedMs: transfer.elapsedMs ?? null,
      throughputBytesPerSecond: transfer.throughputBytesPerSecond ?? null,
    },
  };
}

function dashboardDegradedReason(result: CommandResult, transport: Record<string, unknown>, page: Record<string, unknown> | null, screenshotOk: boolean): string {
  if (result.timedOut) return "sentinel-dashboard-command-timeout";
  if (transport.ok !== true) return "sentinel-dashboard-transport-failed";
  if (page === null) return "sentinel-dashboard-browser-output-missing";
  if (page.ok !== true) return "sentinel-dashboard-render-failed";
  if (!screenshotOk) return "sentinel-dashboard-screenshot-missing";
  return "sentinel-dashboard-unknown";
}

function renderAsyncP5Job(state: SentinelCicdState, subcommand: readonly string[], timeoutSeconds: number, releaseId: string | null, reason: string | null, quickVerify: boolean): RenderedCliResult {
  const args = ["web-probe", "sentinel", ...subcommand, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--sentinel", state.sentinelId, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
  if (releaseId !== null) args.push("--release-id", releaseId);
  if (reason !== null) args.push("--reason", reason);
  if (quickVerify) args.push("--quick-verify");
  const job = startJob(`hwlab_nodes_${state.spec.lane}_web_probe_sentinel_${safeJobSegment(state.sentinelId)}_${subcommand.join("_")}`, ["bun", "scripts/cli.ts", ...args], `Run HWLAB ${state.spec.lane} web-probe sentinel ${state.sentinelId} ${subcommand.join(" ")} for node ${state.spec.nodeId}`);
  const command = `web-probe sentinel ${subcommand.join(" ")}`;
  return rendered(true, command, renderAsyncJobResult({
    ok: true,
    command,
    node: state.spec.nodeId,
    lane: state.spec.lane,
    mode: "async-job",
    mutation: true,
    job,
    next: {
      status: `bun scripts/cli.ts job status ${job.id} --tail-bytes 12000`,
      wait: ["bun", "scripts/cli.ts", ...args].join(" "),
    },
    valuesRedacted: true,
  }));
}

function printQuickVerifyProgress(state: SentinelCicdState, runId: string | null, phase: string, status: string, extra: Record<string, unknown> = {}): void {
  const compactExtra = Object.fromEntries(Object.entries(extra).map(([key, value]) => {
    if (typeof value === "string") return [key, short(value)];
    if (Array.isArray(value)) return [key, value.slice(0, 8)];
    return [key, value];
  }));
  process.stdout.write(`${JSON.stringify({
    event: "sentinel.quick-verify.progress",
    at: new Date().toISOString(),
    node: state.spec.nodeId,
    lane: state.spec.lane,
    sentinelId: state.sentinelId,
    runId,
    ...compactExtra,
    phase,
    status,
    valuesRedacted: true,
  })}\n`);
}

function runSentinelQuickVerify(state: SentinelCicdState, reason: string, timeoutSeconds: number): Record<string, unknown> {
  const startedAt = Date.now();
  const elapsedMs = () => Date.now() - startedAt;
  const scenarioId = stringAt(state.cicd, "targetValidation.scenarioId");
  const maxSeconds = numberAt(state.cicd, "targetValidation.maxSeconds");
  const scenario = findScenario(state, scenarioId);
  if (scenario === null) return { ok: false, status: "blocked", reason: "scenario-not-found", scenarioId, valuesRedacted: true };
  const commandSequence = arrayAt(scenario, "commandSequence").map(record);
  const needsPromptSet = commandSequence.some((item) => stringAt(item, "type") === "sendPrompt");
  const prompts = needsPromptSet
    ? readPromptSetForScenario(scenario)
    : { ok: true as const, prompts: [], summary: { source: "not-required", promptCount: 0, valuesRedacted: true } };
  if (!prompts.ok) return { ok: false, status: "blocked", reason: "prompt-source-unavailable", promptSource: prompts, valuesRedacted: true };
  const accountEnv = quickVerifyAccountEnv(state);
  if (!accountEnv.ok) {
    const findings = [{
      id: "quick-verify-account-secret-missing",
      severity: "red",
      count: arrayAt(accountEnv.summary, "missing").length || 1,
      summary: "quick verify could not materialize YAML-declared web account credentials for the observer runner.",
      missing: arrayAt(accountEnv.summary, "missing"),
      valuesRedacted: true,
    }];
    return recordQuickVerify(state, {
      ok: false,
      runId: `sentinel-run-${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`,
      scenarioId,
      reason,
      status: "blocked",
      observerId: null,
      elapsedMs: 0,
      steps: [{ phase: "quick-verify-account-env", ok: false, result: accountEnv.summary }],
      failure: "quick-verify-account-secret-missing",
      findingCount: findings.length,
      findings,
      promptSource: prompts.summary,
      accountEnv: accountEnv.summary,
      views: {
        summary: { renderedText: renderQuickVerifySummary({ scenarioId, artifactSummary: { ok: false, findings, findingCount: findings.length }, steps: [], publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
        "auth-session-switch-summary": { renderedText: renderAuthSessionSwitchQuickVerifySummary({ scenarioId, steps: [], findings, accountEnv: accountEnv.summary, publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
      },
      warnings: [],
      valuesRedacted: true,
    });
  }
  const sampleIntervalMs = numberAt(scenario, "sampleIntervalMs");
  const warningBudgetSeconds = maxSeconds;
  const hardBudgetSeconds = Math.min(timeoutSeconds, Math.max(maxSeconds, numberAt(scenario, "maxRunSeconds")));
  const elapsedWarnings = () => targetValidationElapsedWarnings(elapsedMs(), "quick verify confirm-wait", warningBudgetSeconds);
  const deadline = Date.now() + hardBudgetSeconds * 1000;
  const runId = `sentinel-run-${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`;
  printQuickVerifyProgress(state, runId, "start", "running", { scenarioId, reason, warningBudgetSeconds, hardBudgetSeconds, timeoutSeconds });
  const steps: Record<string, unknown>[] = [];
  const startArgs = [
    "web-probe", "observe", "start",
    "--node", state.spec.nodeId,
    "--lane", state.spec.lane,
    "--target-path", stringAt(scenario, "observeTargetPath"),
    "--sample-interval-ms", String(sampleIntervalMs),
    "--screenshot-interval-ms", String(numberAt(scenario, "screenshotIntervalMs")),
    "--command-timeout-seconds", "55",
  ];
  const viewport = stringAtNullable(scenario, "viewport");
  if (viewport !== null) startArgs.push("--viewport", viewport);
  printQuickVerifyProgress(state, runId, "observe-start", "running", { targetPath: stringAt(scenario, "observeTargetPath"), remainingSeconds: remainingSeconds(deadline, 55) });
  const started = runChildCli(startArgs, remainingSeconds(deadline, 55), undefined, accountEnv.env);
  steps.push({ phase: "observe-start", ok: started.ok, result: started.result });
  const observerId = observerIdFromText(String(record(started.result).stdoutPreview ?? ""));
  printQuickVerifyProgress(state, runId, "observe-start", started.ok && observerId !== null ? "succeeded" : "failed", { observerId, exitCode: record(started.result).exitCode ?? null, timedOut: record(started.result).timedOut === true, elapsedMs: elapsedMs() });
  if (!started.ok || observerId === null) {
    const findings = quickVerifyControlFindings("observe-start-failed", 0, null, null);
    return recordQuickVerify(state, {
      ok: false,
      runId,
      scenarioId,
      reason,
      status: "blocked",
      observerId,
      elapsedMs: elapsedMs(),
      steps,
      failure: "observe-start-failed",
      findingCount: findings.length,
      findings,
      warnings: elapsedWarnings(),
      valuesRedacted: true,
    });
  }
  printQuickVerifyProgress(state, runId, "observe-wait-startup-ready", "running", { observerId, remainingSeconds: remainingSeconds(deadline, 55) });
  const startupReady = waitForQuickVerifyObserverStartup(state, observerId, deadline, sampleIntervalMs, warningBudgetSeconds);
  steps.push({ phase: "observe-wait-startup-ready", ok: startupReady.ok, result: startupReady });
  printQuickVerifyProgress(state, runId, "observe-wait-startup-ready", startupReady.ok === true ? "succeeded" : "failed", { observerId, failure: startupReady.failure ?? null, status: startupReady.status ?? null, heartbeatStatus: startupReady.heartbeatStatus ?? null, elapsedMs: elapsedMs() });
  if (startupReady.ok !== true) {
    return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
      runId,
      scenarioId,
      reason,
      observerId,
      promptIndex: 0,
      steps,
      failure: text(startupReady.failure ?? "observe-startup-ready-wait-failed"),
      elapsedMs: elapsedMs(),
      warnings: mergeWarnings(Array.isArray(startupReady.warnings) ? startupReady.warnings : [], elapsedWarnings()),
      promptSource: prompts.summary,
    }));
  }
  let promptIndex = 0;
  const sessionInvarianceChecks = sessionInvarianceChecksByRound(scenario);
  const nonBlockingCanaryWarnings: string[] = [];
  for (const item of commandSequence) {
    const type = stringAt(item, "type");
    const repeat = Math.max(1, typeof item.repeat === "number" && Number.isFinite(item.repeat) ? Math.trunc(item.repeat) : 1);
    for (let index = 0; index < repeat; index += 1) {
      if (Date.now() >= deadline) {
        printQuickVerifyProgress(state, runId, "timeout", "failed", { observerId, promptIndex, elapsedMs: elapsedMs(), hardBudgetSeconds });
        return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
          runId,
          scenarioId,
          reason,
          observerId,
          promptIndex,
          steps,
          failure: "quick-verify-timeout-over-budget",
          elapsedMs: elapsedMs(),
          warnings: mergeWarnings(`quick verify exceeded the hard ${hardBudgetSeconds}s execution budget after the configured ${warningBudgetSeconds}s targetValidation warning budget.`, elapsedWarnings()),
          promptSource: prompts.summary,
        }));
      }
      const commandWaitMs = Math.max(1000, Math.trunc(numberAtNullable(item, "commandWaitMs") ?? numberAtNullable(scenario, "commandWaitMs") ?? 55_000));
      const commandTimeoutSeconds = Math.max(1, Math.trunc(numberAtNullable(item, "commandTimeoutSeconds") ?? numberAtNullable(scenario, "commandTimeoutSeconds") ?? 55));
      const turnWaitChunkSeconds = Math.max(1, Math.trunc(numberAtNullable(item, "turnWaitChunkSeconds") ?? numberAtNullable(scenario, "turnWaitChunkSeconds") ?? 55));
      const args = ["web-probe", "observe", "command", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--type", type, "--wait-ms", String(commandWaitMs), "--command-timeout-seconds", String(remainingSeconds(deadline, commandTimeoutSeconds))];
      if (type === "selectProvider") args.push("--provider", stringAt(item, "provider"));
      if (type === "loginAccount" || type === "listSessions" || type === "logout") {
        const accountId = stringAtNullable(item, "accountId");
        if (accountId !== null) args.push("--account-id", accountId);
      }
      if (type === "switchSessions") {
        const fromAccountId = stringAtNullable(item, "fromAccountId");
        const toAccountId = stringAtNullable(item, "toAccountId");
        if (fromAccountId !== null) args.push("--from-account-id", fromAccountId);
        if (toAccountId !== null) args.push("--to-account-id", toAccountId);
      }
      if (type === "sendPrompt") {
        args.push("--text", prompts.prompts[promptIndex % prompts.prompts.length] ?? "");
        args.push("--expected-action-wait-ms", String(numberAtNullable(item, "expectedActionWaitMs") ?? 45000));
        promptIndex += 1;
      }
      appendScenarioObserveCommandArgs(args, item, { skipText: type === "sendPrompt" });
      printQuickVerifyProgress(state, runId, `observe-command-${type}`, "running", { observerId, promptIndex: type === "sendPrompt" ? promptIndex : null, repeatIndex: index + 1, repeat });
      const commandResult = runChildCli(args, remainingSeconds(deadline, Math.max(60, commandTimeoutSeconds + 10)));
      steps.push({ phase: `observe-command-${type}`, ok: commandResult.ok, promptIndex: type === "sendPrompt" ? promptIndex : null, result: commandResult.result });
      printQuickVerifyProgress(state, runId, `observe-command-${type}`, commandResult.ok ? "succeeded" : "failed", { observerId, promptIndex: type === "sendPrompt" ? promptIndex : null, exitCode: record(commandResult.result).exitCode ?? null, timedOut: record(commandResult.result).timedOut === true, elapsedMs: elapsedMs() });
      if (!commandResult.ok) {
        if (type === "sendPrompt") {
          printQuickVerifyProgress(state, runId, "observe-wait-turn-terminal-after-command-timeout", "running", { observerId, promptIndex, remainingSeconds: remainingSeconds(deadline, turnWaitChunkSeconds) });
          const delayedWaitResult = waitForQuickVerifyPromptTurn(state, observerId, promptIndex, deadline, sampleIntervalMs, warningBudgetSeconds, turnWaitChunkSeconds);
          steps.push({ phase: "observe-wait-turn-terminal-after-command-timeout", ok: delayedWaitResult.ok, promptIndex, result: delayedWaitResult });
          printQuickVerifyProgress(state, runId, "observe-wait-turn-terminal-after-command-timeout", delayedWaitResult.ok === true ? "succeeded" : "failed", { observerId, promptIndex, failure: delayedWaitResult.failure ?? null, status: delayedWaitResult.status ?? null, traceId: delayedWaitResult.traceId ?? null, elapsedMs: elapsedMs() });
          if (delayedWaitResult.ok === true) {
            const invariantResult = runQuickVerifySessionInvarianceChecks(state, observerId, sessionInvarianceChecks.get(promptIndex) ?? [], deadline, promptIndex, steps);
            nonBlockingCanaryWarnings.push(...mergeWarnings(record(invariantResult).warnings));
            printQuickVerifyProgress(state, runId, "observe-session-invariance", invariantResult.ok === true ? "succeeded" : "failed", { observerId, promptIndex, failure: record(invariantResult).failure ?? null, elapsedMs: elapsedMs() });
            if (invariantResult.ok !== true) {
              return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
                runId,
                scenarioId,
                reason,
                observerId,
                promptIndex,
                steps,
                failure: text(record(invariantResult).failure ?? "observe-session-invariance-failed"),
                promptSource: prompts.summary,
                elapsedMs: elapsedMs(),
                warnings: mergeWarnings(record(invariantResult).warnings, elapsedWarnings()),
              }));
            }
            continue;
          }
        }
        return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
          runId,
          scenarioId,
          reason,
          observerId,
          promptIndex,
          steps,
          failure: `observe-command-${type}-failed`,
          elapsedMs: elapsedMs(),
          warnings: elapsedWarnings(),
          promptSource: prompts.summary,
        }));
      }
      if (type === "sendPrompt") {
        printQuickVerifyProgress(state, runId, "observe-wait-turn-terminal", "running", { observerId, promptIndex, remainingSeconds: remainingSeconds(deadline, turnWaitChunkSeconds) });
        const waitResult = waitForQuickVerifyPromptTurn(state, observerId, promptIndex, deadline, sampleIntervalMs, warningBudgetSeconds, turnWaitChunkSeconds);
        steps.push({ phase: "observe-wait-turn-terminal", ok: waitResult.ok, promptIndex, result: waitResult });
        printQuickVerifyProgress(state, runId, "observe-wait-turn-terminal", waitResult.ok === true ? "succeeded" : "failed", { observerId, promptIndex, failure: waitResult.failure ?? null, status: waitResult.status ?? null, traceId: waitResult.traceId ?? null, elapsedMs: elapsedMs() });
        if (waitResult.ok !== true) {
          return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
            runId,
            scenarioId,
            reason,
            observerId,
            promptIndex,
            steps,
            failure: text(waitResult.failure ?? "observe-turn-terminal-wait-failed"),
            promptSource: prompts.summary,
            elapsedMs: elapsedMs(),
            warnings: mergeWarnings(Array.isArray(waitResult.warnings) ? waitResult.warnings : [], elapsedWarnings()),
          }));
        }
        const invariantResult = runQuickVerifySessionInvarianceChecks(state, observerId, sessionInvarianceChecks.get(promptIndex) ?? [], deadline, promptIndex, steps);
        nonBlockingCanaryWarnings.push(...mergeWarnings(record(invariantResult).warnings));
        printQuickVerifyProgress(state, runId, "observe-session-invariance", invariantResult.ok === true ? "succeeded" : "failed", { observerId, promptIndex, failure: record(invariantResult).failure ?? null, elapsedMs: elapsedMs() });
        if (invariantResult.ok !== true) {
          return recordQuickVerify(state, finalizeQuickVerifyFailure(state, {
            runId,
            scenarioId,
            reason,
            observerId,
            promptIndex,
            steps,
            failure: text(invariantResult.failure ?? "observe-session-invariance-check-failed"),
            promptSource: prompts.summary,
            elapsedMs: elapsedMs(),
            warnings: mergeWarnings(nonBlockingCanaryWarnings, elapsedWarnings()),
          }));
        }
      }
    }
  }
  printQuickVerifyProgress(state, runId, "observe-analyze", "running", { observerId, remainingSeconds: remainingSeconds(deadline, 120) });
  const analysis = runChildCli(["web-probe", "observe", "analyze", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--command-timeout-seconds", String(remainingSeconds(deadline, 120))], remainingSeconds(deadline, 120));
  steps.push({ phase: "observe-analyze", ok: analysis.ok, result: analysis.result });
  printQuickVerifyProgress(state, runId, "observe-analyze", analysis.ok ? "succeeded" : "failed", { observerId, exitCode: record(analysis.result).exitCode ?? null, timedOut: record(analysis.result).timedOut === true, elapsedMs: elapsedMs() });
  const indexEntry = readLocalObserveIndex(observerId);
  const artifactSummary = indexEntry === null ? { ok: false, reason: "observe-index-entry-missing", observerId, valuesRedacted: true } : readAnalysisSummaryFromWorkspace(state, indexEntry.stateDir, remainingSeconds(deadline, 30));
  const turnSummary = collectObserveView(state, observerId, "turn-summary", null, remainingSeconds(deadline, 30));
  const traceFrame = collectObserveView(state, observerId, "trace-frame", promptIndex > 0 ? promptIndex : null, remainingSeconds(deadline, 30));
  const controlFindings = quickVerifyControlFindings(null, promptIndex, turnSummary, traceFrame);
  const artifactSummaryRecord = record(artifactSummary);
  const artifactFindings = Array.isArray(artifactSummaryRecord.findings) ? artifactSummaryRecord.findings.map(record) : [];
  const findings = mergeFindingRecords(artifactFindings, controlFindings);
  const blockingFindings = findings.filter(isQuickVerifyBlockingFinding);
  const analysisWarnings = analysis.ok ? [] : ["quick verify analyze command returned non-zero but a readable analysis artifact was produced; targetValidation is using artifact severity plus control blockers."];
  const ok = record(artifactSummary).ok === true && controlFindings.length === 0 && blockingFindings.length === 0;
  printQuickVerifyProgress(state, runId, "record-report", ok ? "succeeded" : "blocked", { observerId, reportJsonSha256: stringAtNullable(artifactSummary, "reportJsonSha256"), findingCount: findings.length, blockingFindingCount: blockingFindings.length, controlFindingCount: controlFindings.length, elapsedMs: elapsedMs() });
  return recordQuickVerify(state, {
    ok,
    runId,
    scenarioId,
    reason,
    status: ok ? "analyzed" : "blocked",
    observerId,
    elapsedMs: elapsedMs(),
    stateDir: indexEntry?.stateDir ?? null,
    reportJsonSha256: stringAtNullable(artifactSummary, "reportJsonSha256"),
    findingCount: findings.length,
    artifactCount: numberAtNullable(artifactSummary, "artifactCount") ?? 0,
    failure: controlFindings.length > 0 ? "quick-verify-no-business-turn" : blockingFindings.length > 0 ? "quick-verify-blocking-findings" : null,
    promptSource: prompts.summary,
    accountEnv: accountEnv.summary,
    steps,
    analysis: artifactSummary,
    views: {
      summary: { renderedText: renderQuickVerifySummary({ runId, scenarioId, observerId, artifactSummary, steps, publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
      "auth-session-switch-summary": { renderedText: renderAuthSessionSwitchQuickVerifySummary({ runId, scenarioId, observerId, artifactSummary, steps, findings, accountEnv: accountEnv.summary, publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
      "turn-summary": { renderedText: typeof turnSummary.renderedText === "string" ? turnSummary.renderedText : null, ok: turnSummary.ok },
      "trace-frame": { renderedText: typeof traceFrame.renderedText === "string" ? traceFrame.renderedText : null, ok: traceFrame.ok },
    },
    findings,
    screenshot: record(artifactSummary).screenshot,
    publicOrigin: stringAt(state.publicExposure, "publicBaseUrl"),
    warnings: mergeWarnings(analysisWarnings, nonBlockingCanaryWarnings, elapsedWarnings()),
    valuesRedacted: true,
  });
}

function sessionInvarianceChecksByRound(scenario: Record<string, unknown>): Map<number, Record<string, unknown>[]> {
  const checks = new Map<number, Record<string, unknown>[]>();
  const items = Array.isArray(scenario.sessionInvarianceChecks) ? scenario.sessionInvarianceChecks.map(record) : [];
  for (const item of items) {
    const afterRound = typeof item.afterRound === "number" && Number.isInteger(item.afterRound) ? item.afterRound : null;
    if (afterRound === null || afterRound < 0) continue;
    const list = checks.get(afterRound) ?? [];
    list.push(item);
    checks.set(afterRound, list);
  }
  return checks;
}

function runQuickVerifySessionInvarianceChecks(
  state: SentinelCicdState,
  observerId: string,
  checks: readonly Record<string, unknown>[],
  deadline: number,
  promptIndex: number,
  steps: Record<string, unknown>[],
): Record<string, unknown> {
  const warnings: string[] = [];
  for (const check of checks) {
    const checkId = nonEmptyString(check.id) ?? `after-round-${promptIndex}`;
    const blocking = check.blocking === true;
    const commands: { readonly type: string; readonly enabled: boolean }[] = [
      { type: "refreshCurrentSession", enabled: check.refreshCurrent === true },
      { type: "switchAwayAndBack", enabled: check.switchAwayAndBack === true },
      { type: "assertSessionInvariant", enabled: check.assertSessionInvariant !== false },
    ];
    for (const command of commands) {
      if (!command.enabled) continue;
      const args = [
        "web-probe", "observe", "command", observerId,
        "--node", state.spec.nodeId,
        "--lane", state.spec.lane,
        "--type", command.type,
        "--after-round", String(promptIndex),
        "--wait-ms", "55000",
        "--command-timeout-seconds", String(remainingSeconds(deadline, 55)),
      ];
      const severity = nonEmptyString(check.severity);
      const findingId = nonEmptyString(check.findingId);
      const expectedSentinelRange = nonEmptyString(check.expectedSentinelRange);
      const alternateSessionStrategy = nonEmptyString(check.alternateSessionStrategy);
      if (severity !== null) args.push("--severity", severity);
      if (findingId !== null) args.push("--finding-id", findingId);
      if (expectedSentinelRange !== null) args.push("--expected-sentinel-range", expectedSentinelRange);
      if (command.type === "switchAwayAndBack" && alternateSessionStrategy !== null) args.push("--alternate-session-strategy", alternateSessionStrategy);
      if (command.type === "assertSessionInvariant" && check.requireComposerReady === true) args.push("--require-composer-ready");
      args.push(check.blocking === true ? "--blocking" : "--non-blocking");
      const result = runChildCli(args, remainingSeconds(deadline, 60));
      steps.push({ phase: `observe-session-invariance-${command.type}`, ok: result.ok, promptIndex, checkId, result: result.result });
      if (!result.ok) {
        if (!blocking) {
          warnings.push(`non-blocking session invariance canary ${checkId}/${command.type} failed after round ${promptIndex}; continuing Code Agent multi-round quick verify because scenario marks this check blocking=false.`);
          continue;
        }
        return { ok: false, failure: `observe-session-invariance-${command.type}-failed`, checkId, promptIndex, valuesRedacted: true };
      }
    }
  }
  return { ok: true, promptIndex, checkCount: checks.length, warnings, valuesRedacted: true };
}

function appendScenarioObserveCommandArgs(args: string[], item: Record<string, unknown>, options: { readonly skipText?: boolean } = {}): void {
  const mappings: readonly (readonly [string, string])[] = [
    ["path", "--path"],
    ["label", "--label"],
    ["sessionId", "--session-id"],
    ["provider", "--provider"],
    ["accountId", "--account-id"],
    ["fromAccountId", "--from-account-id"],
    ["toAccountId", "--to-account-id"],
    ["sourceId", "--source-id"],
    ["fileRef", "--file-ref"],
    ["filename", "--filename"],
    ["taskRef", "--task-ref"],
    ["taskId", "--task-id"],
    ["task", "--task"],
    ["field", "--field"],
    ["link", "--link"],
    ["title", "--title"],
    ["body", "--body"],
    ["status", "--status"],
    ["hwpodId", "--hwpod-id"],
    ["nodeId", "--node-id"],
    ["workspaceRoot", "--workspace-root"],
    ["root", "--root"],
  ];
  for (const [key, flag] of mappings) {
    if (args.includes(flag)) continue;
    const value = stringAtNullable(item, key);
    if (value !== null) args.push(flag, value);
  }
  if (options.skipText !== true && !args.includes("--text")) {
    const text = stringAtNullable(item, "text") ?? stringAtNullable(item, "value");
    if (text !== null) args.push("--text", text);
  }
  if (item.waitProjectManagementReady === true && !args.includes("--wait-project-management-ready")) args.push("--wait-project-management-ready");
}

function finalizeQuickVerifyFailure(state: SentinelCicdState, input: {
  readonly runId: string;
  readonly scenarioId: string;
  readonly reason: string;
  readonly observerId: string;
  readonly promptIndex: number;
  readonly steps: readonly Record<string, unknown>[];
  readonly failure: string;
  readonly promptSource?: Record<string, unknown>;
  readonly elapsedMs?: number;
  readonly warnings?: readonly unknown[];
}): Record<string, unknown> {
  const cleanupSteps: Record<string, unknown>[] = [];
  if (input.promptIndex > 0) {
    const cancel = runChildCli([
      "web-probe", "observe", "command", input.observerId,
      "--node", state.spec.nodeId,
      "--lane", state.spec.lane,
      "--type", "cancel",
      "--wait-ms", "55000",
      "--command-timeout-seconds", "55",
    ], 60);
    cleanupSteps.push({ phase: "observe-cancel-after-failure", ok: cancel.ok, result: cancel.result });
  }
  const stop = runChildCli([
    "web-probe", "observe", "stop", input.observerId,
    "--node", state.spec.nodeId,
    "--lane", state.spec.lane,
    "--force",
    "--command-timeout-seconds", "55",
  ], 30);
  cleanupSteps.push({ phase: "observe-stop-after-failure", ok: stop.ok, result: stop.result });
  const analysis = runChildCli([
    "web-probe", "observe", "analyze", input.observerId,
    "--node", state.spec.nodeId,
    "--lane", state.spec.lane,
    "--command-timeout-seconds", "55",
  ], 60);
  cleanupSteps.push({ phase: "observe-analyze-after-failure", ok: analysis.ok, result: analysis.result });
  const indexEntry = readLocalObserveIndex(input.observerId);
  const artifactSummary = indexEntry === null
    ? { ok: false, reason: "observe-index-entry-missing", observerId: input.observerId, valuesRedacted: true }
    : readAnalysisSummaryFromWorkspace(state, indexEntry.stateDir, 30);
  const turnSummary = collectObserveView(state, input.observerId, "turn-summary", null, 30);
  const traceFrame = collectObserveView(state, input.observerId, "trace-frame", input.promptIndex > 0 ? input.promptIndex : null, 30);
  const durableBusinessTurn = quickVerifyHasDurableBusinessTurn(input.promptIndex, turnSummary, traceFrame);
  const controlFindings = quickVerifyControlFindings(input.failure, input.promptIndex, turnSummary, traceFrame);
  const artifactSummaryRecord = record(artifactSummary);
  const artifactFindings = Array.isArray(artifactSummaryRecord.findings) ? artifactSummaryRecord.findings.map(record) : [];
  const findings = mergeFindingRecords(artifactFindings, controlFindings);
  const blockingFindings = findings.filter(isQuickVerifyBlockingFinding);
  const recoveredWaitFailure = durableBusinessTurn
    && isRecoverableQuickVerifyWaitFailure(input.failure)
    && record(artifactSummary).ok === true
    && controlFindings.length === 0
    && blockingFindings.length === 0;
  return {
    ok: recoveredWaitFailure,
    runId: input.runId,
    scenarioId: input.scenarioId,
    reason: input.reason,
    status: recoveredWaitFailure ? "analyzed" : "blocked",
    observerId: input.observerId,
    elapsedMs: input.elapsedMs ?? null,
    stateDir: indexEntry?.stateDir ?? null,
    reportJsonSha256: stringAtNullable(artifactSummary, "reportJsonSha256"),
    findingCount: findings.length,
    artifactCount: numberAtNullable(artifactSummary, "artifactCount") ?? 0,
    failure: recoveredWaitFailure ? null : input.failure,
    promptSource: input.promptSource,
    steps: [...input.steps, ...cleanupSteps],
    analysis: artifactSummary,
    views: {
      summary: { renderedText: renderQuickVerifySummary({ runId: input.runId, scenarioId: input.scenarioId, observerId: input.observerId, artifactSummary, steps: input.steps, publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
      "auth-session-switch-summary": { renderedText: renderAuthSessionSwitchQuickVerifySummary({ runId: input.runId, scenarioId: input.scenarioId, observerId: input.observerId, artifactSummary, steps: input.steps, findings, publicOrigin: stringAt(state.publicExposure, "publicBaseUrl") }) },
      "turn-summary": { renderedText: typeof turnSummary.renderedText === "string" ? turnSummary.renderedText : null, ok: turnSummary.ok },
      "trace-frame": { renderedText: typeof traceFrame.renderedText === "string" ? traceFrame.renderedText : null, ok: traceFrame.ok },
    },
    findings,
    screenshot: record(artifactSummary).screenshot,
    publicOrigin: stringAt(state.publicExposure, "publicBaseUrl"),
    warnings: mergeWarnings(
      Array.isArray(input.warnings) ? input.warnings : [],
      recoveredWaitFailure ? ["quick verify wait command timed out, but collected turn-summary/trace-frame artifacts show a durable completed business turn; treating the wait timeout as a non-blocking tool finding."] : [],
      targetValidationElapsedWarnings(input.elapsedMs ?? null, "quick verify confirm-wait", numberAt(state.cicd, "targetValidation.maxSeconds")),
    ),
    valuesRedacted: true,
  };
}

function recordQuickVerify(state: SentinelCicdState, payload: Record<string, unknown>): Record<string, unknown> {
  const views = compactQuickVerifyRecordViews(record(payload.views));
  const summary = {
    reason: payload.reason,
    status: payload.status,
    elapsedMs: payload.elapsedMs,
    failure: payload.failure,
    warnings: Array.isArray(payload.warnings) ? payload.warnings : [],
    analysis: compactQuickVerifyRecordAnalysis(payload.analysis),
    promptSource: payload.promptSource,
    steps: Array.isArray(payload.steps) ? payload.steps.map(compactQuickVerifyRecordStep) : [],
    valuesRedacted: true,
  };
  const recordResult = callSentinelService(state, "POST", "/api/runs/record", {
    runId: payload.runId,
    scenarioId: payload.scenarioId,
    status: payload.status,
    observerId: payload.observerId,
    stateDir: payload.stateDir,
    reportJsonSha256: payload.reportJsonSha256,
    findingCount: payload.findingCount,
    artifactCount: payload.artifactCount,
    summary,
    findings: payload.findings,
    views,
    screenshot: payload.screenshot,
    publicOrigin: payload.publicOrigin ?? stringAt(state.publicExposure, "publicBaseUrl"),
    maintenance: payload.reason === "maintenance-stop",
    valuesRedacted: true,
  }, 60);
  return withWarnings({ ...payload, views, recordResult, valuesRedacted: true }, recordResult.ok === true ? [] : ["quick verify completed but sentinel report index record failed; report/dashboard may lag until record payload is reduced or retried."]);
}

function compactQuickVerifyRecordViews(views: Record<string, unknown>): Record<string, unknown> {
  const compacted: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(views)) {
    const item = record(value);
    const limit = key === "summary" || key === "auth-session-switch-summary" ? 8_000 : 6_000;
    compacted[key] = {
      ...item,
      renderedText: boundQuickVerifyRecordText(item.renderedText, limit),
      valuesRedacted: true,
    };
  }
  return compacted;
}

function compactQuickVerifyRecordAnalysis(value: unknown): Record<string, unknown> | null {
  const item = record(value);
  if (Object.keys(item).length === 0) return null;
  return {
    ok: item.ok === true ? true : item.ok === false ? false : null,
    reportOk: item.reportOk === true ? true : item.reportOk === false ? false : null,
    reason: stringAtNullable(item, "reason"),
    stateDir: stringAtNullable(item, "stateDir"),
    reportJsonSha256: stringAtNullable(item, "reportJsonSha256"),
    reportMdSha256: stringAtNullable(item, "reportMdSha256"),
    findingCount: numberAtNullable(item, "findingCount"),
    artifactCount: numberAtNullable(item, "artifactCount"),
    counts: compactQuickVerifyRecordCounts(record(item.counts)),
    screenshot: compactQuickVerifyRecordScreenshot(record(item.screenshot)),
    findings: Array.isArray(item.findings) ? item.findings.slice(0, 16).map(compactQuickVerifyRecordFinding) : [],
    pagePerformanceSlowApi: Array.isArray(item.pagePerformanceSlowApi) ? item.pagePerformanceSlowApi.slice(0, 6).map(record) : [],
    valuesRedacted: true,
  };
}

function compactQuickVerifyRecordCounts(value: Record<string, unknown>): Record<string, unknown> {
  return {
    samples: numberAtNullable(value, "samples"),
    control: numberAtNullable(value, "control"),
    network: numberAtNullable(value, "network"),
    console: numberAtNullable(value, "console"),
    errors: numberAtNullable(value, "errors"),
    artifacts: numberAtNullable(value, "artifacts"),
    valuesRedacted: true,
  };
}

function compactQuickVerifyRecordScreenshot(value: Record<string, unknown>): Record<string, unknown> | null {
  if (Object.keys(value).length === 0) return null;
  return {
    path: stringAtNullable(value, "path"),
    sha256: stringAtNullable(value, "sha256"),
    bytes: numberAtNullable(value, "bytes"),
    valuesRedacted: true,
  };
}

function compactQuickVerifyRecordFinding(value: unknown): Record<string, unknown> {
  const item = record(value);
  return {
    id: stringAtNullable(item, "id"),
    kind: stringAtNullable(item, "kind"),
    code: stringAtNullable(item, "code"),
    severity: stringAtNullable(item, "severity"),
    level: stringAtNullable(item, "level"),
    count: numberAtNullable(item, "count"),
    summary: boundQuickVerifyRecordText(item.summary ?? item.message, 220),
    rootCause: boundQuickVerifyRecordText(item.rootCause, 140),
    rootCauseStatus: boundQuickVerifyRecordText(item.rootCauseStatus, 90),
    rootCauseConfidence: boundQuickVerifyRecordText(item.rootCauseConfidence, 40),
    nextAction: boundQuickVerifyRecordText(item.nextAction, 240),
    evidenceSummary: stringAtNullable(item, "evidenceSummary") ?? compactQuickVerifyFindingEvidence(item.evidence),
    blocking: item.blocking === true,
    valuesRedacted: true,
  };
}

function compactQuickVerifyFindingEvidence(value: unknown): string | null {
  const item = record(value);
  if (Object.keys(item).length === 0) return null;
  const keys = [
    "http404Count",
    "responseErrorCount",
    "requestFailedCount",
    "statuses",
    "afterProjectedSeqs",
    "sinceSeqs",
    "traceIds",
    "maxFallbackRatio",
    "maxFallbackTitleCount",
    "overThresholdSampleCount",
    "majorityFallbackSampleCount",
  ];
  const compact: Record<string, unknown> = {};
  for (const key of keys) {
    const raw = item[key];
    if (raw === null || raw === undefined) continue;
    compact[key] = Array.isArray(raw) ? raw.slice(0, 6) : raw;
  }
  return Object.keys(compact).length === 0 ? null : boundQuickVerifyRecordText(JSON.stringify(compact), 240);
}

function compactQuickVerifyRecordStep(value: unknown): Record<string, unknown> {
  const item = record(value);
  return {
    phase: stringAtNullable(item, "phase"),
    ok: item.ok === true ? true : item.ok === false ? false : null,
    promptIndex: numberAtNullable(item, "promptIndex"),
    checkId: stringAtNullable(item, "checkId"),
    failure: stringAtNullable(item, "failure"),
    result: compactQuickVerifyRecordStepResult(record(item.result)),
    valuesRedacted: true,
  };
}

function compactQuickVerifyRecordStepResult(value: Record<string, unknown>): Record<string, unknown> {
  return {
    ok: value.ok === true ? true : value.ok === false ? false : null,
    status: stringAtNullable(value, "status"),
    view: stringAtNullable(value, "view"),
    exitCode: numberAtNullable(value, "exitCode"),
    timedOut: value.timedOut === true ? true : value.timedOut === false ? false : null,
    stdoutBytes: numberAtNullable(value, "stdoutBytes"),
    stderrBytes: numberAtNullable(value, "stderrBytes"),
    stdoutPreview: boundQuickVerifyRecordText(value.stdoutPreview, 240),
    stderrPreview: boundQuickVerifyRecordText(value.stderrPreview, 240),
    valuesRedacted: true,
  };
}

function boundQuickVerifyRecordText(value: unknown, maxChars: number): string | null {
  if (typeof value !== "string") return null;
  if (value.length <= maxChars) return value;
  return `${value.slice(0, maxChars)}\n[truncated ${value.length - maxChars} chars]`;
}

function callSentinelService(state: SentinelCicdState, method: "GET" | "POST", pathWithQuery: string, body: Record<string, unknown> | null, timeoutSeconds: number): Record<string, unknown> {
  const namespace = stringAt(state.runtime, "namespace");
  const serviceName = stringAt(state.runtime, "serviceName");
  const servicePort = numberAt(state.runtime, "servicePort");
  const deploymentName = stringAt(state.runtime, "deploymentName");
  const url = `http://${serviceName}.${namespace}.svc.cluster.local:${servicePort}${pathWithQuery}`;
  if (process.env.UNIDESK_WEB_PROBE_SENTINEL_DIRECT_SERVICE === "1") {
    return callSentinelServiceDirect(method, pathWithQuery, body, timeoutSeconds, url);
  }
  const proxyPath = `/api/v1/namespaces/${namespace}/services/${serviceName}:${servicePort}/proxy${pathWithQuery}`;
  const bodyB64 = Buffer.from(body === null ? "" : JSON.stringify(body), "utf8").toString("base64");
  const pathB64 = Buffer.from(pathWithQuery, "utf8").toString("base64");
  const postScript = [
    "const path = Buffer.from(process.env.SENTINEL_PATH_B64 || '', 'base64').toString('utf8');",
    "const body = Buffer.from(process.env.SENTINEL_BODY_B64 || '', 'base64').toString('utf8');",
    `const url = 'http://127.0.0.1:${servicePort}' + path;`,
    "fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body }).then(async (response) => {",
    "  const text = await response.text();",
    "  process.stdout.write(text);",
    "  if (!response.ok) process.exit(22);",
    "}).catch((error) => {",
    "  console.error(error && error.stack ? error.stack : String(error));",
    "  process.exit(23);",
    "});",
  ].join(" ");
  const script = method === "GET"
    ? `kubectl get --raw ${shellQuote(proxyPath)}`
    : [
      "set -eu",
      `kubectl exec -n ${shellQuote(namespace)} deploy/${shellQuote(deploymentName)} -- env SENTINEL_PATH_B64=${shellQuote(pathB64)} SENTINEL_BODY_B64=${shellQuote(bodyB64)} node -e ${shellQuote(postScript)}`,
    ].join("\n");
  const maxAttempts = method === "GET" ? 3 : 1;
  const attemptTimeoutSeconds = Math.max(5, Math.min(timeoutSeconds, method === "GET" ? 15 : 60));
  const attempts: Record<string, unknown>[] = [];
  let result: CommandResult | null = null;
  let parsed: Record<string, unknown> | null = null;
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
    result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", script], repoRoot, { timeoutMs: attemptTimeoutSeconds * 1000 });
    parsed = parseJsonObject(result.stdout);
    attempts.push({ attempt, ...compactCommand(result), parsedOk: parsed !== null, valuesRedacted: true });
    if (result.exitCode === 0) break;
  }
  const compactBodyJson = compactSentinelServiceBodyJson(parsed);
  return {
    ok: result?.exitCode === 0,
    method,
    path: pathWithQuery,
    internalUrl: `http://${serviceName}.${namespace}.svc.cluster.local:${servicePort}${pathWithQuery}`,
    httpStatus: result?.exitCode === 0 ? 200 : null,
    bodyJson: record(compactBodyJson),
    bodyTextPreview: parsed === null ? clipTail(result?.stdout ?? "", 4000) : "",
    bodyBytes: Buffer.byteLength(result?.stdout ?? ""),
    error: result?.exitCode === 0 ? null : clipTail(`${result?.stderr ?? ""}${result?.stdout ?? ""}`, 1000),
    proxyPath,
    result: result === null ? null : compactCommand(result),
    attempts,
    valuesRedacted: true,
  };
}

function callSentinelServiceDirect(method: "GET" | "POST", pathWithQuery: string, body: Record<string, unknown> | null, timeoutSeconds: number, url: string): Record<string, unknown> {
  const bodyB64 = Buffer.from(body === null ? "" : JSON.stringify(body), "utf8").toString("base64");
  const fetchScript = [
    "const method = process.env.SENTINEL_METHOD || 'GET';",
    "const url = process.env.SENTINEL_URL || '';",
    "const body = Buffer.from(process.env.SENTINEL_BODY_B64 || '', 'base64').toString('utf8');",
    "const attempts = Math.max(1, Number(process.env.SENTINEL_ATTEMPTS || '1') || 1);",
    "const delayMs = Math.max(0, Number(process.env.SENTINEL_RETRY_DELAY_MS || '0') || 0);",
    "const headers = method === 'POST' ? { 'content-type': 'application/json' } : undefined;",
    "const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));",
    "(async () => {",
    "  let lastError = null;",
    "  for (let attempt = 1; attempt <= attempts; attempt += 1) {",
    "    try {",
    "      const response = await fetch(url, { method, headers, body: method === 'POST' ? body : undefined });",
    "      const text = await response.text();",
    "      process.stdout.write(text);",
    "      if (!response.ok) process.exit(22);",
    "      process.exit(0);",
    "    } catch (error) {",
    "      lastError = error;",
    "      console.error(JSON.stringify({ attempt, attempts, code: error?.cause?.code ?? null, address: error?.cause?.address ?? null, valuesRedacted: true }));",
    "      if (attempt < attempts && delayMs > 0) await sleep(delayMs);",
    "    }",
    "  }",
    "  console.error(lastError && lastError.stack ? lastError.stack : String(lastError));",
    "  process.exit(23);",
    "})().catch((error) => {",
    "  console.error(error && error.stack ? error.stack : String(error));",
    "  process.exit(24);",
    "});",
  ].join(" ");
  const attempts = method === "GET" ? 6 : 3;
  const retryDelayMs = 1000;
  const attemptTimeoutSeconds = Math.max(5, Math.min(timeoutSeconds, method === "GET" ? 20 : 70));
  const result = runCommand(["node", "-e", fetchScript], repoRoot, {
    timeoutMs: attemptTimeoutSeconds * 1000,
    env: {
      ...process.env,
      SENTINEL_METHOD: method,
      SENTINEL_URL: url,
      SENTINEL_BODY_B64: bodyB64,
      SENTINEL_ATTEMPTS: String(attempts),
      SENTINEL_RETRY_DELAY_MS: String(retryDelayMs),
    },
  });
  const parsed = parseJsonObject(result.stdout);
  const compactBodyJson = compactSentinelServiceBodyJson(parsed);
  return {
    ok: result.exitCode === 0,
    method,
    path: pathWithQuery,
    internalUrl: url,
    httpStatus: result.exitCode === 0 ? 200 : null,
    bodyJson: record(compactBodyJson),
    bodyTextPreview: parsed === null ? clipTail(result.stdout, 4000) : "",
    bodyBytes: Buffer.byteLength(result.stdout),
    error: result.exitCode === 0 ? null : clipTail(`${result.stderr}${result.stdout}`, 1000),
    proxyPath: null,
    result: compactCommand(result),
    attempts: [{ attempt: "1..n", maxAttempts: attempts, ...compactCommand(result), parsedOk: parsed !== null, transport: "direct-service", valuesRedacted: true }],
    transport: "direct-service",
    valuesRedacted: true,
  };
}

function compactSentinelServiceBodyJson(value: Record<string, unknown> | null): unknown {
  if (value === null || typeof value.renderedText !== "string") return value;
  return {
    ...pickFields(value, ["ok", "view", "error", "availableViews", "valuesRedacted"]),
    run: pickFields(record(value.run), ["id", "scenario_id", "status", "node", "lane", "observer_id", "state_dir", "report_json_sha256", "finding_count", "artifact_count", "maintenance", "created_at", "updated_at"]),
    summary: pickFields(record(value.summary), ["reason", "status", "valuesRedacted"]),
    findings: Array.isArray(value.findings) ? value.findings.slice(0, 12) : [],
    renderedText: value.renderedText,
    valuesRedacted: true,
  };
}

function pickFields(value: Record<string, unknown>, keys: readonly string[]): Record<string, unknown> {
  const picked: Record<string, unknown> = {};
  for (const key of keys) {
    if (Object.prototype.hasOwnProperty.call(value, key)) picked[key] = value[key];
  }
  return picked;
}

function clipTail(value: string, maxChars: number): string {
  return value.length <= maxChars ? value : value.slice(-maxChars);
}

function probePublicSentinelService(state: SentinelCicdState, pathWithQuery: string, timeoutSeconds: number): Record<string, unknown> {
  const publicBaseUrl = stringAt(state.publicExposure, "publicBaseUrl").replace(/\/$/u, "");
  const url = `${publicBaseUrl}${pathWithQuery.startsWith("/") ? pathWithQuery : `/${pathWithQuery}`}`;
  const timeoutMs = Math.max(1000, Math.min(Math.trunc(timeoutSeconds * 1000), 20_000));
  const js = [
    "const url=process.env.REQ_URL||'';",
    "const timeoutMs=Number(process.env.REQ_TIMEOUT_MS||10000);",
    "let out;",
    "try{",
    "  const controller=new AbortController();",
    "  const timer=setTimeout(()=>controller.abort(), timeoutMs);",
    "  const started=Date.now();",
    "  const res=await fetch(url,{signal:controller.signal});",
    "  const text=await res.text();",
    "  clearTimeout(timer);",
    "  let bodyJson=null; try{bodyJson=JSON.parse(text)}catch{}",
    "  out={ok:res.ok,httpStatus:res.status,publicUrl:url,contentType:res.headers.get('content-type'),bodyJson,bodyTextPreview:text.slice(0,4000),bodyBytes:Buffer.byteLength(text),elapsedMs:Date.now()-started,valuesRedacted:true};",
    "}catch(error){out={ok:false,publicUrl:url,error:error instanceof Error?error.message:String(error),valuesRedacted:true};}",
    "console.log(JSON.stringify(out));",
  ].join("");
  const result = runCommand(["bun", "-e", js], repoRoot, {
    timeoutMs: timeoutMs + 2000,
    env: { ...process.env, REQ_URL: url, REQ_TIMEOUT_MS: String(timeoutMs) },
  });
  const parsed = parseJsonObject(result.stdout);
  return {
    ok: result.exitCode === 0 && parsed?.ok === true,
    method: "GET",
    path: pathWithQuery,
    publicUrl: url,
    httpStatus: parsed?.httpStatus ?? null,
    bodyJson: record(parsed?.bodyJson),
    bodyTextPreview: typeof parsed?.bodyTextPreview === "string" ? parsed.bodyTextPreview : "",
    bodyBytes: parsed?.bodyBytes ?? null,
    error: parsed?.error ?? null,
    result: compactCommand(result),
    valuesRedacted: true,
  };
}

function probeSentinelPublicExposure(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const publicBaseUrl = stringAt(state.publicExposure, "publicBaseUrl");
  const hostname = stringAt(state.publicExposure, "hostname");
  const expectedA = stringAt(state.publicExposure, "expectedA");
  const probeUrl = `${publicBaseUrl.replace(/\/$/u, "")}/api/health`;
  const script = [
    "set +e",
    `host=${shellQuote(hostname)}`,
    `expected=${shellQuote(expectedA)}`,
    `url=${shellQuote(probeUrl)}`,
    "dns=$(getent ahostsv4 \"$host\" 2>/dev/null | awk '{print $1}' | sort -u | paste -sd, -)",
    "headers=$(mktemp)",
    "body=$(mktemp)",
    "writeout=$(curl -sS -D \"$headers\" -o \"$body\" --connect-timeout 8 --max-time 20 --write-out '%{http_code} %{ssl_verify_result} %{remote_ip}' \"$url\" 2>/tmp/web-probe-sentinel-public.err)",
    "curl_rc=$?",
    "body_head=$(head -c 4000 \"$body\" | base64 | tr -d '\\n')",
    "node - \"$dns\" \"$expected\" \"$writeout\" \"$curl_rc\" \"$url\" \"$body_head\" \"$headers\" <<'NODE'",
    "const fs=require('node:fs');",
    "const [dns,expected,writeout,rcRaw,url,bodyB64,headersPath]=process.argv.slice(2);",
    "const [statusRaw,sslRaw,remoteIp]=String(writeout||'').trim().split(/\\s+/);",
    "const status=Number(statusRaw||0);",
    "const ssl=Number(sslRaw||-1);",
    "const addrs=dns?dns.split(',').filter(Boolean):[];",
    "const headers=(()=>{try{return fs.readFileSync(headersPath,'utf8')}catch{return ''}})();",
    "const body=Buffer.from(bodyB64||'', 'base64').toString('utf8');",
    "let bodyJson=null; try{bodyJson=JSON.parse(body)}catch{}",
    "const authCovered=status===401||status===403||status>=200&&status<300;",
    "const edgeOk=Number(rcRaw)===0&&ssl===0&&status>0&&status<500;",
    "const upstreamOk=status>=200&&status<300&&(bodyJson?.ok===true||body.includes('valuesRedacted'));",
    "const dnsMatches=addrs.includes(expected);",
    "console.log(JSON.stringify({ok:dnsMatches&&edgeOk&&authCovered&&upstreamOk,publicUrl:url,dns:{addresses:addrs,expectedA:expected,matches:dnsMatches},tls:{verified:ssl===0,sslVerifyResult:ssl,remoteIp:remoteIp||null},https:{curlExitCode:Number(rcRaw),httpStatus:status,edgeOk},auth:{requestAuthorizationHeader:false,covered:authCovered,status},upstream:{ok:upstreamOk,bodyPreview:body.slice(0,200)},headers:{wwwAuthenticate:/^www-authenticate:/im.test(headers)},valuesRedacted:true}));",
    "NODE",
  ].join("\n");
  const result = runCommand(["bash", "-lc", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 30) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, ...record(parsed), result: compactCommand(result), valuesRedacted: true };
}

function probeSentinelPublicDashboard(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const publicBaseUrl = stringAt(state.publicExposure, "publicBaseUrl").replace(/\/$/u, "");
  const rootUrl = `${publicBaseUrl}/`;
  const cssUrl = `${publicBaseUrl}/monitor-web/assets/monitor-web.css`;
  const jsUrl = `${publicBaseUrl}/monitor-web/assets/monitor-web.js`;
  const vueUrl = `${publicBaseUrl}/monitor-web/assets/vendor/vue.esm-browser.prod.js`;
  const script = [
    "set +e",
    `root_url=${shellQuote(rootUrl)}`,
    `css_url=${shellQuote(cssUrl)}`,
    `js_url=${shellQuote(jsUrl)}`,
    `vue_url=${shellQuote(vueUrl)}`,
    "root_body=$(mktemp)",
    "css_body=$(mktemp)",
    "js_body=$(mktemp)",
    "vue_body=$(mktemp)",
    "root_code=$(curl -sS -L --connect-timeout 8 --max-time 20 -o \"$root_body\" --write-out '%{http_code}' \"$root_url\" 2>/tmp/web-probe-sentinel-dashboard-root.err); root_rc=$?",
    "css_code=$(curl -sS -L --connect-timeout 8 --max-time 20 -o \"$css_body\" --write-out '%{http_code}' \"$css_url\" 2>/tmp/web-probe-sentinel-dashboard-css.err); css_rc=$?",
    "js_code=$(curl -sS -L --connect-timeout 8 --max-time 20 -o \"$js_body\" --write-out '%{http_code}' \"$js_url\" 2>/tmp/web-probe-sentinel-dashboard-js.err); js_rc=$?",
    "vue_code=$(curl -sS -L --connect-timeout 8 --max-time 20 -o \"$vue_body\" --write-out '%{http_code}' \"$vue_url\" 2>/tmp/web-probe-sentinel-dashboard-vue.err); vue_rc=$?",
    "node - \"$root_url\" \"$css_url\" \"$js_url\" \"$vue_url\" \"$root_code\" \"$root_rc\" \"$css_code\" \"$css_rc\" \"$js_code\" \"$js_rc\" \"$vue_code\" \"$vue_rc\" \"$root_body\" \"$css_body\" \"$js_body\" \"$vue_body\" <<'NODE'",
    "const fs=require('node:fs');",
    "const [rootUrl,cssUrl,jsUrl,vueUrl,rootCode,rootRc,cssCode,cssRc,jsCode,jsRc,vueCode,vueRc,rootPath,cssPath,jsPath,vuePath]=process.argv.slice(2);",
    "function read(path){try{return fs.readFileSync(path,'utf8')}catch{return ''}}",
    "const root=read(rootPath); const css=read(cssPath); const js=read(jsPath); const vue=read(vuePath);",
    "const rootOk=Number(rootRc)===0&&Number(rootCode)>=200&&Number(rootCode)<300&&root.includes('id=\"monitor-web-root\"')&&root.includes('/monitor-web/assets/monitor-web.js')&&root.includes('monitor-web-bootstrap');",
    "const cssOk=Number(cssRc)===0&&Number(cssCode)>=200&&Number(cssCode)<300&&css.includes('monitor-shell')&&css.includes('workspace-grid')&&css.includes('trend-stage')&&css.length>1000;",
    "const jsOk=Number(jsRc)===0&&Number(jsCode)>=200&&Number(jsCode)<300&&js.includes('createApp')&&js.includes('/api/overview')&&js.includes('data-monitor-trend-curve')&&js.length>1000;",
    "const vueOk=Number(vueRc)===0&&Number(vueCode)>=200&&Number(vueCode)<300&&vue.includes('createApp')&&vue.length>80000;",
    "console.log(JSON.stringify({ok:rootOk&&cssOk&&jsOk&&vueOk,root:{url:rootUrl,httpStatus:Number(rootCode),bytes:Buffer.byteLength(root),shell:root.includes('id=\"monitor-web-root\"'),contract:root.includes('draft-2026-06-27-p11-monitor-web-observability-dashboard')},css:{url:cssUrl,httpStatus:Number(cssCode),bytes:Buffer.byteLength(css),workspaceGrid:css.includes('workspace-grid'),trendStage:css.includes('trend-stage')},js:{url:jsUrl,httpStatus:Number(jsCode),bytes:Buffer.byteLength(js),vueApp:js.includes('createApp'),apiClient:js.includes('/api/overview'),trend:js.includes('data-monitor-trend-curve')},vue:{url:vueUrl,httpStatus:Number(vueCode),bytes:Buffer.byteLength(vue),runtime:vue.includes('createApp')},valuesRedacted:true}));",
    "NODE",
  ].join("\n");
  const result = runCommand(["bash", "-lc", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 30) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, ...record(parsed), result: compactCommand(result), valuesRedacted: true };
}

function applySentinelRuntimeSecrets(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const sourcesByPurpose = new Map<string, Record<string, unknown>>();
  for (const source of arrayAt(state.secrets, "sources").map(record)) {
    const purpose = stringAtNullable(source, "purpose");
    if (purpose !== null) sourcesByPurpose.set(purpose, source);
  }
  const desired: Array<{ namespace: string; name: string; data: Array<{ key: string; value: string; sourcePurpose: string; sourceRef: string; sourceKey: string; fingerprint: string }> }> = [];
  const missing: Record<string, unknown>[] = [];
  const skipped: Record<string, unknown>[] = [];
  for (const runtimeSecret of arrayAt(state.secrets, "runtimeSecrets").map(record)) {
    const name = stringAt(runtimeSecret, "name");
    const namespace = stringAt(runtimeSecret, "namespace");
    const data: Array<{ key: string; value: string; sourcePurpose: string; sourceRef: string; sourceKey: string; fingerprint: string }> = [];
    for (const item of arrayAt(runtimeSecret, "data").map(record)) {
      const sourcePurpose = stringAt(item, "sourcePurpose");
      const targetKey = stringAt(item, "targetKey");
      if (sourcePurpose === "frp-token") {
        skipped.push({ name, namespace, targetKey, sourcePurpose, reason: "managed-by-publicExposure-frpc", valuesRedacted: true });
        continue;
      }
      const source = sourcesByPurpose.get(sourcePurpose);
      if (source === undefined) {
        missing.push({ name, namespace, targetKey, sourcePurpose, reason: "source-purpose-missing", valuesRedacted: true });
        continue;
      }
      const sourceRef = stringAt(source, "sourceRef");
      const sourceKey = stringAt(source, "sourceKey");
      const material = readSentinelSecretSourceValue(source);
      if (!material.ok) {
        missing.push({ name, namespace, targetKey, sourcePurpose, sourceRef, sourceKey, reason: material.error, sourcePath: material.sourcePath, valuesRedacted: true });
        continue;
      }
      const value = stringAt(material, "value");
      data.push({
        key: targetKey,
        value,
        sourcePurpose,
        sourceRef,
        sourceKey,
        fingerprint: `sha256:${createHash("sha256").update(value).digest("hex").slice(0, 16)}`,
      });
    }
    if (data.length > 0) desired.push({ namespace, name, data });
  }
  if (missing.length > 0) return { ok: false, phase: "local-source", missing, skipped, valuesRedacted: true };
  if (desired.length === 0) return { ok: true, phase: "skipped-no-runtime-secrets", secretCount: 0, keyCount: 0, skippedKeyCount: skipped.length, skipped, valuesRedacted: true };
  const manifests = desired.map((secret) => ({
    apiVersion: "v1",
    kind: "Secret",
    metadata: {
      name: secret.name,
      namespace: secret.namespace,
      labels: {
        "app.kubernetes.io/managed-by": "unidesk",
        "app.kubernetes.io/part-of": "hwlab-web-probe-sentinel",
        "unidesk.ai/node": state.spec.nodeId,
        "unidesk.ai/lane": state.spec.lane,
        "unidesk.ai/web-probe-sentinel-id": state.sentinelId,
      },
    },
    type: "Opaque",
    data: Object.fromEntries(secret.data.map((item) => [item.key, Buffer.from(item.value, "utf8").toString("base64")])),
  }));
  const manifestYaml = `${manifests.map((item) => Bun.YAML.stringify(item).trim()).join("\n---\n")}\n`;
  const summary = desired.map((secret) => ({
    name: secret.name,
    namespace: secret.namespace,
    keys: secret.data.map((item) => item.key).sort(),
    sources: secret.data.map((item) => ({ key: item.key, sourcePurpose: item.sourcePurpose, sourceRef: item.sourceRef, sourceKey: item.sourceKey, fingerprint: item.fingerprint, valuesRedacted: true })),
    valuesRedacted: true,
  }));
  const summaryB64 = Buffer.from(JSON.stringify(summary), "utf8").toString("base64");
  const script = [
    "set +e",
    `summary_b64=${shellQuote(summaryB64)}`,
    "tmp=$(mktemp -d)",
    "trap 'rm -rf \"$tmp\"' EXIT",
    "manifest=\"$tmp/runtime-secrets.yaml\"",
    "cat >\"$manifest\"",
    "kubectl apply --server-side --force-conflicts --field-manager=unidesk-web-probe-sentinel-runtime-secrets -f \"$manifest\" >/tmp/web-probe-sentinel-runtime-secrets.out 2>/tmp/web-probe-sentinel-runtime-secrets.err",
    "apply_rc=$?",
    "python3 - \"$summary_b64\" \"$apply_rc\" <<'PY'",
    "import base64, json, subprocess, sys",
    "summary = json.loads(base64.b64decode(sys.argv[1]).decode('utf-8'))",
    "apply_rc = int(sys.argv[2])",
    "items = []",
    "ok = apply_rc == 0",
    "for secret in summary:",
    "    proc = subprocess.run(['kubectl', '-n', secret['namespace'], 'get', 'secret', secret['name'], '-o', 'json'], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)",
    "    data = json.loads(proc.stdout).get('data', {}) if proc.returncode == 0 and proc.stdout else {}",
    "    keys = {key: key in data for key in secret['keys']}",
    "    present = proc.returncode == 0 and all(keys.values())",
    "    ok = ok and present",
    "    items.append({'name': secret['name'], 'namespace': secret['namespace'], 'present': present, 'keys': keys, 'sources': secret['sources'], 'valuesRedacted': True})",
    "print(json.dumps({'ok': ok, 'applyExitCode': apply_rc, 'secretCount': len(summary), 'keyCount': sum(len(item['keys']) for item in summary), 'items': items, 'valuesRedacted': True}, ensure_ascii=False))",
    "PY",
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", script], repoRoot, { input: manifestYaml, timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, ...record(parsed), skippedKeyCount: skipped.length, skipped, result: compactCommand(result), valuesRedacted: true };
}

function readSentinelSecretSourceValue(source: Record<string, unknown>): Record<string, unknown> {
  const sourceRef = stringAt(source, "sourceRef");
  const sourceKey = stringAt(source, "sourceKey");
  const paths = secretSourcePaths(sourceRef);
  const sourcePath = paths.find((item) => existsSync(item)) ?? paths[0] ?? join(repoRoot, ".state", "secrets", sourceRef);
  if (!existsSync(sourcePath)) return { ok: false, error: "secret-source-missing", sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  const values = parseEnvFile(readFileSync(sourcePath, "utf8"));
  const value = values[sourceKey];
  if (value === undefined || value.length === 0) return { ok: false, error: "secret-source-key-missing", sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  const format = stringAtNullable(source, "format");
  if (format === null) return { ok: true, value, sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  if (format === "web-account-json") {
    const username = stringAtNullable(source, "username");
    if (username === null) return { ok: false, error: "web-account-json-username-missing", sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
    return { ok: true, value: JSON.stringify({ username, password: value }), sourceRef, sourceKey, format, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  }
  return { ok: false, error: "unsupported-secret-source-format", sourceRef, sourceKey, format, sourcePath: displayPath(sourcePath), valuesRedacted: true };
}

function applySentinelPublicExposure(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const material = readSentinelFrpcMaterial(state);
  if (!material.ok) return { ok: false, hostname: stringAt(state.publicExposure, "hostname"), material, valuesRedacted: true };
  const secret = applySentinelFrpcSecret(state, stringAt(material, "frpcToml"), timeoutSeconds);
  const caddy = applySentinelCaddyBlock(state, timeoutSeconds);
  return {
    ok: secret.ok === true && caddy.ok === true,
    hostname: stringAt(state.publicExposure, "hostname"),
    publicBaseUrl: stringAt(state.publicExposure, "publicBaseUrl"),
    material: {
      ok: true,
      sourceRef: material.sourceRef,
      sourcePath: material.sourcePath,
      fingerprint: material.fingerprint,
      valuesRedacted: true,
    },
    secret,
    caddy,
    valuesRedacted: true,
  };
}

function readSentinelFrpcMaterial(state: SentinelCicdState): Record<string, unknown> {
  const sourceRef = stringAt(state.publicExposure, "frpc.tokenSourceRef");
  const sourceKey = stringAt(state.publicExposure, "frpc.tokenSourceKey");
  const paths = secretSourcePaths(sourceRef);
  const sourcePath = paths.find((item) => existsSync(item)) ?? paths[0] ?? join(repoRoot, ".state", "secrets", sourceRef);
  if (!existsSync(sourcePath)) return { ok: false, error: "frp-token-source-missing", sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  const values = parseEnvFile(readFileSync(sourcePath, "utf8"));
  const token = values[sourceKey];
  if (token === undefined || token.length === 0) return { ok: false, error: "frp-token-key-missing", sourceRef, sourceKey, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  const proxy = record(valueAtPath(state.publicExposure, "frpc.httpProxy"));
  const frpcToml = [
    `serverAddr = "${tomlEscape(stringAt(state.publicExposure, "frpc.serverAddr"))}"`,
    `serverPort = ${numberAt(state.publicExposure, "frpc.serverPort")}`,
    "loginFailExit = true",
    `auth.token = "${tomlEscape(token)}"`,
    "",
    "[[proxies]]",
    `name = "${tomlEscape(stringAt(proxy, "name"))}"`,
    'type = "tcp"',
    `localIP = "${tomlEscape(stringAt(proxy, "localIP"))}"`,
    `localPort = ${numberAt(proxy, "localPort")}`,
    `remotePort = ${numberAt(proxy, "remotePort")}`,
    "",
  ].join("\n");
  return {
    ok: true,
    sourceRef,
    sourceKey,
    sourcePath: displayPath(sourcePath),
    frpcToml,
    fingerprint: `sha256:${createHash("sha256").update(`${token}\n${frpcToml}`).digest("hex").slice(0, 16)}`,
    valuesRedacted: true,
  };
}

function applySentinelFrpcSecret(state: SentinelCicdState, frpcToml: string, timeoutSeconds: number): Record<string, unknown> {
  const namespace = stringAt(state.runtime, "namespace");
  const secretName = stringAt(state.publicExposure, "frpc.secretName");
  const secretKey = stringAt(state.publicExposure, "frpc.secretKey");
  const script = [
    "set +e",
    `namespace=${shellQuote(namespace)}`,
    `secret=${shellQuote(secretName)}`,
    `key=${shellQuote(secretKey)}`,
    "tmp=$(mktemp -d)",
    "trap 'rm -rf \"$tmp\"' EXIT",
    "cat >\"$tmp/frpc.toml\"",
    "kubectl -n \"$namespace\" create secret generic \"$secret\" --from-file=\"$key=$tmp/frpc.toml\" --dry-run=client -o yaml | kubectl apply --server-side --force-conflicts --field-manager=unidesk-web-probe-sentinel-public-exposure -f - >/tmp/web-probe-sentinel-frpc-secret.out 2>/tmp/web-probe-sentinel-frpc-secret.err",
    "rc=$?",
    "present=no",
    "bytes=0",
    "if kubectl -n \"$namespace\" get secret \"$secret\" -o jsonpath=\"{.data.$key}\" >/tmp/web-probe-sentinel-frpc-secret.data 2>/dev/null; then present=yes; bytes=$(base64 -d </tmp/web-probe-sentinel-frpc-secret.data 2>/dev/null | wc -c | tr -d ' '); fi",
    "node - \"$rc\" \"$namespace\" \"$secret\" \"$key\" \"$present\" \"$bytes\" <<'NODE'",
    "const [rc, namespace, secret, key, present, bytes] = process.argv.slice(2);",
    "console.log(JSON.stringify({ok:Number(rc)===0&&present==='yes',namespace,secret,key,present:present==='yes',bytes:Number(bytes||0),applyExitCode:Number(rc),valuesRedacted:true}));",
    "NODE",
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", script], repoRoot, { input: frpcToml, timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, ...record(parsed), result: compactCommand(result), valuesRedacted: true };
}

function applySentinelCaddyBlock(state: SentinelCicdState, timeoutSeconds: number): Record<string, unknown> {
  const hostname = stringAt(state.publicExposure, "hostname");
  const owner = stringAt(state.publicExposure, "caddy.managedBlockOwner");
  const configPath = stringAt(state.publicExposure, "caddy.configPath");
  const serviceName = stringAt(state.publicExposure, "caddy.serviceName");
  const responseHeaderTimeoutSeconds = numberAt(state.publicExposure, "caddy.responseHeaderTimeoutSeconds");
  const remotePort = numberAt(state.publicExposure, "frpc.httpProxy.remotePort");
  const routePrefix = normalizeRoutePrefix(stringAtNullable(state.publicExposure, "routePrefix"));
  const rootOrder = stringAtNullable(state.publicExposure, "caddy.rootOrder") ?? "normal";
  const monitorRoot = record(state.publicExposure.monitorRoot);
  const cleanupOwner = monitorRoot.enabled === false ? stringAtNullable(monitorRoot, "caddyManagedBlockOwner") : null;
  const proxyLines = [
    `reverse_proxy 127.0.0.1:${remotePort} {`,
    "    transport http {",
    `        response_header_timeout ${responseHeaderTimeoutSeconds}s`,
    "    }",
    "}",
  ];
  const block = [
    routePrefix === "/" ? "handle {" : `handle_path ${routePrefix}* {`,
    ...proxyLines.map((line) => `    ${line}`),
    "}",
    "",
  ].join("\n");
  const blockB64 = Buffer.from(block, "utf8").toString("base64");
  const script = [
    "set +e",
    `hostname=${shellQuote(hostname)}`,
    `owner=${shellQuote(owner)}`,
    `config_path=${shellQuote(configPath)}`,
    `service=${shellQuote(serviceName)}`,
    `route_prefix=${shellQuote(routePrefix)}`,
    `root_order=${shellQuote(rootOrder)}`,
    `cleanup_owner=${shellQuote(cleanupOwner ?? "")}`,
    `block_b64=${shellQuote(blockB64)}`,
    "marker=\"unidesk managed $owner\"",
    "tmp=$(mktemp -d)",
    "trap 'rm -rf \"$tmp\"' EXIT",
    "block=\"$tmp/block\"",
    "next=\"$tmp/Caddyfile\"",
    "printf '%s' \"$block_b64\" | base64 -d >\"$block\"",
    "if [ -f \"$config_path\" ]; then cp \"$config_path\" \"$next\"; else : >\"$next\"; fi",
    "python3 - \"$next\" \"$block\" \"$marker\" \"$hostname\" \"$route_prefix\" \"$root_order\" \"$cleanup_owner\" <<'PY' >/tmp/web-probe-sentinel-caddy-python.out 2>/tmp/web-probe-sentinel-caddy-python.err",
    "import pathlib, re, sys",
    "config = pathlib.Path(sys.argv[1])",
    "block = pathlib.Path(sys.argv[2]).read_text(encoding='utf-8')",
    "marker = sys.argv[3]",
    "hostname = sys.argv[4]",
    "route_prefix = sys.argv[5]",
    "root_order = sys.argv[6]",
    "cleanup_owner = sys.argv[7]",
    "text = config.read_text(encoding='utf-8') if config.exists() else ''",
    "begin = f'# BEGIN {marker}'",
    "end = f'# END {marker}'",
    "def managed_pattern(marker_text):",
    "    return re.compile(rf'(?ms)^[ \\t]*# BEGIN {re.escape(marker_text)}\\n.*?^[ \\t]*# END {re.escape(marker_text)}\\n*')",
    "pattern = managed_pattern(marker)",
    "def collect_nested_managed(segment):",
    "    preserved = []",
    "    lines = segment.splitlines()",
    "    index = 0",
    "    while index < len(lines):",
    "        stripped = lines[index].strip()",
    "        if stripped.startswith('# BEGIN ') and stripped != begin:",
    "            owner_text = stripped[len('# BEGIN '):]",
    "            end_line = '# END ' + owner_text",
    "            block_lines = [lines[index]]",
    "            index += 1",
    "            while index < len(lines):",
    "                block_lines.append(lines[index])",
    "                if lines[index].strip() == end_line:",
    "                    break",
    "                index += 1",
    "            preserved.append('\\n'.join(block_lines).rstrip() + '\\n')",
    "        index += 1",
    "    return preserved",
    "preserved_blocks = []",
    "for match in pattern.finditer(text):",
    "    preserved_blocks.extend(collect_nested_managed(match.group(0)))",
    "text = pattern.sub('', text)",
    "if cleanup_owner:",
    "    cleanup_marker = f'unidesk managed {cleanup_owner}'",
    "    if cleanup_marker != marker:",
    "        text = managed_pattern(cleanup_marker).sub('', text)",
    "def site_span(src, host):",
    "    match = re.search(rf'(?m)^([ \\t]*){re.escape(host)}[ \\t]*\\{{[ \\t]*\\n', src)",
    "    if not match:",
    "        return None",
    "    depth = 1",
    "    index = match.end()",
    "    while index < len(src):",
    "        char = src[index]",
    "        if char == '{':",
    "            depth += 1",
    "        elif char == '}':",
    "            depth -= 1",
    "            if depth == 0:",
    "                end_index = index + 1",
    "                if end_index < len(src) and src[end_index] == '\\n':",
    "                    end_index += 1",
    "                return match.start(), end_index, index, match.end()",
    "        index += 1",
    "    raise ValueError(f'unclosed Caddy site block for {host}')",
    "handler = '\\n'.join(('    ' + line) if line else '' for line in block.rstrip().splitlines())",
    "managed = f'    {begin}\\n{handler}\\n    {end}\\n'",
    "def fallback_insert_pos(site, relative_open, close_rel):",
    "    for match in re.finditer(r'(?m)^[ \\t]*handle[ \\t]*\\{[ \\t]*\\n', site[relative_open:close_rel]):",
    "        pos = relative_open + match.start()",
    "        prev_end = pos - 1",
    "        if prev_end >= 0 and site[prev_end] == '\\n':",
    "            prev_end -= 1",
    "        if prev_end >= 0:",
    "            prev_start = site.rfind('\\n', 0, prev_end + 1) + 1",
    "            if site[prev_start:prev_end + 1].strip().startswith('# BEGIN '):",
    "                return prev_start",
    "        return pos",
    "    return relative_open",
    "def append_before_close(site, close_rel, addition):",
    "    prefix = site[:close_rel]",
    "    suffix = site[close_rel:]",
    "    if prefix and not prefix.endswith('\\n'):",
    "        prefix += '\\n'",
    "    return prefix + addition + suffix",
    "span = site_span(text, hostname)",
    "if span is None:",
    "    body = ''.join(preserved_blocks) + managed",
    "    text = text.rstrip() + '\\n\\n' + f'{hostname} {{\\n{body}}}\\n'",
    "else:",
    "    start, stop, close_index, open_end = span",
    "    site = text[start:stop]",
    "    relative_open = open_end - start",
    "    close_rel = close_index - start",
    "    additions = ''.join(preserved_blocks) + managed",
    "    if route_prefix == '/' and root_order == 'active':",
    "        replacement = site[:relative_open] + additions + site[relative_open:]",
    "    elif route_prefix == '/':",
    "        replacement = append_before_close(site, close_rel, additions)",
    "    else:",
    "        insert_at = fallback_insert_pos(site, relative_open, close_rel)",
    "        replacement = site[:insert_at] + additions + site[insert_at:]",
    "    text = text[:start] + replacement + text[stop:]",
    "config.write_text(text, encoding='utf-8')",
    "PY",
    "python_rc=$?",
    "validate_rc=1",
    "reload_rc=",
    "if [ \"$python_rc\" = 0 ]; then sudo caddy validate --config \"$next\" --adapter caddyfile >/tmp/web-probe-sentinel-caddy-validate.out 2>/tmp/web-probe-sentinel-caddy-validate.err; validate_rc=$?; fi",
    "if [ \"$validate_rc\" = 0 ]; then sudo install -m 0644 \"$next\" \"$config_path\" >/tmp/web-probe-sentinel-caddy-install.out 2>/tmp/web-probe-sentinel-caddy-install.err && (sudo systemctl reload \"$service\" >/tmp/web-probe-sentinel-caddy-reload.out 2>/tmp/web-probe-sentinel-caddy-reload.err || sudo systemctl restart \"$service\" >>/tmp/web-probe-sentinel-caddy-reload.out 2>>/tmp/web-probe-sentinel-caddy-reload.err); reload_rc=$?; fi",
    "probe_rc=1",
    "probe_status=",
    "if [ \"$reload_rc\" = 0 ]; then",
    "  probe_path=\"$route_prefix\"",
    "  if [ \"$probe_path\" = \"/\" ]; then probe_url=\"https://$hostname/\"; else probe_url=\"https://$hostname$probe_path/\"; fi",
    "  probe_status=$(curl -k -sS -o /tmp/web-probe-sentinel-caddy-probe.out -w '%{http_code}' --max-time 10 --resolve \"$hostname:443:127.0.0.1\" \"$probe_url\" 2>/tmp/web-probe-sentinel-caddy-probe.err)",
    "  probe_rc=$?",
    "fi",
    "after_present=no",
    "grep -Fq \"# BEGIN $marker\" \"$config_path\" 2>/dev/null && after_present=yes",
    "active=$(systemctl is-active \"$service\" 2>/dev/null || true)",
    "err=$(cat /tmp/web-probe-sentinel-caddy-python.err /tmp/web-probe-sentinel-caddy-validate.err /tmp/web-probe-sentinel-caddy-install.err /tmp/web-probe-sentinel-caddy-reload.err /tmp/web-probe-sentinel-caddy-probe.err 2>/dev/null | tr '\\n' ';' | cut -c1-1000 || true)",
    "python3 - \"$python_rc\" \"$validate_rc\" \"$reload_rc\" \"$probe_rc\" \"$probe_status\" \"$after_present\" \"$active\" \"$hostname\" \"$config_path\" \"$err\" <<'PY'",
    "import json, sys",
    "python_rc, validate_rc, reload_rc, probe_rc, probe_status, after_present, active, hostname, config_path, error_preview = sys.argv[1:11]",
    "def num(value):",
    "    if value == '':",
    "        return None",
    "    try:",
    "        return int(value)",
    "    except ValueError:",
    "        return None",
    "http_status = num(probe_status)",
    "probe_ok = num(probe_rc) == 0 and http_status is not None and 200 <= http_status < 400",
    "payload = {",
    "    'ok': num(python_rc) == 0 and num(validate_rc) == 0 and num(reload_rc) == 0 and probe_ok and after_present == 'yes',",
    "    'hostname': hostname,",
    "    'configPath': config_path,",
    "    'pythonExitCode': num(python_rc),",
    "    'validateExitCode': num(validate_rc),",
    "    'reloadExitCode': num(reload_rc),",
    "    'routeProbeExitCode': num(probe_rc),",
    "    'routeProbeHttpStatus': http_status,",
    "    'routeProbeOk': probe_ok,",
    "    'afterBlockPresent': after_present == 'yes',",
    "    'active': active,",
    "    'errorPreview': error_preview,",
    "    'valuesRedacted': True,",
    "}",
    "print(json.dumps(payload, ensure_ascii=False))",
    "PY",
  ].join("\n");
  const result = runCommand(["trans", stringAt(state.publicExposure, "caddy.route"), "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, routePrefix, rootOrder, ...record(parsed), result: compactCommand(result), valuesRedacted: true };
}

function readAnalysisSummaryFromWorkspace(state: SentinelCicdState, stateDir: string, timeoutSeconds: number): Record<string, unknown> {
  if (!isSafeRelativeStateDir(stateDir)) return { ok: false, reason: "unsafe-state-dir", stateDir, valuesRedacted: true };
  const script = [
    "set -eu",
    `state_dir=${shellQuote(stateDir)}`,
    "node - \"$state_dir\" <<'NODE'",
    "const fs=require('node:fs'); const path=require('node:path'); const crypto=require('node:crypto');",
    "const stateDir=process.argv[2]; const reportPath=path.join(stateDir,'analysis','report.json'); const reportMdPath=path.join(stateDir,'analysis','report.md');",
    "const read=(p)=>{try{return fs.readFileSync(p)}catch{return null}}; const jsonBuf=read(reportPath);",
    "const sha=(buf)=>buf?`sha256:${crypto.createHash('sha256').update(buf).digest('hex')}`:null;",
    "const rec=(v)=>v&&typeof v==='object'&&!Array.isArray(v)?v:{}; const arr=(v)=>Array.isArray(v)?v:[]; const clip=(v,n=180)=>v==null?null:String(v).slice(0,n);",
    "let report=null; try{report=jsonBuf?JSON.parse(jsonBuf.toString('utf8')):null}catch{}",
    "let artifactCount=0; let screenshot=null;",
    "function walk(dir){let entries=[]; try{entries=fs.readdirSync(dir,{withFileTypes:true})}catch{return}; for(const e of entries){const p=path.join(dir,e.name); if(e.isDirectory()) walk(p); else { artifactCount++; if(/\\.png$/i.test(e.name)){const b=read(p); screenshot={path:p,sha256:sha(b),bytes:b?b.length:0}; } } }}",
    "walk(stateDir);",
    "const findings=arr(report?.findings ?? report?.archiveSummary?.redFindings).slice(0,20).map((item)=>{const v=rec(item); return {id:clip(v.id??v.kind??v.code,80),kind:clip(v.kind??v.id??v.code,80),code:clip(v.code??v.kind??v.id,80),severity:clip(v.severity??v.level,32),level:clip(v.level??v.severity,32),count:Number(v.count??v.sampleCount??1),summary:clip(v.summary??v.message,220),message:clip(v.message??v.summary,220),rootCause:clip(v.rootCause,140),rootCauseStatus:clip(v.rootCauseStatus,90),rootCauseConfidence:clip(v.rootCauseConfidence,40),nextAction:clip(v.nextAction,240),evidenceSummary:v.evidence?clip(JSON.stringify(rec(v.evidence)),220):clip(v.evidenceSummary,220),blocking:v.blocking===true,afterRound:v.afterRound??null,canarySessionId:clip(v.canarySessionId,80),routeSessionId:clip(v.routeSessionId,80),activeSessionId:clip(v.activeSessionId,80),consecutiveUserMessageCount:v.consecutiveUserMessageCount??null,sentinelRange:clip(v.sentinelRange,80),sampleSeq:v.sampleSeq??null,traceIds:arr(v.traceIds).slice(0,8).map((x)=>clip(x,80)),pageRole:clip(v.pageRole,32),pageId:clip(v.pageId,80),observerId:clip(v.observerId,80),stateDir:clip(v.stateDir,160),commandId:clip(v.commandId,80),valuesRedacted:true};});",
    "const slow=arr(report?.pagePerformanceSlowApi ?? report?.archivePagePerformanceSlowApi).slice(0,8).map((item)=>{const v=rec(item); return {path:clip(v.path??v.route,120),sampleCount:v.sampleCount??null,p95Ms:v.p95Ms??null,maxMs:v.maxMs??null,overFiveSecondCount:v.overFiveSecondCount??null};});",
    "console.log(JSON.stringify({ok:!!report,reportOk:!!report&&report.ok!==false,stateDir,reportJsonPath:reportPath,reportJsonSha256:sha(jsonBuf),reportMdPath,reportMdSha256:sha(read(reportMdPath)),findingCount:Number(report?.findingCount??findings.length),artifactCount,screenshot,findings,counts:rec(report?.counts),analysisWindow:rec(report?.analysisWindow??report?.windows?.recent?.summary),pagePerformanceSlowApi:slow,valuesRedacted:true}));",
    "NODE",
  ].join("\n");
  const result = runCommand(["trans", `${state.spec.nodeId}:${state.spec.workspace}`, "sh"], repoRoot, { input: script, timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  const parsed = parseJsonObject(result.stdout);
  return { ok: result.exitCode === 0 && parsed?.ok === true, ...record(parsed), result: compactCommand(result), valuesRedacted: true };
}

function waitForQuickVerifyObserverStartup(state: SentinelCicdState, observerId: string, deadline: number, pollIntervalMs: number, budgetSeconds: number): Record<string, unknown> {
  const observations: Record<string, unknown>[] = [];
  const indexEntry = readLocalObserveIndex(observerId);
  if (indexEntry === null) {
    return {
      ok: false,
      failure: "observe-index-entry-missing",
      observerId,
      valuesRedacted: true,
    };
  }
  const pollSleepMs = Math.max(250, Math.min(500, Math.trunc(pollIntervalMs / 2) || 250));
  while (Date.now() < deadline) {
    const waitMs = Math.max(1000, Math.min(55_000, deadline - Date.now()));
    const script = quickVerifyObserverStartupWaitScript(indexEntry.stateDir, waitMs, pollSleepMs);
    const result = runCommand(["trans", `${state.spec.nodeId}:${state.spec.workspace}`, "sh"], repoRoot, { input: script, timeoutMs: waitMs + 5000 });
    const payload = parseJsonObject(result.stdout);
    if (Array.isArray(payload?.observations)) observations.push(...payload.observations.map(record));
    const terminalPayload = {
      observerId,
      stateDir: indexEntry.stateDir,
      status: typeof payload?.status === "string" ? payload.status : null,
      heartbeatStatus: typeof payload?.heartbeatStatus === "string" ? payload.heartbeatStatus : null,
      startup: record(payload?.startup),
      observations: observations.slice(-6),
      waitResult: compactCommand(result),
      valuesRedacted: true,
    };
    if (result.exitCode !== 0 || payload === null || payload.ok === false && payload.failure !== "quick-verify-startup-wait-chunk-timeout") {
      return {
        ok: false,
        failure: text(payload?.failure ?? "quick-verify-startup-artifact-wait-failed"),
        ...terminalPayload,
      };
    }
    if (payload.ok === true) return { ok: true, ...terminalPayload };
  }
  return {
    ok: false,
    failure: "quick-verify-timeout-over-budget",
    observerId,
    stateDir: indexEntry.stateDir,
    observations: observations.slice(-6),
    warnings: [`quick verify exceeded the configured ${budgetSeconds}s targetValidation budget while waiting for the observe runner startup to finish before sending the first command.`],
    valuesRedacted: true,
  };
}

function quickVerifyObserverStartupWaitScript(stateDir: string, timeoutMs: number, pollSleepMs: number): string {
  return [
    "set -eu",
    `state_dir=${shellQuote(stateDir)}`,
    `timeout_ms=${shellQuote(String(Math.max(1, Math.trunc(timeoutMs))))}`,
    `poll_ms=${shellQuote(String(Math.max(250, Math.trunc(pollSleepMs))))}`,
    "test -d \"$state_dir\" || { printf '{\"ok\":false,\"failure\":\"state-dir-missing\",\"stateDir\":\"%s\",\"valuesRedacted\":true}\\n' \"$state_dir\"; exit 0; }",
    "node - \"$state_dir\" \"$timeout_ms\" \"$poll_ms\" <<'NODE'",
    "const fs = require('node:fs');",
    "const path = require('node:path');",
    "const dir = process.argv[2];",
    "const timeoutMs = Number(process.argv[3]);",
    "const pollMs = Number(process.argv[4]);",
    "const startedAt = Date.now();",
    "const startupIds = ['startup-login', 'startup-goto', 'startup-observer-goto'];",
    "const readJson = (rel) => { try { return JSON.parse(fs.readFileSync(path.join(dir, rel), 'utf8')); } catch { return null; } };",
    "const readJsonl = (rel) => { try { return fs.readFileSync(path.join(dir, rel), 'utf8').split(/\\r?\\n/u).filter(Boolean).map((line) => { try { return JSON.parse(line); } catch { return null; } }).filter(Boolean); } catch { return []; } };",
    "const clip = (value, limit = 160) => value == null ? null : String(value).replace(/\\s+/gu, ' ').trim().slice(0, limit);",
    "const norm = (value) => String(value || '').trim().toLowerCase().replace(/_/gu, '-');",
    "const terminal = new Set(['failed', 'force-stopped', 'stopped', 'abandoned', 'completed']);",
    "function commandEvents(control, id) { return control.filter((item) => item && item.commandId === id); }",
    "function lastPhase(control, id) { return commandEvents(control, id).filter((item) => typeof item.phase === 'string').slice(-1)[0]?.phase || null; }",
    "function firstFailedStartup(control) { return control.filter((item) => item && startupIds.includes(item.commandId) && item.phase === 'failed').slice(-1)[0] || null; }",
    "function rowFor() {",
    "  const heartbeat = readJson('heartbeat.json') || {};",
    "  const manifest = readJson('manifest.json') || {};",
    "  const control = readJsonl('control.jsonl');",
    "  const phases = Object.fromEntries(startupIds.map((id) => [id, lastPhase(control, id)]));",
    "  const failed = firstFailedStartup(control);",
    "  const heartbeatStatus = norm(heartbeat.status || manifest.status);",
    "  const ready = startupIds.every((id) => phases[id] === 'completed') && heartbeatStatus === 'running';",
    "  const terminalBeforeReady = !ready && terminal.has(heartbeatStatus);",
    "  const degraded = control.filter((item) => item && item.type === 'observer-startup-degraded').slice(-1)[0] || null;",
    "  return {",
    "    ok: ready,",
    "    status: ready ? 'startup-ready' : terminalBeforeReady ? 'startup-terminal' : 'startup-waiting',",
    "    heartbeatStatus,",
    "    startup: { phases, failedCommandId: failed?.commandId || null, failedType: failed?.type || null, failedMessage: clip(failed?.detail?.error?.message || failed?.detail?.error || failed?.error?.message), observerStartupDegraded: !!degraded, degradedReason: clip(degraded?.reason || degraded?.result?.failureKind || degraded?.result?.reason), sampleSeq: heartbeat.sampleSeq ?? null, commandSeq: heartbeat.commandSeq ?? null, currentUrl: clip(heartbeat.currentUrl, 180), observerUrl: clip(heartbeat.observerUrl, 180), valuesRedacted: true },",
    "    valuesRedacted: true",
    "  };",
    "}",
    "const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));",
    "(async () => {",
    "  const observations = [];",
    "  while (Date.now() - startedAt <= timeoutMs) {",
    "    const row = rowFor();",
    "    observations.push(row);",
    "    if (row.ok === true) { console.log(JSON.stringify({ ok: true, ...row, observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    if (row.startup.failedCommandId) { console.log(JSON.stringify({ ok: false, failure: 'observer-startup-command-failed', ...row, observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    if (row.status === 'startup-terminal') { console.log(JSON.stringify({ ok: false, failure: 'observer-startup-terminal', ...row, observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    await sleep(Math.min(pollMs, Math.max(0, timeoutMs - (Date.now() - startedAt))));",
    "  }",
    "  const row = rowFor();",
    "  observations.push(row);",
    "  console.log(JSON.stringify({ ok: false, failure: 'quick-verify-startup-wait-chunk-timeout', ...row, observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true }));",
    "})().catch((error) => { console.log(JSON.stringify({ ok: false, failure: 'quick-verify-startup-wait-script-error', error: error instanceof Error ? error.message : String(error), valuesRedacted: true })); });",
    "NODE",
  ].join("\n");
}

function collectObserveView(state: SentinelCicdState, observerId: string, view: "turn-summary" | "trace-frame", turn: number | null, timeoutSeconds: number): Record<string, unknown> {
  const args = ["web-probe", "observe", "collect", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--view", view, "--command-timeout-seconds", String(Math.max(5, Math.min(timeoutSeconds, 55))), "--raw", "--compact-raw"];
  if (turn !== null) args.push("--turn", String(turn));
  const result = runChildCli(args, timeoutSeconds);
  const payload = cliDataPayload(result.parsed);
  const collect = record(payload.collect);
  return {
    ok: result.ok && result.parsed !== null && payload.ok !== false && collect.ok !== false,
    view,
    renderedText: typeof collect.renderedText === "string" ? collect.renderedText : typeof payload.renderedText === "string" ? payload.renderedText : String(record(result.result).stdoutTail ?? record(result.result).stdoutPreview ?? ""),
    collect,
    payload,
    result: result.result,
    valuesRedacted: true,
  };
}

function runChildCli(args: string[], timeoutSeconds: number, input?: string, env?: NodeJS.ProcessEnv): ChildCliResult {
  const result = runCommand(["bun", "scripts/cli.ts", ...args], repoRoot, {
    input,
    env: env === undefined ? undefined : { ...process.env, ...env },
    timeoutMs: Math.max(5, Math.min(timeoutSeconds, 120)) * 1000,
  });
  return {
    ok: result.exitCode === 0 && !result.timedOut,
    parsed: parseJsonObject(result.stdout),
    result: compactCommandWithTail(result),
  };
}

function waitForQuickVerifyPromptTurn(state: SentinelCicdState, observerId: string, promptIndex: number, deadline: number, pollIntervalMs: number, budgetSeconds: number, chunkSeconds = 45): Record<string, unknown> {
  const observations: Record<string, unknown>[] = [];
  const indexEntry = readLocalObserveIndex(observerId);
  if (indexEntry === null) {
    return {
      ok: false,
      failure: "observe-index-entry-missing",
      round: promptIndex,
      observerId,
      valuesRedacted: true,
    };
  }
  const pollSleepMs = Math.max(1000, Math.min(3000, Math.trunc(pollIntervalMs * 2) || 1000));
  while (Date.now() < deadline) {
    const waitMs = Math.max(1000, Math.min(Math.max(1000, Math.trunc(chunkSeconds * 1000)), deadline - Date.now()));
    const script = quickVerifyPromptWaitScript(indexEntry.stateDir, promptIndex, waitMs, pollSleepMs);
    const result = runCommand(["trans", `${state.spec.nodeId}:${state.spec.workspace}`, "sh"], repoRoot, { input: script, timeoutMs: waitMs + 8000 });
    const payload = parseJsonObject(result.stdout);
    if (Array.isArray(payload?.observations)) observations.push(...payload.observations.map(record));
    const status = typeof payload?.status === "string" ? payload.status : null;
    const terminalPayload = {
      round: promptIndex,
      status,
      traceId: payload?.traceId ?? null,
      finalResponseEmpty: payload?.finalResponseEmpty === true,
      composerReadyForTurn: payload?.composerReadyForTurn === true,
      composerAction: typeof payload?.composerAction === "string" ? payload.composerAction : null,
      observations: observations.slice(-6),
      waitResult: compactCommand(result),
      valuesRedacted: true,
    };
    if (result.exitCode !== 0 || payload === null || payload.ok === false && payload.failure !== "quick-verify-wait-chunk-timeout") {
      const fallback = quickVerifyTurnSummaryFallback(state, observerId, promptIndex);
      if (fallback.ok === true) {
        return {
          ok: true,
          ...terminalPayload,
          status: stringAtNullable(fallback, "status") ?? status,
          traceId: stringAtNullable(fallback, "traceId") ?? payload?.traceId ?? null,
          finalResponseEmpty: false,
          fallback,
          warnings: ["quick verify artifact wait command failed, but bounded turn-summary artifacts show this round completed; continuing validation."],
        };
      }
      return {
        ok: false,
        failure: text(payload?.failure ?? "quick-verify-artifact-wait-failed"),
        ...terminalPayload,
        fallback,
      };
    }
    if (payload.ok === false && payload.failure === "quick-verify-wait-chunk-timeout") {
      const fallback = quickVerifyTurnSummaryFallback(state, observerId, promptIndex);
      if (fallback.ok === true) {
        return {
          ok: true,
          ...terminalPayload,
          status: stringAtNullable(fallback, "status") ?? status,
          traceId: stringAtNullable(fallback, "traceId") ?? payload.traceId ?? null,
          finalResponseEmpty: false,
          fallback,
          warnings: ["quick verify wait chunk timed out, but bounded turn-summary artifacts show this round completed; continuing validation."],
        };
      }
    }
    if (payload.ok === true) return { ok: true, ...terminalPayload };
    if (isQuickVerifyTurnSuccessful(status)) {
      if (payload?.finalResponseEmpty !== true) return { ok: true, ...terminalPayload };
      continue;
    }
    if (isQuickVerifyTurnTerminal(status)) {
      return {
        ok: false,
        failure: "observe-turn-terminal-non-success",
        ...terminalPayload,
      };
    }
  }
  return {
    ok: false,
    failure: "quick-verify-timeout-over-budget",
    round: promptIndex,
    observations: observations.slice(-6),
    warnings: [`quick verify exceeded the configured ${budgetSeconds}s targetValidation budget while waiting for a submitted turn to become terminal; investigate Code Agent multi-round continuity before retrying.`],
    valuesRedacted: true,
  };
}

function quickVerifyPromptWaitScript(stateDir: string, promptIndex: number, timeoutMs: number, pollSleepMs: number): string {
  return [
    "set -eu",
    `state_dir=${shellQuote(stateDir)}`,
    `prompt_index=${shellQuote(String(promptIndex))}`,
    `timeout_ms=${shellQuote(String(Math.max(1, Math.trunc(timeoutMs))))}`,
    `poll_ms=${shellQuote(String(Math.max(250, Math.trunc(pollSleepMs))))}`,
    "test -d \"$state_dir\" || { printf '{\"ok\":false,\"failure\":\"state-dir-missing\",\"stateDir\":\"%s\",\"valuesRedacted\":true}\\n' \"$state_dir\"; exit 0; }",
    "node - \"$state_dir\" \"$prompt_index\" \"$timeout_ms\" \"$poll_ms\" <<'NODE'",
    "const fs = require('node:fs');",
    "const path = require('node:path');",
    "const dir = process.argv[2];",
    "const promptIndex = Number(process.argv[3]);",
    "const timeoutMs = Number(process.argv[4]);",
    "const pollMs = Number(process.argv[5]);",
    "const startedAt = Date.now();",
    "const short = (value, limit = 160) => String(value || '').replace(/\\s+/gu, ' ').trim().slice(0, limit);",
    "const textOf = (value) => String(value?.text || value?.textPreview || value?.preview || '');",
    "const arr = (value) => Array.isArray(value) ? value : [];",
    "const unique = (values) => Array.from(new Set(values.filter(Boolean)));",
    "const numOrNull = (value) => { const n = Number(value); return Number.isFinite(n) ? n : null; };",
    "const tsMs = (value) => { const ms = Date.parse(String(value || '')); return Number.isFinite(ms) ? ms : null; };",
    "const readJson = (rel) => { try { return JSON.parse(fs.readFileSync(path.join(dir, rel), 'utf8')); } catch { return null; } };",
    "const readJsonl = (rel) => { try { return fs.readFileSync(path.join(dir, rel), 'utf8').split(/\\r?\\n/u).filter(Boolean).map((line) => { try { return JSON.parse(line); } catch { return null; } }).filter(Boolean); } catch { return []; } };",
    "const readJsonlTail = (rel, maxBytes = 2000000) => {",
    "  try {",
    "    const file = path.join(dir, rel);",
    "    const stat = fs.statSync(file);",
    "    const start = Math.max(0, stat.size - maxBytes);",
    "    const length = stat.size - start;",
    "    const fd = fs.openSync(file, 'r');",
    "    try {",
    "      const buffer = Buffer.alloc(length);",
    "      fs.readSync(fd, buffer, 0, length, start);",
    "      const lines = buffer.toString('utf8').split(/\\r?\\n/u);",
    "      if (start > 0) lines.shift();",
    "      return lines.filter(Boolean).map((line) => { try { return JSON.parse(line); } catch { return null; } }).filter(Boolean);",
    "    } finally {",
    "      fs.closeSync(fd);",
    "    }",
    "  } catch {",
    "    return [];",
    "  }",
    "};",
    "const readDone = (id) => id ? readJson(path.join('commands', 'done', `${id}.json`)) : null;",
    "const readFailed = (id) => id ? readJson(path.join('commands', 'failed', `${id}.json`)) : null;",
    "function sessionIdFromUrl(value) { const match = String(value || '').match(/\\/workbench\\/sessions\\/(ses_[A-Za-z0-9_-]+)/u); return match ? match[1] : null; }",
    "function commandSessionId(item) { const done = readDone(item?.commandId); return item?.sessionId || item?.detail?.sessionId || item?.input?.sessionId || item?.result?.sessionId || done?.result?.sessionId || done?.result?.observer?.sessionId || sessionIdFromUrl(item?.afterUrl) || sessionIdFromUrl(item?.detail?.afterUrl) || sessionIdFromUrl(done?.result?.afterUrl) || null; }",
    "function commandTextHash(item) { const done = readDone(item?.commandId); return item?.detail?.textHash || item?.input?.textHash || item?.result?.textHash || done?.result?.textHash || null; }",
    "function firstTraceId(value) { const match = String(value || '').match(/\\btrc_[A-Za-z0-9_-]+\\b/u); return match ? match[0] : null; }",
    "function commandTraceId(item) { const done = readDone(item?.commandId); return item?.traceId || item?.detail?.chatSubmit?.traceId || item?.detail?.traceId || item?.input?.traceId || item?.result?.chatSubmit?.traceId || done?.result?.chatSubmit?.traceId || done?.result?.traceId || null; }",
    "function itemTraceId(item) { return item?.traceId || firstTraceId(textOf(item)) || null; }",
    "function completedNewSessionIdsBefore(control, ts) { const limit = tsMs(ts); return control.filter((item) => item.type === 'newSession' && item.phase === 'completed').filter((item) => limit === null || tsMs(item.ts) === null || tsMs(item.ts) <= limit).map(commandSessionId).filter(Boolean); }",
    "function authoritativeSessionIdForPrompts(control, prompts) { const ids = completedNewSessionIdsBefore(control, prompts[0]?.firstTs || null); return ids.slice(-1)[0] || unique(prompts.map((item) => item.sessionId))[0] || null; }",
    "function promptCommands(control) {",
    "  const map = new Map();",
    "  for (const item of control) {",
    "    if (item.type !== 'sendPrompt' || !['started', 'completed', 'failed'].includes(item.phase)) continue;",
    "    const id = item.commandId || item.seq || String(map.size + 1);",
    "    const existing = map.get(id) || {};",
    "    map.set(id, { ...existing, ...item, input: { ...(existing.input || {}), ...(item.input || {}) }, sessionId: existing.sessionId || commandSessionId(item), traceId: existing.traceId || commandTraceId(item), textHash: existing.textHash || commandTextHash(item), firstTs: existing.firstTs || item.ts, lastTs: item.ts });",
    "  }",
    "  const prompts = Array.from(map.values()).filter((item) => tsMs(item.firstTs) !== null).sort((a, b) => tsMs(a.firstTs) - tsMs(b.firstTs));",
    "  const sessionId = authoritativeSessionIdForPrompts(control, prompts);",
    "  if (!sessionId) return prompts;",
    "  const scoped = prompts.filter((item) => item.sessionId === sessionId);",
    "  return scoped.length > 0 ? scoped : prompts;",
    "}",
    "function segmentFor(samples, prompts, index) { const start = tsMs(prompts[index]?.firstTs); const end = index + 1 < prompts.length ? tsMs(prompts[index + 1].firstTs) : Infinity; return samples.filter((sample) => { const ms = tsMs(sample.ts); return ms !== null && ms >= start && ms < end; }); }",
    "function entryGroups(sample) { return [...arr(sample.turns).map((item) => ({ group: 'turn', item })), ...arr(sample.traceRows).map((item) => ({ group: 'traceRow', item })), ...arr(sample.messages).map((item) => ({ group: 'message', item }))]; }",
    "function traceIdsFromSamples(items) { const ids = []; for (const sample of items) for (const entry of entryGroups(sample)) { const id = itemTraceId(entry.item); if (id) ids.push(id); } return unique(ids); }",
    "function chooseTraceId(segment, prompt) { const promptTraceId = commandTraceId(prompt) || prompt?.traceId || null; const ids = traceIdsFromSamples(segment); if (promptTraceId && (ids.length === 0 || ids.includes(promptTraceId))) return promptTraceId; return ids.slice(-1)[0] || promptTraceId || null; }",
    "function traceIdForPromptUserMessage(items, prompt) {",
    "  const hash = prompt?.textHash || commandTextHash(prompt);",
    "  if (!hash) return null;",
    "  for (const sample of items) {",
    "    for (const message of arr(sample.messages)) {",
    "      const role = String(message?.role || message?.dataRole || message?.messageRole || '').toLowerCase();",
    "      if (role && !/user/u.test(role)) continue;",
    "      if (message?.textHash === hash) {",
    "        const id = itemTraceId(message);",
    "        if (id) return id;",
    "      }",
    "    }",
    "  }",
    "  return null;",
    "}",
    "function traceEntries(items, traceId) { const entries = []; for (const sample of items) for (const entry of entryGroups(sample)) { const text = textOf(entry.item); const id = itemTraceId(entry.item); if (!traceId || id === traceId || text.includes(traceId)) entries.push({ ...entry, sample, text }); } return entries; }",
    "function normalizeLifecycleStatus(value) { const raw = String(value || '').trim().toLowerCase(); if (/^(canceled|cancelled)$/u.test(raw)) return 'canceled'; if (/^(failed|failure|error)$/u.test(raw)) return 'failed'; if (/^(completed|complete|succeeded|success|terminal)$/u.test(raw)) return 'completed'; if (/^(running|admitting|queued|pending|in_progress|in-progress)$/u.test(raw)) return 'running'; return null; }",
    "function statusFor(items, traceId) { const entries = traceId ? traceEntries(items, traceId) : items.flatMap((sample) => entryGroups(sample).map((entry) => ({ ...entry, sample, text: textOf(entry.item) }))); const lastTurn = entries.filter((entry) => entry.group === 'turn').slice(-1)[0]?.item || null; const turnStatus = normalizeLifecycleStatus(lastTurn?.status); if (turnStatus) return turnStatus; const lastMessage = entries.filter((entry) => entry.group === 'message').slice(-1)[0]?.item || null; return normalizeLifecycleStatus(lastMessage?.status) || 'unknown'; }",
    "function cleanFinalResponseText(value) { const raw = String(value || '').trim(); if (!raw) return ''; if (/^(completed|failed|canceled|cancelled|轮次完成|轮次失败|轮次取消|已记录)$/iu.test(raw.replace(/\\s+/gu, ' '))) return ''; if (/^(admitted|run|ok|error)\\s+/iu.test(raw)) return ''; return raw; }",
    "function finalResponseTextFromEntry(entry) {",
    "  const explicit = cleanFinalResponseText(entry.item?.finalResponse?.text || entry.item?.finalResponse?.preview || '');",
    "  if (explicit && !/^Code Agent\\s*耗时/iu.test(explicit)) return explicit;",
    "  if (entry.group !== 'message') return '';",
    "  const role = String(entry.item?.role || entry.item?.dataRole || entry.item?.messageRole || '').toLowerCase();",
    "  if (role && !/assistant|agent|system/u.test(role)) return '';",
    "  const text = cleanFinalResponseText(entry.text);",
    "  return text && !/^Code Agent\\s*耗时/iu.test(text) ? text : '';",
    "}",
    "function finalResponseEmpty(items, traceId) { if (!/^(completed|failed|canceled)$/u.test(statusFor(items, traceId))) return true; const entries = (traceId ? traceEntries(items, traceId) : items.flatMap((sample) => entryGroups(sample).map((entry) => ({ ...entry, sample, text: textOf(entry.item) })))).slice().reverse(); for (const entry of entries) { if (finalResponseTextFromEntry(entry)) return false; } return true; }",
    "function rowFor() {",
    "  const control = readJsonl('control.jsonl');",
    "  const samples = readJsonlTail('samples.jsonl');",
    "  const prompts = promptCommands(control);",
    "  const prompt = prompts[promptIndex - 1] || null;",
    "  if (!prompt) return { ok: true, round: promptIndex, status: 'command-pending', traceId: null, finalResponseEmpty: true, lastSeq: null, lastTs: null, promptMissing: true, valuesRedacted: true };",
    "  const done = readDone(prompt.commandId);",
    "  const failed = readFailed(prompt.commandId);",
    "  if (failed) return { ok: false, failure: 'observe-command-sendPrompt-failed', round: promptIndex, status: 'command-failed', commandId: prompt.commandId || null, traceId: null, finalResponseEmpty: true, commandFailure: short(failed.error?.message || failed.failure || failed.status || 'command failed'), valuesRedacted: true };",
    "  const promptTraceId = commandTraceId(prompt);",
    "  if (!done) return { ok: true, round: promptIndex, status: 'command-pending', commandId: prompt.commandId || null, traceId: promptTraceId || null, finalResponseEmpty: true, commandPhase: prompt.phase || null, traceMissing: !promptTraceId, valuesRedacted: true };",
    "  const segment = segmentFor(samples, prompts, promptIndex - 1);",
    "  const controlSegment = segment.filter((sample) => sample.pageRole === 'control');",
    "  const traceId = promptTraceId || traceIdForPromptUserMessage(segment, prompt) || chooseTraceId(controlSegment, prompt) || chooseTraceId(segment, prompt);",
    "  if (!traceId) return { ok: true, round: promptIndex, status: 'command-pending', commandId: prompt.commandId || null, traceId: null, finalResponseEmpty: true, commandPhase: prompt.phase || null, traceMissing: true, segmentSampleCount: segment.length, valuesRedacted: true };",
    "  const controlTraceSegment = traceId ? controlSegment.filter((sample) => traceIdsFromSamples([sample]).includes(traceId)) : [];",
    "  const statusSegment = controlTraceSegment.length > 0 ? controlSegment : segment;",
    "  const status = statusFor(statusSegment, traceId);",
    "  const sampleForTrace = traceId ? statusSegment.filter((sample) => traceIdsFromSamples([sample]).includes(traceId)).slice(-1)[0] || segment.filter((sample) => traceIdsFromSamples([sample]).includes(traceId)).slice(-1)[0] || null : null;",
    "  const lastSample = sampleForTrace || segment.slice(-1)[0] || null;",
    "  const composerSample = segment.filter((sample) => sample.pageRole === 'control').slice(-1)[0] || lastSample;",
    "  const composer = composerSample?.composer || {};",
    "  const composerReadyForTurn = composer.inputPresent === true && composer.inputDisabled !== true && composer.submitPresent === true && composer.warningPresent !== true && composer.submitAction === 'turn';",
    "  return { ok: true, round: promptIndex, status, traceId, finalResponseEmpty: finalResponseEmpty(statusSegment, traceId), lastSeq: numOrNull(lastSample?.seq), lastTs: lastSample?.ts || null, composerReadyForTurn, composerAction: composer.submitAction || null, sampleScope: controlSegment.length > 0 ? 'control' : 'all', segmentSampleCount: segment.length, statusSampleCount: statusSegment.length, source: 'observe-artifact-wait-script', valuesRedacted: true };",
    "}",
    "function norm(value) { return String(value || '').trim().toLowerCase().replace(/_/gu, '-'); }",
    "function successful(value) { return ['completed', 'succeeded', 'success'].includes(norm(value)); }",
    "function terminal(value) { return ['completed', 'succeeded', 'success', 'failed', 'error', 'blocked', 'timeout', 'canceled', 'cancelled', 'terminal'].includes(norm(value)); }",
    "const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));",
    "(async () => {",
    "  const observations = [];",
    "  while (Date.now() - startedAt <= timeoutMs) {",
    "    const row = rowFor();",
    "    observations.push(row);",
    "    if (row.ok === false) { console.log(JSON.stringify({ ...row, ok: false, failure: row.failure || 'quick-verify-artifact-row-failed', observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    if (successful(row.status) && row.finalResponseEmpty !== true) { console.log(JSON.stringify({ ...row, ok: true, observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    if (!successful(row.status) && terminal(row.status)) { console.log(JSON.stringify({ ...row, ok: false, failure: 'observe-turn-terminal-non-success', observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true })); return; }",
    "    await sleep(Math.min(pollMs, Math.max(0, timeoutMs - (Date.now() - startedAt))));",
    "  }",
    "  const row = rowFor();",
    "  observations.push(row);",
    "  console.log(JSON.stringify({ ...row, ok: false, failure: 'quick-verify-wait-chunk-timeout', observations: observations.slice(-6), elapsedMs: Date.now() - startedAt, valuesRedacted: true }));",
    "})().catch((error) => { console.log(JSON.stringify({ ok: false, failure: 'quick-verify-artifact-wait-script-error', error: error instanceof Error ? error.message : String(error), valuesRedacted: true })); });",
    "NODE",
  ].join("\n");
}

function isQuickVerifyTurnSuccessful(value: string | null): boolean {
  const status = normalizeQuickVerifyStatus(value);
  return status === "completed" || status === "succeeded" || status === "success";
}

function isQuickVerifyTurnTerminal(value: string | null): boolean {
  const status = normalizeQuickVerifyStatus(value);
  return status === "completed"
    || status === "succeeded"
    || status === "success"
    || status === "failed"
    || status === "error"
    || status === "blocked"
    || status === "timeout"
    || status === "canceled"
    || status === "cancelled"
    || status === "terminal";
}

function normalizeQuickVerifyStatus(value: string | null): string {
  return String(value ?? "").trim().toLowerCase().replace(/_/gu, "-");
}

function cliDataPayload(parsed: Record<string, unknown> | null): Record<string, unknown> {
  const root = record(parsed);
  const payload = isRecord(root.data) ? root.data : root;
  return cliDumpPayload(payload) ?? payload;
}

function cliDumpPayload(payload: Record<string, unknown>): Record<string, unknown> | null {
  if (payload.outputTruncated !== true) return null;
  const dumpPath = stringAtNullable(record(payload.dump), "path");
  if (dumpPath === null || !existsSync(dumpPath)) return null;
  const dumped = parseJsonObject(readFileSync(dumpPath, "utf8"));
  if (dumped === null) return null;
  const dumpedRoot = record(dumped);
  return isRecord(dumpedRoot.data) ? dumpedRoot.data : dumpedRoot;
}

function findScenario(state: SentinelCicdState, scenarioId: string): Record<string, unknown> | null {
  const scenarios = readConfigRefTarget(state.configRefs.scenarios);
  const items = Array.isArray(scenarios) ? scenarios : isRecord(scenarios) ? [scenarios] : [];
  return items.map(record).find((item) => item.id === scenarioId) ?? null;
}

function readPromptSetForScenario(scenario: Record<string, unknown>): { ok: true; prompts: string[]; summary: Record<string, unknown> } | { ok: false; error: string; summary: Record<string, unknown> } {
  const promptSet = recordTarget(readConfigRefTarget(stringAt(scenario, "promptSetRef")), stringAt(scenario, "promptSetRef"));
  const sourceRef = stringAt(promptSet, "promptSourceRef");
  const key = stringAt(promptSet, "promptSourceKey");
  const paths = secretSourcePaths(sourceRef);
  const sourcePath = paths.find((item) => existsSync(item)) ?? paths[0] ?? join(repoRoot, ".state", "secrets", sourceRef);
  const summary = { sourceRef, sourceKey: key, sourcePath: displayPath(sourcePath), valuesRedacted: true };
  const runtimeRaw = process.env[key];
  const values = existsSync(sourcePath) ? parseEnvFile(readFileSync(sourcePath, "utf8")) : {};
  const raw = values[key] ?? runtimeRaw;
  const sourceMode = values[key] !== undefined ? "secret-source-file" : runtimeRaw !== undefined && runtimeRaw.length > 0 ? "runtime-env" : null;
  if (!existsSync(sourcePath) && sourceMode === null) return { ok: false, error: "prompt-source-missing", summary };
  if (raw === undefined || raw.length === 0) return { ok: false, error: "prompt-key-missing", summary };
  const parsed = parsePromptJson(raw);
  if (parsed.length === 0) return { ok: false, error: "prompt-json-empty", summary };
  return {
    ok: true,
    prompts: parsed,
    summary: {
      ...summary,
      sourceMode,
      promptCount: parsed.length,
      promptMarkers: parsed.map((item) => Array.from(new Set(Array.from(item.matchAll(/\bsentinel-(?:0[1-9]|10)\b/giu)).map((match) => match[0].toLowerCase())))),
      promptTextHashes: parsed.map((item) => `sha256:${createHash("sha256").update(item).digest("hex").slice(0, 16)}`),
      promptTextBytes: parsed.map((item) => Buffer.byteLength(item)),
      valuesRedacted: true,
    },
  };
}

function parsePromptJson(raw: string): string[] {
  try {
    const parsed = JSON.parse(raw) as unknown;
    if (Array.isArray(parsed)) return parsed.filter((item): item is string => typeof item === "string" && item.length > 0);
    const recordValue = record(parsed);
    if (Array.isArray(recordValue.prompts)) return recordValue.prompts.filter((item): item is string => typeof item === "string" && item.length > 0);
    if (typeof recordValue.prompt === "string" && recordValue.prompt.length > 0) return [recordValue.prompt];
  } catch {
    if (raw.trim().length > 0) return [raw];
  }
  return [];
}

function readLocalObserveIndex(observerId: string): { stateDir: string } | null {
  const path = rootPath(".state/web-observe/index.json");
  if (!existsSync(path)) return null;
  const parsed = parseJsonObject(readFileSync(path, "utf8"));
  const entry = record(parsed?.[observerId]);
  const stateDir = typeof entry.stateDir === "string" ? entry.stateDir : null;
  return stateDir === null ? null : { stateDir };
}

function secretSourcePaths(sourceRef: string): string[] {
  const paths = [join(repoRoot, ".state", "secrets", sourceRef)];
  const marker = "/.worktree/";
  const index = repoRoot.indexOf(marker);
  if (index >= 0) paths.push(join(repoRoot.slice(0, index), ".state", "secrets", sourceRef));
  return [...new Set(paths)];
}

function parseEnvFile(textValue: string): Record<string, string> {
  const values: Record<string, string> = {};
  for (const rawLine of textValue.split(/\r?\n/u)) {
    const line = rawLine.trim();
    if (line.length === 0 || line.startsWith("#")) continue;
    const index = line.indexOf("=");
    if (index <= 0) continue;
    const key = line.slice(0, index).trim();
    let value = line.slice(index + 1).trim();
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) value = value.slice(1, -1);
    values[key] = value;
  }
  return values;
}

function observerIdFromText(textValue: string): string | null {
  return /\bwebobs-[a-z0-9-]+\b/iu.exec(textValue)?.[0] ?? null;
}

function remainingSeconds(deadline: number, cap: number): number {
  return Math.max(5, Math.min(cap, Math.ceil((deadline - Date.now()) / 1000)));
}

function metricNames(textValue: unknown): string[] {
  if (typeof textValue !== "string") return [];
  return textValue.split(/\r?\n/u).map((line) => /^([A-Za-z_:][A-Za-z0-9_:]*)/u.exec(line)?.[1]).filter((item): item is string => typeof item === "string");
}

function validationBlocker(health: Record<string, unknown>, metrics: Record<string, unknown>, report: Record<string, unknown>, publicExposure: Record<string, unknown>, publicDashboard: Record<string, unknown>, quickVerify: Record<string, unknown> | null): Record<string, unknown> {
  const blockers = [];
  if (!health.ok || record(health.bodyJson).ok !== true) blockers.push("health");
  if (!metrics.ok || !metricNames(metrics.bodyTextPreview).includes("web_probe_sentinel_health")) blockers.push("metrics");
  if (!report.ok) blockers.push("recent-report");
  if (publicExposure.ok !== true) blockers.push("public-exposure");
  if (publicDashboard.ok !== true) blockers.push("public-dashboard");
  if (quickVerify !== null && quickVerify.ok !== true) blockers.push("quick-verify");
  return { code: "sentinel-validation-failed", blockers, valuesRedacted: true };
}

function serviceUnavailableBlocker(state: SentinelCicdState): Record<string, unknown> {
  return {
    code: "sentinel-service-unavailable",
    policy: stringAt(state.cicd, "targetValidation.serviceUnavailablePolicy"),
    reason: "sentinel service must be reachable through k3s internal Service DNS before quick verify can run; no public/fallback path is used.",
    retry: `bun scripts/cli.ts web-probe sentinel validate --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)}`,
    valuesRedacted: true,
  };
}

function sentinelP5Next(state: SentinelCicdState): Record<string, string> {
  const node = state.spec.nodeId;
  const lane = state.spec.lane;
  const suffix = sentinelCliSuffix(state);
  return {
    validate: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane}${suffix}`,
    quickVerify: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane}${suffix} --quick-verify --confirm --wait`,
    maintenanceStart: `bun scripts/cli.ts web-probe sentinel maintenance start --node ${node} --lane ${lane}${suffix} --confirm --wait`,
    maintenanceStop: `bun scripts/cli.ts web-probe sentinel maintenance stop --node ${node} --lane ${lane}${suffix} --confirm --wait`,
    report: `bun scripts/cli.ts web-probe sentinel report --node ${node} --lane ${lane}${suffix} --view summary`,
  };
}

function isSafeRelativeStateDir(value: string): boolean {
  return value.startsWith(".state/web-observe/") && !value.includes("\0") && !value.includes("..");
}

function stringAtNullable(value: unknown, path: string): string | null {
  const found = valueAtPath(value, path);
  return typeof found === "string" && found.length > 0 ? found : null;
}

function numberAtNullable(value: unknown, path: string): number | null {
  const found = valueAtPath(value, path);
  return typeof found === "number" && Number.isFinite(found) ? found : null;
}

function displayPath(pathValue: string): string {
  if (pathValue.startsWith(`${repoRoot}/`)) return pathValue.slice(repoRoot.length + 1);
  const marker = "/.worktree/";
  const index = repoRoot.indexOf(marker);
  if (index >= 0) {
    const mainRoot = repoRoot.slice(0, index);
    if (pathValue.startsWith(`${mainRoot}/`)) return pathValue.slice(mainRoot.length + 1);
  }
  return pathValue;
}

function mergeFindingRecords(primary: readonly Record<string, unknown>[], extra: readonly Record<string, unknown>[]): Record<string, unknown>[] {
  const merged: Record<string, unknown>[] = [];
  const seen = new Set<string>();
  for (const item of [...primary, ...extra]) {
    const id = stringAtNullable(item, "id") ?? stringAtNullable(item, "kind") ?? stringAtNullable(item, "code") ?? stringAtNullable(item, "finding_id") ?? "finding";
    const severity = stringAtNullable(item, "severity") ?? stringAtNullable(item, "level") ?? "unknown";
    const key = `${id}\0${severity}`;
    if (seen.has(key)) continue;
    seen.add(key);
    merged.push(item);
  }
  return merged;
}

function isQuickVerifyBlockingFinding(item: Record<string, unknown>): boolean {
  const severity = (stringAtNullable(item, "severity") ?? stringAtNullable(item, "level") ?? "").toLowerCase();
  if (!["critical", "red", "fatal", "error", "failed", "blocked"].includes(severity)) return false;
  const id = (stringAtNullable(item, "id") ?? stringAtNullable(item, "kind") ?? stringAtNullable(item, "code") ?? "").toLowerCase();
  if (id === "observer-command-failed") return observerCommandFailureBlocks(item);
  return [
    "quick-verify-no-business-turn",
    "quick-verify-command-sequence-failed",
    "quick-verify-observer-start-failed",
    "quick-verify-account-secret-missing",
    "prompt-chat-submit-failed",
    "route-active-session-mismatch",
    "final-response-flicker",
    "round-completion-final-response-missing",
    "turn-trace-id-missing",
    "no-samples",
    "jsonl-read-issues",
  ].includes(id);
}

function observerCommandFailureBlocks(item: Record<string, unknown>): boolean {
  const commands = Array.isArray(item.commands) ? item.commands.map(record) : [];
  if (commands.length === 0) return true;
  return commands.some((command) => {
    const type = (stringAtNullable(command, "type") ?? "").toLowerCase();
    if (["stop", "cancel", "mark", "screenshot"].includes(type)) return false;
    return true;
  });
}

function quickVerifyControlFindings(failure: string | null, promptIndex: number, turnSummary: Record<string, unknown> | null, traceFrame: Record<string, unknown> | null): Record<string, unknown>[] {
  if (quickVerifyHasDurableBusinessTurn(promptIndex, turnSummary, traceFrame)) return [];
  const rendered = [
    typeof turnSummary?.renderedText === "string" ? turnSummary.renderedText : "",
    typeof traceFrame?.renderedText === "string" ? traceFrame.renderedText : "",
  ].join("\n");
  const noPromptScenario = promptIndex <= 0;
  if (noPromptScenario && failure === null) return [];
  if (noPromptScenario && failure !== null) {
    const observerStartFailure = failure === "observe-start-failed";
    return [{
      id: observerStartFailure ? "quick-verify-observer-start-failed" : "quick-verify-command-sequence-failed",
      severity: "red",
      count: 1,
      summary: observerStartFailure
        ? "quick verify observer failed to start before the no-prompt scenario could run."
        : "quick verify no-prompt command sequence failed before the account/session workflow completed.",
      failure,
      promptIndex,
      valuesRedacted: true,
    }];
  }
  const noTrace = /无\s*sendPrompt|no\s+sendPrompt|无\s*trace\s*rows|no\s+trace\s+rows|traceId=-|routeSession=-|activeSession=-/iu.test(rendered);
  const emptyFinal = /Final Response[\s\S]*\(空内容\)/iu.test(rendered);
  if (!noTrace && !emptyFinal && failure !== "observe-start-failed") return [];
  return [{
    id: "quick-verify-no-business-turn",
    severity: "red",
    count: 1,
    summary: "quick verify did not reach a durable business turn/session/trace rows/final response; public dashboard health cannot be treated as HWLAB recovery.",
    failure: failure ?? null,
    promptIndex,
    valuesRedacted: true,
  }];
}

function quickVerifyCompletedTurnSummaryRow(promptIndex: number, turnSummary: Record<string, unknown> | null): Record<string, unknown> | null {
  const rows = Array.isArray(record(turnSummary?.collect).rows) ? record(turnSummary?.collect).rows.map(record) : [];
  const scopedRows = promptIndex > 0 ? rows.filter((row) => numberAtNullable(row, "round") === promptIndex) : rows;
  return scopedRows.find((row) => {
    const finalResponse = record(row.finalResponse);
    return isQuickVerifyTurnSuccessful(stringAtNullable(row, "status"))
      && stringAtNullable(row, "traceId") !== null
      && finalResponse.empty !== true;
  }) ?? null;
}

function quickVerifyTurnSummaryFallback(state: SentinelCicdState, observerId: string, promptIndex: number): Record<string, unknown> {
  const turnSummary = collectObserveView(state, observerId, "turn-summary", null, 25);
  const row = quickVerifyCompletedTurnSummaryRow(promptIndex, turnSummary);
  const rows = Array.isArray(record(turnSummary.collect).rows) ? record(turnSummary.collect).rows.map(record) : [];
  if (row === null) {
    return {
      ok: false,
      source: "turn-summary-fallback",
      collectOk: turnSummary.ok === true,
      rowCount: rows.length,
      promptIndex,
      result: turnSummary.result ?? null,
      valuesRedacted: true,
    };
  }
  const finalResponse = record(row.finalResponse);
  return {
    ok: true,
    source: "turn-summary-fallback",
    collectOk: turnSummary.ok === true,
    rowCount: rows.length,
    promptIndex,
    status: stringAtNullable(row, "status"),
    traceId: stringAtNullable(row, "traceId"),
    finalResponseEmpty: finalResponse.empty === true,
    finalResponseBytes: numberAtNullable(finalResponse, "textBytes"),
    result: turnSummary.result ?? null,
    valuesRedacted: true,
  };
}

function quickVerifyHasDurableBusinessTurn(promptIndex: number, turnSummary: Record<string, unknown> | null, traceFrame: Record<string, unknown> | null): boolean {
  if (quickVerifyCompletedTurnSummaryRow(promptIndex, turnSummary) !== null) return true;
  const renderedTrace = typeof traceFrame?.renderedText === "string" ? traceFrame.renderedText : "";
  if (!renderedTrace) return false;
  if (/Final Response\s*\n\s*\(空内容\)/iu.test(renderedTrace)) return false;
  return /Code Agent[^\n]*completed|轮次完成（总耗时/iu.test(renderedTrace)
    && /Final Response\s*\n\s*\S/iu.test(renderedTrace)
    && !/无\s*trace\s*rows|no\s+trace\s+rows|traceId=-|routeSession=-|activeSession=-/iu.test(renderedTrace);
}

function isRecoverableQuickVerifyWaitFailure(failure: string): boolean {
  return failure === "quick-verify-wait-chunk-timeout"
    || failure === "quick-verify-timeout-over-budget"
    || failure === "observe-turn-terminal-wait-failed";
}

function compactCommandWithTail(result: CommandResult): CompactCommandResult & { stdoutTail: string; stderrTail: string } {
  return {
    ...compactCommand(result),
    stdoutPreview: result.stdout.trim().slice(0, 1200),
    stderrPreview: result.stderr.trim().slice(0, 1200),
    stdoutTail: result.stdout.trim().slice(-4000),
    stderrTail: result.stderr.trim().slice(-4000),
  };
}

function renderQuickVerifySummary(input: Record<string, unknown>): string {
  const artifact = record(input.artifactSummary);
  const findings = Array.isArray(artifact.findings) ? artifact.findings.map(record).slice(0, 8) : [];
  return [
    "Web Probe Sentinel Quick Verify",
    "=======================================================",
    `run=${input.runId ?? "-"} scenario=${input.scenarioId ?? "-"} observer=${input.observerId ?? "-"}`,
    `report=${artifact.reportJsonSha256 ?? "-"} artifacts=${artifact.artifactCount ?? "-"} findings=${artifact.findingCount ?? findings.length}`,
    `publicOrigin=${input.publicOrigin ?? "-"}`,
    "",
    "Findings",
    findings.length === 0 ? "-" : findings.map((item) => `${item.severity ?? item.level ?? "-"} ${item.kind ?? item.id ?? item.code ?? "-"} count=${item.count ?? "-"} ${item.summary ?? item.message ?? ""}`).join("\n"),
  ].join("\n");
}

function renderAuthSessionSwitchQuickVerifySummary(input: Record<string, unknown>): string {
  const artifact = record(input.artifactSummary);
  const accountEnv = record(input.accountEnv);
  const findingRows = Array.isArray(input.findings)
    ? input.findings.map(record).slice(0, 8)
    : Array.isArray(artifact.findings)
      ? artifact.findings.map(record).slice(0, 8)
      : [];
  const steps = Array.isArray(input.steps) ? input.steps.map(record) : [];
  const commandSteps = steps
    .filter((step) => {
      const phase = stringAtNullable(step, "phase") ?? "";
      return phase.startsWith("observe-command-") || phase.startsWith("observe-session-invariance-") || phase === "quick-verify-account-env";
    })
    .map((step) => {
      const phase = stringAtNullable(step, "phase") ?? "-";
      const ok = step.ok === true ? "ok" : step.ok === false ? "failed" : "-";
      const result = record(step.result);
      const status = stringAtNullable(result, "status") ?? stringAtNullable(result, "failure") ?? "-";
      return `${phase} ${ok} ${status}`;
    });
  return [
    "Auth Session Switch Quick Verify",
    "=======================================================",
    `run=${input.runId ?? "-"} scenario=${input.scenarioId ?? "-"} observer=${input.observerId ?? "-"}`,
    `status=${artifact.ok === true ? "ok" : "blocked"} report=${artifact.reportJsonSha256 ?? "-"} publicOrigin=${input.publicOrigin ?? "-"}`,
    `accountEnv=${accountEnv.envCount ?? "-"} valuesRedacted=true`,
    "",
    "Command Sequence",
    commandSteps.length === 0 ? "-" : commandSteps.join("\n"),
    "",
    "Findings",
    findingRows.length === 0 ? "-" : findingRows.map((item) => `${item.severity ?? item.level ?? "-"} ${item.kind ?? item.id ?? item.code ?? "-"} count=${item.count ?? "-"} ${item.summary ?? item.message ?? ""}`).join("\n"),
  ].join("\n");
}

function renderMaintenanceResult(result: Record<string, unknown>): string {
  const serviceHealth = record(result.serviceHealth);
  const maintenance = record(result.maintenance);
  const quickVerify = record(result.quickVerify);
  const planned = record(result.planned);
  const blocker = record(result.blocker);
  const next = record(result.next);
  const maintenanceBody = record(maintenance.bodyJson);
  const state = record(maintenanceBody.maintenance);
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "STATUS", "MODE", "MUTATION"], [[result.node, result.lane, result.ok === true ? "ok" : "blocked", result.mode ?? "status", result.mutation ?? false]]),
    "",
    table(["SERVICE", "HTTP", "INTERNAL_URL"], [[serviceHealth.ok, serviceHealth.httpStatus, serviceHealth.internalUrl]]),
    "",
    Object.keys(state).length > 0
      ? table(["ACTIVE", "RELEASE", "STARTED", "STOPPED", "VERIFY_RUN"], [[state.active, state.releaseId, state.startedAt, state.stoppedAt, state.quickVerifyPlannedRunId]])
      : Object.keys(planned).length > 0
        ? table(["ACTION", "RELEASE", "REASON", "QUICK_VERIFY"], [[planned.action, planned.releaseId, planned.reason, planned.quickVerify]])
        : "MAINTENANCE\n-",
    "",
    Object.keys(quickVerify).length === 0 ? "QUICK_VERIFY\n-" : table(["OK", "RUN", "SCENARIO", "OBSERVER", "REPORT", "FINDINGS"], [[quickVerify.ok, quickVerify.runId, quickVerify.scenarioId, quickVerify.observerId, quickVerify.reportJsonSha256, quickVerify.findingCount]]),
    "",
    Object.keys(blocker).length === 0 ? "BLOCKER\n-" : table(["CODE", "REASON"], [[blocker.code, blocker.reason]]),
    "",
    "NEXT",
    `  validate: ${next.validate ?? "-"}`,
    `  report: ${next.report ?? "-"}`,
    `  maintenance-stop: ${next.maintenanceStop ?? "-"}`,
    "",
    "DISCLOSURE",
    "  maintenance uses the k3s internal sentinel Service DNS; no public fallback or second runner is used.",
  ].join("\n");
}

function renderValidateResult(result: Record<string, unknown>): string {
  const health = record(result.serviceHealth);
  const metrics = record(result.metrics);
  const report = record(result.report);
  const publicExposure = record(result.publicExposure);
  const publicDashboard = record(result.publicDashboard);
  const quickVerify = record(result.quickVerify);
  const blocker = record(result.blocker);
  const next = record(result.next);
  const warnings = mergeWarnings(Array.isArray(result.warnings) ? result.warnings : [], Array.isArray(quickVerify.warnings) ? quickVerify.warnings : []);
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "STATUS", "MODE"], [[result.node, result.lane, result.ok === true ? "ok" : "blocked", result.mode ?? "status"]]),
    "",
    table(["CHECK", "OK", "DETAIL"], [
      ["health", health.ok, `${health.httpStatus ?? "-"} ${short(health.internalUrl ?? health.publicUrl)}`],
      ["metrics", metrics.ok && metricNames(metrics.bodyTextPreview).includes("web_probe_sentinel_health"), `bytes=${metrics.bodyBytes ?? "-"} metric=web_probe_sentinel_health`],
      ["recent-report", report.ok, `${record(record(report.bodyJson).run).id ?? "-"} ${short(record(record(report.bodyJson).run).report_json_sha256)}`],
      ["public-exposure", publicExposure.ok, `${record(publicExposure.dns).expectedA ?? "-"} http=${record(publicExposure.https).httpStatus ?? "-"}`],
      ["public-dashboard", publicDashboard.ok, `${record(publicDashboard.root).url ?? "-"} root=${record(publicDashboard.root).httpStatus ?? "-"} css=${record(publicDashboard.css).httpStatus ?? "-"} js=${record(publicDashboard.js).httpStatus ?? "-"}`],
      ["quick-verify", Object.keys(quickVerify).length === 0 ? "skipped" : quickVerify.ok, `${quickVerify.runId ?? "-"} ${short(quickVerify.reportJsonSha256)}`],
    ]),
    "",
    warnings.length === 0 ? "WARNINGS\n-" : ["WARNINGS", ...warnings.map((item) => `- ${text(item)}`)].join("\n"),
    "",
    Object.keys(blocker).length === 0 ? "BLOCKER\n-" : table(["CODE", "BLOCKERS"], [[blocker.code, Array.isArray(blocker.blockers) ? blocker.blockers.join(",") : blocker.reason]]),
    "",
    "NEXT",
    `  quick-verify: ${next.quickVerify ?? "-"}`,
    `  report: ${next.report ?? "-"}`,
    `  maintenance-start: ${next.maintenanceStart ?? "-"}`,
    "",
    "DISCLOSURE",
    "  validate checks /api/health, /metrics, indexed analyze report and publicExposure without printing tokens.",
  ].join("\n");
}

function renderDashboardResult(result: Record<string, unknown>): string {
  const page = record(result.page);
  const dom = record(page.dom);
  const dataset = record(dom.dataset);
  const layout = record(dom.layout);
  const chartCounts = record(dom.chartCounts);
  const latestRunCounts = record(dom.latestRunCounts);
  const latestDetailSummary = record(dom.latestDetailSummary);
  const checkScope = record(dom.checkScope);
  const runFilterProbe = record(dom.runFilterProbe);
  const runFilterObserved = record(runFilterProbe.observed);
  const runFilterExpected = record(runFilterProbe.expected);
  const overviewSamples = record(dom.overviewSamples);
  const panelHeights = record(dom.panelHeights);
  const workspaceHeight = record(panelHeights.workspace);
  const checksHeight = record(panelHeights.checks);
  const screenshot = record(result.screenshot);
  const remote = record(result.remote);
  const transport = record(result.transport);
  const degradedReason = result.degradedReason ?? null;
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "SENTINEL", "STATUS", "URL"], [[result.node, result.lane, result.sentinelId, result.ok === true ? "pass" : "blocked", result.publicUrl]]),
    "",
    table(["HTTP", "SHELL", "RUN_ROWS", "FINDINGS", "TABS", "ERRORS", "CONSOLE_ERR", "REQ_FAIL"], [[
      page.httpStatus ?? "-",
      dom.shell,
      dom.runRows,
      dom.findingItems,
      dom.detailTabs,
      page.pageErrorCount,
      page.consoleErrorCount,
      page.requestFailureCount,
    ]]),
    "",
    table(["TITLE", "STATUS_TEXT", "CONTRACT", "BASE_PATH"], [[dom.title, dom.statusText, dataset.contractVersion, dataset.basePath ?? "-"]]),
    "",
    table(["TREND_ERROR", "TREND_WARNING", "TREND_TOTAL", "TREND_EXACT", "MATCH_LATEST", "BAD_TITLE", "BAD_BODY"], [[
      chartCounts.error ?? "-",
      chartCounts.warning ?? "-",
      chartCounts.total ?? "-",
      chartCounts.ok ?? "-",
      chartCounts.matchesLatestRun ?? "-",
      dom.badCardTitleCount ?? "-",
      dom.badCardBodyCount ?? "-",
    ]]),
    "",
    table(["LATEST_RUN", "TYPE_COUNT", "LATEST_ERR", "LATEST_WARN", "LATEST_TOTAL", "LATEST_ALL", "HIST_ERR", "HIST_WARN"], [[
      latestRunCounts.runId ?? "-",
      latestRunCounts.typeCount ?? "-",
      latestRunCounts.error ?? "-",
      latestRunCounts.warning ?? "-",
      latestRunCounts.total ?? "-",
      latestRunCounts.allSamples ?? "-",
      overviewSamples.error ?? "-",
      overviewSamples.warning ?? "-",
    ]]),
    "",
    table(["CHECK_SCOPE", "CHECK_RUN", "CHECK_TYPES", "CHECK_ALERT_TYPES", "CHECK_ERR", "CHECK_WARN", "CHECK_TOTAL", "CHECK_MATCH_LATEST", "CHECK_MATCH_DETAIL"], [[
      checkScope.scope ?? "-",
      checkScope.runId ?? "-",
      `${checkScope.typeCount ?? "-"}/${latestDetailSummary.typeCount ?? "-"}`,
      `${checkScope.alertTypeCount ?? "-"}/${latestDetailSummary.alertTypeCount ?? "-"}`,
      checkScope.errorSamples ?? "-",
      checkScope.warningSamples ?? "-",
      checkScope.alertSamples ?? "-",
      checkScope.matchesLatestRun ?? "-",
      checkScope.matchesRunDetail ?? "-",
    ]]),
    "",
    table(["CHECK_VISIBLE", "CHECK_VISIBLE_ALERT", "BELOW_WORKSPACE", "FULL_WIDTH"], [[
      checkScope.visibleCardCount ?? "-",
      checkScope.visibleAlertSamples ?? "-",
      checkScope.belowWorkspace ?? "-",
      checkScope.fullWidth ?? "-",
    ]]),
    "",
    table(["WORKSPACE_H", "WORKSPACE_RATIO", "WORKSPACE_80", "CHECKS_H", "CHECKS_RATIO", "CHECKS_80", "PANES_80"], [[
      `${workspaceHeight.heightPx ?? "-"}/${workspaceHeight.targetPx ?? "-"}`,
      workspaceHeight.ratio ?? "-",
      panelHeights.workspaceOk ?? "-",
      `${checksHeight.heightPx ?? "-"}/${checksHeight.targetPx ?? "-"}`,
      checksHeight.ratio ?? "-",
      panelHeights.checksOk ?? "-",
      panelHeights.workspacePaneBounded ?? "-",
    ]]),
    "",
    table(["FILTER_RUN", "FILTER_OPTION", "FILTER_TYPES", "FILTER_ALERT_TYPES", "FILTER_ERR", "FILTER_WARN", "FILTER_TOTAL", "FILTER_MATCH_DETAIL"], [[
      runFilterProbe.targetRunId ?? "-",
      runFilterProbe.requestedOptionPresent ?? "-",
      `${runFilterObserved.typeCount ?? "-"}/${runFilterExpected.typeCount ?? "-"}`,
      `${runFilterObserved.alertTypeCount ?? "-"}/${runFilterExpected.alertTypeCount ?? "-"}`,
      runFilterObserved.errorSamples ?? "-",
      runFilterObserved.warningSamples ?? "-",
      runFilterObserved.alertSamples ?? "-",
      runFilterProbe.matchesRunDetail ?? "-",
    ]]),
    "",
    table(["VIEWPORT", "DOC", "H_OVERFLOW", "OVERFLOW_COUNT"], [[
      result.viewport,
      `${record(layout.documentSize).width ?? "-"}x${record(layout.documentSize).height ?? "-"}`,
      layout.horizontalOverflow,
      layout.overflowCount,
    ]]),
    "",
    Object.keys(screenshot).length === 0
      ? "SCREENSHOT\n-"
      : table(["LOCAL_PATH", "BYTES", "SHA256", "VERIFIED"], [[screenshot.localPath, screenshot.bytes, short(screenshot.sha256), screenshot.verified]]),
    "",
    degradedReason === null ? "BLOCKER\n-" : table(["CODE", "REMOTE_EXIT", "TRANSPORT"], [[degradedReason, remote.exitCode, transport.ok]]),
    "",
    "NEXT",
    `  screenshot: bun scripts/cli.ts web-probe sentinel dashboard screenshot --node ${result.node} --lane ${result.lane} --sentinel ${result.sentinelId}`,
    `  validate: bun scripts/cli.ts web-probe sentinel validate --node ${result.node} --lane ${result.lane} --sentinel ${result.sentinelId}`,
    "",
    "DISCLOSURE",
    "  dashboard verify uses the YAML publicExposure URL and remote browser execution; it does not start a sentinel run or inspect provider payloads.",
  ].join("\n");
}

function renderReportResult(result: Record<string, unknown>): string {
  const report = record(result.report);
  const body = record(report.bodyJson);
  const run = record(body.run);
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "STATUS", "VIEW", "RUN"], [[result.node, result.lane, report.ok ? "ok" : "blocked", body.view ?? "-", run.id ?? "-"]]),
    "",
    table(["HTTP", "ERROR", "REPORT"], [[report.httpStatus, body.error ?? report.error ?? "-", short(run.report_json_sha256)]]),
    "",
    "DISCLOSURE",
    "  report reads sentinel indexed analyze summaries/views only; it does not resample, rerun analyze, or read Workbench.",
  ].join("\n");
}

function sentinelPipelineRunName(state: SentinelCicdState): string {
  const commit = state.sourceHead.commit ?? "source";
  return `hwlab-web-probe-sentinel-${safeKubernetesSegment(state.sentinelId, 24)}-${commit.slice(0, 12)}`;
}

function sentinelCliSuffix(state: SentinelCicdState): string {
  return ` --sentinel ${state.sentinelId}`;
}

function safeJobSegment(value: string): string {
  return value.replace(/[^A-Za-z0-9_]+/gu, "_").replace(/^_+|_+$/gu, "").slice(0, 48) || "sentinel";
}

function safeKubernetesSegment(value: string, maxLength: number): string {
  const normalized = value.toLowerCase().replace(/[^a-z0-9-]+/gu, "-").replace(/^-+|-+$/gu, "");
  return (normalized || "sentinel").slice(0, Math.max(1, maxLength)).replace(/-+$/u, "") || "sentinel";
}

function renderImageResult(result: Record<string, unknown>): string {
  const source = record(result.source);
  const sourceMirror = record(result.sourceMirror);
  const sourceMirrorSync = record(result.sourceMirrorSync);
  const image = record(result.image);
  const monitorWeb = record(image.monitorWeb);
  const registry = record(result.registry);
  const publish = record(result.publish);
  const blocker = record(result.blocker);
  const next = record(result.next);
  const warnings = Array.isArray(result.warnings) ? result.warnings : [];
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "STATUS", "MODE", "MUTATION"], [[result.node, result.lane, result.ok === true ? "ok" : "blocked", result.mode, result.mutation]]),
    "",
    table(["SOURCE_REPO", "BRANCH", "COMMIT", "LOCAL_HEAD"], [[source.repository, source.branch, short(source.commit), short(source.localHead)]]),
    "",
    Object.keys(sourceMirror).length === 0 ? "SOURCE_MIRROR\n-" : table(["OK", "MODE", "COMMIT", "EXPECTED", "READ_URL"], [[sourceMirror.ok, record(sourceMirror.probe).mode, short(record(sourceMirror.probe).commit), short(record(sourceMirror.probe).expectedCommit), record(sourceMirror.probe).readUrl ?? "-"]]),
    "",
    table(["IMAGE", "BASE", "ENTRYPOINT", "DOCKERFILE"], [[image.ref, image.baseImage, image.entrypoint, short(image.dockerfileSha256)]]),
    "",
    Object.keys(monitorWeb).length === 0 ? "MONITOR_WEB\n-" : table(["STACK", "MODE", "ASSETS", "VERIFY", "ENV_REUSE"], [[monitorWeb.stack, monitorWeb.runtimeMode, monitorWeb.assetRoot, monitorWeb.verifyCommand, `${monitorWeb.envReuseMode}:${monitorWeb.envReuseNodeDepsPath}`]]),
    "",
    Object.keys(registry).length === 0 ? "REGISTRY\n-" : table(["PROBED", "PRESENT", "DIGEST"], [[record(registry.probe).url ?? "-", record(registry.probe).present ?? "-", short(record(registry.probe).digest)]]),
    "",
    Object.keys(sourceMirrorSync).length === 0 ? "SOURCE_MIRROR_SYNC\n-" : table(["OK", "PHASE", "JOB", "COMMIT", "ELAPSED"], [[sourceMirrorSync.ok, sourceMirrorSync.phase, sourceMirrorSync.jobName, short(record(sourceMirrorSync.payload).mirrorCommit), sourceMirrorSync.elapsedMs ?? "-"]]),
    "",
    Object.keys(publish).length === 0 ? "PUBLISH\n-" : table(["OK", "PHASE", "JOB", "DIGEST", "GITOPS"], [[publish.ok, publish.phase, publish.jobName, short(record(publish.payload).digestRef), short(record(publish.payload).gitopsCommit)]]),
    "",
    warnings.length === 0 ? "WARNINGS\n-" : ["WARNINGS", ...warnings.map((item) => `- ${text(item)}`)].join("\n"),
    "",
    Object.keys(blocker).length === 0 ? "BLOCKER\n-" : table(["CODE", "REASON"], [[blocker.code, blocker.reason]]),
    "",
    "NEXT",
    `  status: ${next.status ?? "-"}`,
    `  dry-run: ${next.dryRun ?? "-"}`,
    `  confirm: ${next.confirm ?? "-"}`,
    `  trigger: ${next.controlPlaneTrigger ?? "-"}`,
    `  control-plane: ${next.controlPlanePlan ?? "-"}`,
    "",
    "DISCLOSURE",
    "  valuesRedacted=true; image status shows refs, hashes and object names only.",
  ].join("\n");
}

function renderControlPlaneResult(result: Record<string, unknown>): string {
  const source = record(result.source);
  const image = record(result.image);
  const gitops = record(result.gitops);
  const argo = record(result.argo);
  const validation = record(result.validation);
  const observed = record(result.observed);
  const sourceMirrorSync = record(result.sourceMirrorSync);
  const publish = record(result.publish);
  const flush = record(result.flush);
  const runtimeSecretsApply = record(result.runtimeSecretsApply);
  const publicExposureApply = record(result.publicExposureApply);
  const publicExposureCaddy = record(publicExposureApply.caddy);
  const argoApply = record(result.argoApply);
  const blocker = record(result.blocker);
  const targetValidation = record(result.targetValidation);
  const next = record(result.next);
  const warnings = Array.isArray(result.warnings) ? result.warnings : [];
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "STATUS", "MODE", "PIPELINERUN"], [[result.node, result.lane, result.ok === true ? "ok" : "blocked", result.mode, result.pipelineRun]]),
    "",
    table(["SOURCE", "COMMIT", "IMAGE", "MANIFEST"], [[`${source.repository}@${source.branch}`, short(source.commit), image.ref, short(gitops.manifestSha256)]]),
    "",
    table(["GITOPS_PATH", "ARGO_APP", "TARGET_REV", "OBJECTS"], [[gitops.path, argo.applicationName, gitops.targetRevision, gitops.manifestObjects]]),
    "",
    table(["SCENARIO", "MAX_SECONDS", "CI_WAIT", "QVERIFY", "SECOND_PATH"], [[validation.scenarioId, validation.maxSeconds, validation.controlPlaneWaitMaxSeconds ?? "-", validation.quickVerifyMode ?? "-", validation.automaticSecondPath]]),
    "",
    renderObservedStatus(observed),
    "",
    Object.keys(sourceMirrorSync).length === 0 ? "SOURCE_MIRROR_SYNC\n-" : table(["OK", "PHASE", "JOB", "COMMIT", "ELAPSED"], [[sourceMirrorSync.ok, sourceMirrorSync.phase, sourceMirrorSync.jobName, short(record(sourceMirrorSync.payload).mirrorCommit), sourceMirrorSync.elapsedMs ?? "-"]]),
    "",
    Object.keys(targetValidation).length === 0 ? "TARGET_VALIDATION\n-" : table(["OK", "STATUS", "SCENARIO", "RUN", "OBSERVER", "REPORT", "FINDINGS", "ARTIFACTS"], [[
      targetValidation.ok,
      targetValidation.status,
      targetValidation.scenarioId,
      targetValidation.runId,
      targetValidation.observerId,
      short(targetValidation.reportJsonSha256),
      targetValidation.findingCount,
      targetValidation.artifactCount,
    ]]),
    "",
    Object.keys(publish).length === 0 ? "PUBLISH\n-" : table(["OK", "PHASE", "JOB", "DIGEST", "GITOPS"], [[publish.ok, publish.phase, publish.jobName, short(record(publish.payload).digestRef), short(record(publish.payload).gitopsCommit)]]),
    "",
    Object.keys(flush).length === 0
      ? "FLUSH\n-"
      : flush.mode === "async-job"
        ? table(["OK", "MODE", "JOB", "STATUS"], [[flush.ok, flush.mode, record(flush.job).id, record(flush.next).status]])
        : table(["OK", "EXIT", "TIMED_OUT", "PREVIEW"], [[flush.ok, record(flush.result).exitCode, record(flush.result).timedOut, record(flush.result).stdoutPreview]]),
    "",
    Object.keys(runtimeSecretsApply).length === 0 ? "RUNTIME_SECRETS\n-" : table(["OK", "SECRETS", "KEYS", "SKIPPED"], [[runtimeSecretsApply.ok, runtimeSecretsApply.secretCount ?? "-", runtimeSecretsApply.keyCount ?? "-", runtimeSecretsApply.skippedKeyCount ?? "-"]]),
    "",
    Object.keys(publicExposureApply).length === 0 ? "PUBLIC_EXPOSURE_APPLY\n-" : table(["OK", "SECRET", "CADDY", "HOST", "ROUTE_HTTP"], [[publicExposureApply.ok, record(publicExposureApply.secret).ok, record(publicExposureApply.caddy).ok, publicExposureApply.hostname, record(publicExposureApply.caddy).routeProbeHttpStatus ?? "-"]]),
    "",
    Object.keys(publicExposureCaddy).length === 0 || publicExposureCaddy.ok === true
      ? "CADDY_APPLY_DETAIL\n-"
      : table(["PY", "VALIDATE", "RELOAD", "PROBE", "HTTP", "BLOCK", "ACTIVE", "ERROR", "STDOUT", "STDERR"], [[publicExposureCaddy.pythonExitCode, publicExposureCaddy.validateExitCode, publicExposureCaddy.reloadExitCode, publicExposureCaddy.routeProbeExitCode, publicExposureCaddy.routeProbeHttpStatus, publicExposureCaddy.afterBlockPresent, publicExposureCaddy.active, short(publicExposureCaddy.errorPreview), short(record(publicExposureCaddy.result).stdoutPreview), short(record(publicExposureCaddy.result).stderrPreview)]]),
    "",
    Object.keys(argoApply).length === 0 ? "ARGO_APPLY\n-" : table(["OK", "EXIT", "PREVIEW"], [[argoApply.ok, record(argoApply.result).exitCode, record(argoApply.result).stdoutPreview]]),
    "",
    warnings.length === 0 ? "WARNINGS\n-" : ["WARNINGS", ...warnings.map((item) => `- ${text(item)}`)].join("\n"),
    "",
    Object.keys(blocker).length === 0 ? "BLOCKER\n-" : table(["CODE", "REASON"], [[blocker.code, blocker.reason]]),
    "",
    "NEXT",
    `  plan: ${next.plan ?? "-"}`,
    `  status: ${next.status ?? "-"}`,
    `  image: ${next.image ?? "-"}`,
    `  trigger-current: ${next.triggerCurrent ?? "-"}`,
    `  validate: ${next.validate ?? "-"}`,
    `  quick-verify: ${next.quickVerify ?? "-"}`,
    "",
    "DISCLOSURE",
    "  default view is a bounded CI/CD summary; full manifest content is represented by object counts and sha256.",
    "  sentinel unavailable policy is structured-failure; no automatic second execution path is rendered.",
  ].join("\n");
}

function renderObservedStatus(observed: Record<string, unknown>): string {
  const rows = [
    observedStatusRow("source", observed.sourceMirror),
    observedStatusRow("registry", observed.registry),
    observedStatusRow("git-mirror", observed.gitMirror),
    observedStatusRow("gitops", observed.gitops),
    observedStatusRow("argo", observed.argo),
    observedStatusRow("runtime", observed.runtime),
  ].filter((row) => row !== null);
  if (rows.length === 0) return "OBSERVED\n-";
  return table(["CHECK", "OK", "DETAIL", "EXIT", "TIMED_OUT", "PREVIEW"], rows);
}

function observedStatusRow(name: string, value: unknown): unknown[] | null {
  const item = record(value);
  if (Object.keys(item).length === 0) return null;
  const result = record(item.result);
  return [name, item.ok, observedDetail(name, item), result.exitCode, result.timedOut, result.stdoutPreview];
}

function observedDetail(name: string, item: Record<string, unknown>): string {
  if (name === "source") return `${record(item.probe).mode ?? "mirror"} ${short(record(item.probe).commit)}/${short(record(item.probe).expectedCommit)}`;
  if (name === "registry") return `${record(item.probe).present === true ? "present" : "missing"} ${short(record(item.probe).digest)}`;
  if (name === "git-mirror" && item.skipped === true) return `${item.reason ?? "skipped"}`;
  if (name === "gitops") return `${short(item.revision)} image=${short(item.image)}`;
  if (name === "argo") return `${item.syncStatus ?? "-"} ${item.healthStatus ?? "-"} ${short(item.revision)}/${short(item.expectedRevision)}`;
  if (name === "runtime") {
    const probe = record(item.probe);
    const deployment = record(probe.deployment);
    return `ready=${deployment.readyReplicas ?? "-"} image=${short(deployment.image)}/${short(deployment.expectedImage)}`;
  }
  return "-";
}

function renderAsyncJobResult(result: Record<string, unknown>): string {
  const job = record(result.job);
  const next = record(result.next);
  return [
    String(result.command),
    "",
    table(["NODE", "LANE", "MODE", "MUTATION", "JOB"], [[result.node, result.lane, result.mode, result.mutation, job.id]]),
    "",
    table(["STATUS", "NAME", "CREATED"], [[job.status, job.name, job.createdAt]]),
    "",
    "NEXT",
    `  status: ${next.status ?? "-"}`,
    `  wait: ${next.wait ?? "-"}`,
    "",
    "DISCLOSURE",
    "  confirmed operation is delegated to UniDesk job status to keep interactive calls bounded.",
  ].join("\n");
}

function rendered(ok: boolean, command: string, text: string): RenderedCliResult {
  return { ok, command, renderedText: `${text.trimEnd()}\n`, contentType: "text/plain" };
}

function readConfigRefTarget(ref: string): unknown {
  const file = configRefFile(ref);
  const path = configRefPath(ref);
  return valueAtPath(readConfigFile(file), path);
}

function readConfigFile(file: string): unknown {
  if (file.startsWith("/") || file.includes("..") || !file.startsWith("config/")) throw new Error(`unsafe configRef file: ${file}`);
  const abs = rootPath(file);
  if (!existsSync(abs)) throw new Error(`${file} does not exist`);
  return Bun.YAML.parse(readFileSync(abs, "utf8")) as unknown;
}

function configRefFile(ref: string): string {
  const [file, path, extra] = ref.split("#");
  if (extra !== undefined || file === undefined || path === undefined || file.length === 0 || path.length === 0) throw new Error(`invalid configRef: ${ref}`);
  return file;
}

function configRefPath(ref: string): string {
  const [, path] = ref.split("#");
  if (path === undefined || path.length === 0) throw new Error(`invalid configRef: ${ref}`);
  return path;
}

function valueAtPath(value: unknown, path: string): unknown {
  let current: unknown = value;
  for (const segment of path.split(".")) {
    const match = /^([A-Za-z0-9_-]+)?(?:\[(\d+)\])?$/u.exec(segment);
    if (match === null) return undefined;
    if (match[1] !== undefined) {
      if (!isRecord(current)) return undefined;
      current = current[match[1]];
    }
    if (match[2] !== undefined) {
      if (!Array.isArray(current)) return undefined;
      current = current[Number(match[2])];
    }
  }
  return current;
}

function stringAt(value: unknown, path: string): string {
  const found = valueAtPath(value, path);
  if (typeof found !== "string" || found.length === 0) throw new Error(`${path} must be a non-empty string`);
  return found;
}

function nonEmptyString(value: unknown): string | null {
  return typeof value === "string" && value.length > 0 ? value : null;
}

function stringField(value: Record<string, unknown>, path: string): string {
  return stringAt(value, path);
}

function stringTarget(value: unknown, label: string): string {
  if (typeof value !== "string" || value.length === 0) throw new Error(`${label} must resolve to a non-empty string`);
  return value;
}

function numberAt(value: unknown, path: string): number {
  const found = valueAtPath(value, path);
  if (typeof found !== "number" || !Number.isFinite(found)) throw new Error(`${path} must be a number`);
  return found;
}

function arrayAt(value: unknown, path: string): unknown[] {
  const found = valueAtPath(value, path);
  if (!Array.isArray(found)) throw new Error(`${path} must be an array`);
  return found;
}

function recordTarget(value: unknown, label: string): Record<string, unknown> {
  if (!isRecord(value)) throw new Error(`${label} must resolve to an object`);
  return value;
}

function record(value: unknown): Record<string, unknown> {
  return isRecord(value) ? value : {};
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function manifestObjectSummary(items: readonly Record<string, unknown>[]): readonly Record<string, unknown>[] {
  return items.map((item) => ({
    kind: item.kind ?? null,
    name: record(item.metadata).name ?? null,
    namespace: record(item.metadata).namespace ?? null,
  }));
}

function compactCommand(result: CommandResult): CompactCommandResult {
  return {
    exitCode: result.exitCode,
    timedOut: result.timedOut,
    stdoutBytes: Buffer.byteLength(result.stdout),
    stderrBytes: Buffer.byteLength(result.stderr),
    stdoutPreview: result.stdout.trim().slice(0, 500),
    stderrPreview: result.stderr.trim().slice(0, 500),
  };
}

function parseJsonObject(text: string): Record<string, unknown> | null {
  const trimmed = text.trim();
  if (trimmed.length === 0) return null;
  try {
    const parsed = JSON.parse(trimmed) as unknown;
    return isRecord(parsed) ? parsed : null;
  } catch {
    return null;
  }
}

function table(headers: string[], rows: unknown[][]): string {
  const normalized = [headers, ...rows.map((row) => row.map(text))];
  const widths = headers.map((_, index) => Math.max(...normalized.map((row) => text(row[index] ?? "").length)));
  return normalized.map((row) => row.map((cell, index) => text(cell).padEnd(widths[index])).join("  ").trimEnd()).join("\n");
}

function text(value: unknown): string {
  if (value === undefined || value === null || value === "") return "-";
  if (typeof value === "boolean") return value ? "true" : "false";
  return String(value).replace(/\s+/gu, " ").trim();
}

function short(value: unknown): string {
  const raw = text(value);
  if (raw === "-") return raw;
  if (/^sha256:[0-9a-f]{64}$/iu.test(raw)) return `${raw.slice(0, 19)}...`;
  if (/^[0-9a-f]{40}$/iu.test(raw)) return raw.slice(0, 12);
  return raw.length > 42 ? `${raw.slice(0, 39)}...` : raw;
}

function sha256(textValue: string): string {
  return `sha256:${createHash("sha256").update(textValue).digest("hex")}`;
}

function shellQuote(value: string): string {
  return `'${value.replace(/'/gu, "'\\''")}'`;
}

function tomlEscape(value: string): string {
  return value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"');
}
