// SPEC: PJ2026-01060508 Web哨兵 draft-2026-07-01-p16-cicd-source-snapshot.
// Responsibility: source mirror and publish remote Job/PipelineRun orchestration for web-probe sentinel CI/CD.
import { runCommand } from "./command";
import { repoRoot, rootPath } from "./config";
import { readWebProbeSentinelConfigRefTarget } from "./hwlab-node-web-sentinel-config-ref";
import { emitWebProbeSentinelSpan } from "./hwlab-node-web-sentinel-otel";
import {
  arrayAt,
  compactCommand,
  finiteNumberOrNull,
  isRecord,
  monitorWebBuildkitStatePlan,
  nonEmptyString,
  numberAt,
  numberAtNullable,
  parseJsonObject,
  record,
  resolveSentinelChildJson,
  safeKubernetesSegment,
  sentinelCliSuffix,
  sentinelPipelineRunName,
  sentinelProgressEvent,
  sentinelSourceSnapshotStageRefPrefix,
  shellQuote,
  short,
  stringAt,
  stringAtNullable,
  text,
  valueAtPath,
  type SentinelCicdState,
  type SentinelRemoteJobResult,
} from "./hwlab-node-web-sentinel-cicd-shared";

export 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 withSentinelRemoteJobDiagnostics(state, { ok: false, phase: "create-job", jobName, payload: { ok: false, status: "create-failed", valuesRedacted: true }, create: compactCommand(created), valuesRedacted: true }, "source-mirror");
  }
  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 probeResolution = resolveSentinelChildJson(probeCapture, "web-probe-sentinel-source-mirror-job-probe");
    const probe = probeResolution.parsed ?? {};
    lastProbe = { ...probe, stdoutRecovery: probeResolution.diagnostics, 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 withSentinelRemoteJobDiagnostics(state, { 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 }, "source-mirror");
    }
    if (probe.failed === true) {
      return withSentinelRemoteJobDiagnostics(state, { 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 }, "source-mirror");
    }
    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 withSentinelRemoteJobDiagnostics(state, { ok: false, phase: "job-timeout", jobName, payload: { ok: false, status: "timeout", valuesRedacted: true }, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true }, "source-mirror");
}

export 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: [
            sentinelGitMirrorCacheVolume(state),
            { 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 sentinelSourceMirrorSyncShellFromConfig(state.cicd, state.controlPlaneNode, jobName, state.sourceHead.commit);
}

export function sentinelSourceMirrorSyncShellFromConfig(cicd: Record<string, unknown>, controlPlaneNode: Record<string, unknown>, jobName: string, selectedCommit: string | null): string {
  return [
    "set -eu",
    `job_name=${shellQuote(jobName)}`,
    `source_repository=${shellQuote(stringAt(cicd, "source.repository"))}`,
    `source_branch=${shellQuote(stringAt(cicd, "source.branch"))}`,
    `source_git_url=${shellQuote(stringAt(cicd, "source.gitSshUrl"))}`,
    `source_commit=${shellQuote(selectedCommit ?? "")}`,
    `source_stage_ref_prefix=${shellQuote(sentinelSourceSnapshotStageRefPrefix(cicd))}`,
    "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",
    ...sentinelSourceMirrorSshSetupShellLinesForNode(controlPlaneNode),
    "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}\")",
    "if [ -z \"$source_commit\" ]; then source_commit=\"$mirror_commit\"; fi",
    "git --git-dir=\"$repo\" cat-file -e \"$source_commit^{commit}\"",
    "test \"$mirror_commit\" = \"$source_commit\"",
    "stage_ref=\"${source_stage_ref_prefix%/}/${source_commit}\"",
    "git --git-dir=\"$repo\" update-ref \"refs/heads/$source_branch\" \"$mirror_commit\"",
    "git --git-dir=\"$repo\" update-ref \"$stage_ref\" \"$source_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\" \"$stage_ref\" \"$started_ms\" \"$finished_ms\" <<'NODE'",
    "const [jobName, repository, branch, sourceCommit, mirrorCommit, stageRef, startedMs, finishedMs] = process.argv.slice(2);",
    "console.log(JSON.stringify({ ok:true, status:'succeeded', jobName, repository, branch, sourceCommit, mirrorCommit, stageRef, sourceAuthority:'git-mirror-snapshot', elapsedMs:Number(finishedMs)-Number(startedMs), valuesRedacted:true }));",
    "NODE",
    "trap - EXIT",
  ].join("\n");
}

function sentinelSourceMirrorSshSetupShellLines(state: SentinelCicdState): string[] {
  return sentinelSourceMirrorSshSetupShellLinesForNode(state.controlPlaneNode);
}

function sentinelSourceMirrorSshSetupShellLinesForNode(controlPlaneNode: Record<string, unknown>): string[] {
  const proxy = record(valueAtPath(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 hostRouteProxyUrl = nonEmptyString(proxy.proxyUrl);
  const noProxy = Array.isArray(proxy.noProxy) ? proxy.noProxy.filter((item): item is string => typeof item === "string" && item.length > 0).join(",") : "";
  let proxyHost: string | null = null;
  let proxyPort: number | null = null;
  let proxyUrl: string | null = null;
  if (serviceName !== null && namespace !== null && port !== null) {
    proxyHost = `${serviceName}.${namespace}.svc.cluster.local`;
    proxyPort = port;
    proxyUrl = `http://${proxyHost}:${proxyPort}`;
  } else if (hostRouteProxyUrl !== null) {
    try {
      const parsed = new URL(hostRouteProxyUrl);
      const parsedPort = Number.parseInt(parsed.port || "80", 10);
      if ((parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.hostname.length > 0 && Number.isInteger(parsedPort)) {
        proxyHost = parsed.hostname;
        proxyPort = parsedPort;
        proxyUrl = hostRouteProxyUrl;
      }
    } catch {
      proxyHost = null;
      proxyPort = null;
      proxyUrl = null;
    }
  }
  const useProxy = proxyHost !== null && proxyPort !== null && proxyUrl !== 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 proxyCommand = `ProxyCommand=node /tmp/sentinel-github-proxy-connect.cjs ${proxyHost} ${proxyPort} %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=${proxyPort} 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",
  ];
}

export function runSentinelPublishJob(state: SentinelCicdState, publishGitops: boolean, timeoutSeconds: number, rerun: boolean): SentinelRemoteJobResult {
  const pipelineRunName = sentinelPipelineRunName(state, rerun);
  const manifest = sentinelPublishPipelineRunManifest(state, pipelineRunName, publishGitops);
  const namespace = stringAt(state.cicd, "builder.namespace");
  if (process.env.KUBERNETES_SERVICE_HOST && process.env.KUBERNETES_SERVICE_PORT) {
    return runSentinelPublishPipelineRunInCluster(state, manifest, namespace, pipelineRunName, publishGitops, timeoutSeconds);
  }
  sentinelProgressEvent("sentinel.publish.progress", { phase: "create-pipelinerun", status: "submitting", pipelineRun: pipelineRunName, publishGitops, sourceCommit: state.sourceHead.commit, node: state.spec.nodeId, lane: state.spec.lane });
  const created = runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "sh", "--", createTektonPipelineRunScript(namespace, manifest)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
  if (created.exitCode !== 0) {
    sentinelProgressEvent("sentinel.publish.progress", { phase: "create-pipelinerun", status: "failed", pipelineRun: pipelineRunName, publishGitops, node: state.spec.nodeId, lane: state.spec.lane });
    return withSentinelRemoteJobDiagnostics(state, { ok: false, phase: "create-pipelinerun", resourceKind: "PipelineRun", jobName: pipelineRunName, payload: { ok: false, status: "create-failed", valuesRedacted: true }, create: compactCommand(created), valuesRedacted: true }, "publish");
  }
  sentinelProgressEvent("sentinel.publish.progress", { phase: "create-pipelinerun", status: "succeeded", pipelineRun: pipelineRunName, 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", "--", probeTektonPipelineRunScript(namespace, pipelineRunName)], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });
    const probeResolution = resolveSentinelChildJson(probeCapture, "web-probe-sentinel-publish-pipelinerun-probe");
    const probe = probeResolution.parsed ?? {};
    lastProbe = { ...probe, stdoutRecovery: probeResolution.diagnostics, capture: compactCommand(probeCapture) };
    const payload = sentinelPayloadFromLogs(String(probe.logsTail ?? ""));
    sentinelProgressEvent("sentinel.publish.progress", {
      phase: "remote-pipelinerun",
      status: probe.succeeded === true ? "succeeded" : probe.failed === true ? "failed" : "running",
      pipelineRun: pipelineRunName,
      publishGitops,
      polls,
      elapsedMs: Date.now() - startedAt,
      taskRun: probe.taskRun ?? null,
      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 withSentinelRemoteJobDiagnostics(state, { ok, phase: "pipelinerun-succeeded", resourceKind: "PipelineRun", jobName: pipelineRunName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "result-missing", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true }, "publish");
    }
    if (probe.failed === true) {
      return withSentinelRemoteJobDiagnostics(state, { ok: false, phase: "pipelinerun-failed", resourceKind: "PipelineRun", jobName: pipelineRunName, payload: Object.keys(payload).length === 0 ? { ok: false, status: "failed", valuesRedacted: true } : payload, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true }, "publish");
    }
    if (!slowWarningSent && Date.now() - startedAt > warningBudgetMs) {
      slowWarningSent = true;
      sentinelProgressEvent("sentinel.publish.warning", { warning: `remote publish PipelineRun exceeded configured ${Math.round(warningBudgetMs / 1000)}s timing budget; non-blocking timing alert`, pipelineRun: pipelineRunName, elapsedMs: Date.now() - startedAt, node: state.spec.nodeId, lane: state.spec.lane });
    }
    runCommand(["sleep", "2"], repoRoot, { timeoutMs: 3_000 });
  }
  return withSentinelRemoteJobDiagnostics(state, { ok: false, phase: "pipelinerun-timeout", resourceKind: "PipelineRun", jobName: pipelineRunName, payload: { ok: false, status: "timeout", valuesRedacted: true }, polls, elapsedMs: Date.now() - startedAt, probe: lastProbe, valuesRedacted: true }, "publish");
}

function runSentinelPublishPipelineRunInCluster(state: SentinelCicdState, manifest: Record<string, unknown>, namespace: string, pipelineRunName: string, publishGitops: boolean, timeoutSeconds: number): SentinelRemoteJobResult {
  sentinelProgressEvent("sentinel.publish.progress", { phase: "native-submit-pipelinerun", status: "submitting", pipelineRun: pipelineRunName, publishGitops, sourceCommit: state.sourceHead.commit, node: state.spec.nodeId, lane: state.spec.lane });
  const manifestB64 = Buffer.from(JSON.stringify(manifest), "utf8").toString("base64");
  const result = runCommand(["node", "scripts/native/cicd/submit-pipelinerun.mjs"], repoRoot, {
    input: manifestB64,
    timeoutMs: Math.max(5_000, Math.min(timeoutSeconds * 1000, controlPlaneWaitWarningSeconds(state) * 1000)),
    env: {
      ...process.env,
      NAMESPACE: namespace,
      PIPELINERUN: pipelineRunName,
      WAIT: "true",
      TIMEOUT_SECONDS: String(Math.max(1, Math.min(timeoutSeconds, controlPlaneWaitWarningSeconds(state)))),
      POLL_INTERVAL_SECONDS: "2",
      LOGS_TAIL_LINES: "240",
      MAX_LOG_BYTES: "48000",
    },
  });
  const parsed = parseJsonObject(result.stdout) ?? {};
  const payload = sentinelPayloadFromLogs(String(parsed.logsTail ?? ""));
  const pipelineRun = record(parsed.pipelineRun);
  const failed = parsed.failed === true || record(pipelineRun).conditionStatus === "False";
  const completed = parsed.completed === true || record(pipelineRun).conditionStatus === "True";
  const phase = failed ? "pipelinerun-failed" : completed ? "pipelinerun-succeeded" : "pipelinerun-timeout";
  const ok = result.exitCode === 0 && completed && payload.ok === true;
  return withSentinelRemoteJobDiagnostics(state, {
    ok,
    phase,
    resourceKind: "PipelineRun",
    jobName: pipelineRunName,
    payload: Object.keys(payload).length === 0 ? { ok: false, status: completed ? "result-missing" : failed ? "failed" : "timeout", valuesRedacted: true } : payload,
    polls: parsed.polls ?? null,
    elapsedMs: parsed.elapsedMs ?? result.durationMs ?? null,
    traceId: parsed.traceId ?? null,
    traceparent: parsed.traceparent ?? null,
    firstBreak: parsed.firstBreak ?? null,
    error: parsed.error ?? null,
    probe: {
      nativeSubmit: parsed,
      capture: compactCommand(result),
      valuesRedacted: true,
    },
    valuesRedacted: true,
  }, "publish");
}

export function sentinelPublishPipelineRunManifest(state: SentinelCicdState, pipelineRunName: string, publishGitops: boolean): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const buildkitImage = requireSentinelBuildkitImage(state);
  const proxyEnv = sentinelImageBuildProxyEnv(state);
  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,
    "unidesk.ai/ci-system": "tekton",
  };
  return {
    apiVersion: "tekton.dev/v1",
    kind: "PipelineRun",
    metadata: {
      name: pipelineRunName,
      namespace,
      labels,
      annotations: {
        "unidesk.ai/source-commit": state.sourceHead.commit ?? "",
        "unidesk.ai/source-authority": state.sourceHead.sourceAuthority,
        "unidesk.ai/source-stage-ref": state.sourceHead.stageRef ?? "",
        "unidesk.ai/gitops-target-revision": stringAt(state.cicd, "argo.targetRevision"),
        "unidesk.ai/publish-gitops": publishGitops ? "true" : "false",
      },
    },
    spec: {
      timeouts: { pipeline: `${numberAt(state.cicd, "builder.activeDeadlineSeconds")}s` },
      taskRunTemplate: {
        podTemplate: {
          hostNetwork: true,
          dnsPolicy: "ClusterFirstWithHostNet",
          securityContext: { fsGroup: 1000 },
        },
      },
      pipelineSpec: {
        tasks: [{
          name: "publish",
          taskSpec: {
            volumes: [
              sentinelGitMirrorCacheVolume(state),
              { name: "git-ssh", secret: { secretName: stringAt(state.cicd, "builder.gitSshSecretName"), defaultMode: 256 } },
              { name: "workspace", emptyDir: { sizeLimit: "8Gi" } },
              sentinelBuildkitStateVolume(state),
              { name: "tmp", emptyDir: {} },
            ],
            steps: [
              {
                name: "source",
                image: state.image.baseImage,
                imagePullPolicy: "IfNotPresent",
                env: proxyEnv,
                script: tektonShellScript(sentinelPublishSourceShell(state, pipelineRunName)),
                volumeMounts: [
                  { name: "workspace", mountPath: "/workspace" },
                  { name: "git-ssh", mountPath: "/git-ssh", readOnly: true },
                ],
              },
              {
                name: "prepare-buildkit-state",
                image: state.image.baseImage,
                imagePullPolicy: "IfNotPresent",
                script: tektonShellScript("set -eu\nmkdir -p /home/user/.local/share/buildkit\nchown -R 1000:1000 /home/user/.local/share/buildkit"),
                securityContext: { runAsUser: 0, runAsGroup: 0 },
                volumeMounts: [
                  { name: "buildkit-state", mountPath: "/home/user/.local/share/buildkit" },
                ],
              },
              {
                name: "image-build",
                image: buildkitImage,
                imagePullPolicy: "IfNotPresent",
                env: [
                  ...proxyEnv,
                  { name: "BUILDKITD_FLAGS", value: "--oci-worker-no-process-sandbox --oci-worker-net=host --allow-insecure-entitlement network.host" },
                ],
                script: tektonShellScript(sentinelPublishImageBuildShell(state, pipelineRunName)),
                securityContext: { privileged: true, runAsUser: 1000, runAsGroup: 1000 },
                volumeMounts: [
                  { name: "workspace", mountPath: "/workspace" },
                  { name: "buildkit-state", mountPath: "/home/user/.local/share/buildkit" },
                  { name: "tmp", mountPath: "/tmp" },
                ],
              },
              {
                name: "publish",
                image: state.image.baseImage,
                imagePullPolicy: "IfNotPresent",
                env: proxyEnv,
                script: tektonShellScript(sentinelPublishShell(state, pipelineRunName, publishGitops)),
                volumeMounts: [
                  { name: "workspace", mountPath: "/workspace" },
                  { name: "cache", mountPath: "/cache" },
                  { name: "git-ssh", mountPath: "/git-ssh", readOnly: true },
                ],
              },
            ],
          },
        }],
      },
    },
  };
}

function tektonShellScript(body: string): string {
  return `#!/bin/sh\n${body}`;
}

function sentinelGitMirrorCacheVolume(state: SentinelCicdState): Record<string, unknown> {
  return sentinelGitMirrorCacheVolumeFromTarget(state.controlPlaneTarget);
}

export function sentinelGitMirrorCacheVolumeFromTarget(controlPlaneTarget: Record<string, unknown>): Record<string, unknown> {
  const hostPath = nonEmptyString(valueAtPath(controlPlaneTarget, "gitMirror.cacheHostPath"));
  if (hostPath !== null) return { name: "cache", hostPath: { path: hostPath, type: "DirectoryOrCreate" } };
  return { name: "cache", persistentVolumeClaim: { claimName: stringAt(controlPlaneTarget, "gitMirror.cachePvcName") } };
}

function sentinelBuildkitStateVolume(state: SentinelCicdState): Record<string, unknown> {
  const buildkitState = monitorWebBuildkitStatePlan(state.cicd);
  const mode = stringAt(buildkitState, "mode");
  if (mode === "hostPath") {
    return {
      name: "buildkit-state",
      hostPath: {
        path: stringAt(buildkitState, "path"),
        type: stringAt(buildkitState, "type"),
      },
    };
  }
  if (mode === "persistentVolumeClaim") {
    return { name: "buildkit-state", persistentVolumeClaim: { claimName: stringAt(buildkitState, "claimName") } };
  }
  if (mode === "emptyDir") {
    return { name: "buildkit-state", emptyDir: { sizeLimit: stringAt(buildkitState, "sizeLimit") } };
  }
  throw new Error(`monitorWeb.imageBuild.buildkitState.mode must be hostPath, persistentVolumeClaim or emptyDir, got ${mode}`);
}

function requireSentinelBuildkitImage(state: SentinelCicdState): string {
  const image = state.spec.buildkit?.sidecarImage;
  if (typeof image !== "string" || image.length === 0) {
    throw new Error(`config/hwlab-node-lanes.yaml ${state.spec.nodeId}/${state.spec.lane} buildkit.sidecarImage is required for pure k8s web-probe sentinel image publish`);
  }
  return image;
}

export function sentinelImageBuildProxyEnv(state: SentinelCicdState): Array<{ name: string; value: string }> {
  const proxy = state.spec.networkProfile.imageBuildProxy;
  const noProxy = proxy.noProxy.join(",");
  return [
    { name: "HTTP_PROXY", value: proxy.http },
    { name: "http_proxy", value: proxy.http },
    { name: "HTTPS_PROXY", value: proxy.https },
    { name: "https_proxy", value: proxy.https },
    { name: "ALL_PROXY", value: proxy.all },
    { name: "all_proxy", value: proxy.all },
    { name: "NO_PROXY", value: noProxy },
    { name: "no_proxy", value: noProxy },
  ];
}

export function sentinelPublishSourceShell(state: SentinelCicdState, jobName: string): string {
  const monitorWeb = record(state.image.monitorWeb);
  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");
  const envReuseMode = stringAt(monitorWeb, "envReuseMode");
  const envReuseNodeDepsPath = stringAt(monitorWeb, "envReuseNodeDepsPath");
  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 ?? "")}`,
    `source_stage_ref=${shellQuote(state.sourceHead.stageRef ?? "")}`,
    `checkout_paths_b64=${shellQuote(checkoutPathsB64)}`,
    `dockerfile_b64=${shellQuote(dockerfileB64)}`,
    `env_reuse_mode=${shellQuote(envReuseMode)}`,
    `env_reuse_node_deps_path=${shellQuote(envReuseNodeDepsPath)}`,
    "meta_dir=/workspace/meta",
    "event_log=/workspace/publish-events.log",
    "worktree=/workspace/source",
    "rm -rf \"$worktree\" \"$meta_dir\" /workspace/image-build.log /workspace/build-metadata.json",
    "mkdir -p \"$meta_dir\"",
    ": > \"$event_log\"",
    "now_ms() { seconds=$(date +%s); printf '%s\\n' $((seconds * 1000)); }",
    "write_meta() { printf '%s' \"$2\" > \"$meta_dir/$1\"; }",
    "emit_stage() { stage=$1; status=$2; started=$3; current_phase=$stage; export current_phase; finished=$(now_ms); elapsed=$((finished - started)); trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"event\":\"sentinel-publish-stage\",\"stage\":\"%s\",\"status\":\"%s\",\"elapsedMs\":%s,\"traceId\":\"%s\",\"valuesRedacted\":true}\\n' \"$stage\" \"$status\" \"$elapsed\" \"$trace_id\" | tee -a \"$event_log\"; }",
    "emit_failed() { code=$?; if [ \"$code\" -ne 0 ]; then trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"ok\":false,\"status\":\"failed\",\"traceId\":\"%s\",\"firstBreak\":{\"code\":\"child-process-exit-nonzero\",\"phase\":\"%s\",\"reason\":\"publish step command exited non-zero\",\"valuesRedacted\":true},\"error\":{\"type\":\"ChildProcessError\",\"code\":\"EXIT_NONZERO\",\"phase\":\"%s\",\"exitCode\":%s,\"stderrSummary\":\"bounded step logs contain the command failure\",\"valuesRedacted\":true},\"exitCode\":%s,\"jobName\":\"%s\",\"valuesRedacted\":true}\\n' \"$trace_id\" \"${current_phase:-source}\" \"${current_phase:-source}\" \"$code\" \"$code\" \"$job_name\" | tee -a \"$event_log\"; fi; exit \"$code\"; }",
    "trap emit_failed EXIT",
    "started_ms=$(now_ms)",
    "write_meta started_ms \"$started_ms\"",
    "write_meta source_commit \"$source_commit\"",
    "write_meta source_stage_ref \"$source_stage_ref\"",
    "test -n \"$source_commit\"",
    "test -n \"$source_stage_ref\"",
    "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'",
    "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",
    "source_fetch_started_ms=$(now_ms)",
    "write_meta source_fetch_started_ms \"$source_fetch_started_ms\"",
    "emit_stage source-fetch running \"$source_fetch_started_ms\"",
    "git fetch --depth=1 --filter=blob:none origin \"+$source_stage_ref:refs/remotes/origin/unidesk-source-snapshot\"",
    "git checkout --detach \"$source_commit\"",
    "mirror_commit=$(git rev-parse HEAD)",
    "test \"$mirror_commit\" = \"$source_commit\"",
    "write_meta mirror_commit \"$mirror_commit\"",
    "source_fetch_finished_ms=$(now_ms)",
    "write_meta source_fetch_finished_ms \"$source_fetch_finished_ms\"",
    "emit_stage source-fetch succeeded \"$source_fetch_started_ms\"",
    "env_reuse_node_deps_present=false",
    "env_reuse_node_deps_entries=0",
    "if [ -d \"$env_reuse_node_deps_path\" ]; then env_reuse_node_deps_present=true; env_reuse_node_deps_entries=$(find \"$env_reuse_node_deps_path\" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l | tr -d ' '); fi",
    "env_reuse_linked_node_deps=0",
    "rm -rf node_modules",
    "if [ \"$env_reuse_node_deps_present\" = true ]; then mkdir -p node_modules; for dep in \"$env_reuse_node_deps_path\"/*; do [ -e \"$dep\" ] || continue; ln -sf \"$dep\" \"node_modules/$(basename \"$dep\")\"; env_reuse_linked_node_deps=$((env_reuse_linked_node_deps + 1)); done; fi",
    "write_meta env_reuse_mode \"$env_reuse_mode\"",
    "write_meta env_reuse_node_deps_path \"$env_reuse_node_deps_path\"",
    "write_meta env_reuse_node_deps_present \"$env_reuse_node_deps_present\"",
    "write_meta env_reuse_node_deps_entries \"$env_reuse_node_deps_entries\"",
    "write_meta env_reuse_linked_node_deps \"$env_reuse_linked_node_deps\"",
    "node - \"$env_reuse_mode\" \"$env_reuse_node_deps_path\" \"$env_reuse_node_deps_present\" \"$env_reuse_node_deps_entries\" \"$env_reuse_linked_node_deps\" <<'NODE'",
    "const [mode, nodeDepsPath, nodeDepsPresent, nodeDepsEntries, linkedNodeDeps] = process.argv.slice(2); console.log(JSON.stringify({ event:'sentinel-publish-env-reuse', mode, nodeDepsPath, nodeDepsPresent: nodeDepsPresent === 'true', nodeDepsEntries: Number(nodeDepsEntries || 0), linkedNodeDeps: Number(linkedNodeDeps || 0), dependencyReuse: nodeDepsPresent === 'true' ? 'hit' : 'miss', valuesRedacted:true }));",
    "NODE",
    "node - \"$env_reuse_mode\" \"$env_reuse_node_deps_path\" \"$env_reuse_node_deps_present\" \"$env_reuse_node_deps_entries\" \"$env_reuse_linked_node_deps\" <<'NODE' >> \"$event_log\"",
    "const [mode, nodeDepsPath, nodeDepsPresent, nodeDepsEntries, linkedNodeDeps] = process.argv.slice(2); console.log(JSON.stringify({ event:'sentinel-publish-env-reuse', mode, nodeDepsPath, nodeDepsPresent: nodeDepsPresent === 'true', nodeDepsEntries: Number(nodeDepsEntries || 0), linkedNodeDeps: Number(linkedNodeDeps || 0), dependencyReuse: nodeDepsPresent === 'true' ? 'hit' : 'miss', valuesRedacted:true }));",
    "NODE",
    "monitor_web_verify_started_ms=$(now_ms)",
    "write_meta monitor_web_verify_started_ms \"$monitor_web_verify_started_ms\"",
    "emit_stage monitor-web-verify running \"$monitor_web_verify_started_ms\"",
    "if ! bun scripts/verify-web-probe-sentinel-monitor-web.ts > /tmp/web-probe-sentinel-monitor-web-verify.log 2>&1; then cat /tmp/web-probe-sentinel-monitor-web-verify.log; emit_stage monitor-web-verify failed \"$monitor_web_verify_started_ms\"; exit 1; fi",
    "cat /tmp/web-probe-sentinel-monitor-web-verify.log",
    "monitor_web_verify_finished_ms=$(now_ms)",
    "write_meta monitor_web_verify_finished_ms \"$monitor_web_verify_finished_ms\"",
    "emit_stage monitor-web-verify succeeded \"$monitor_web_verify_started_ms\"",
    "mkdir -p .unidesk-sentinel-bin",
    "cat > .unidesk-sentinel-bin/trans <<'SH_TRANS'",
    "#!/bin/sh",
    "exec bun /app/scripts/ssh-cli.ts \"$@\"",
    "SH_TRANS",
    "chmod 0755 .unidesk-sentinel-bin/trans",
    "DOCKERFILE_B64=\"$dockerfile_b64\" node <<'NODE'",
    "const fs = require('node:fs');",
    "fs.writeFileSync('Containerfile.web-probe-sentinel', Buffer.from(process.env.DOCKERFILE_B64 || '', 'base64'));",
    "NODE",
    "cat > .dockerignore <<'EOF_DOCKERIGNORE'",
    ".git",
    ".git/**",
    ".state",
    ".state/**",
    "logs",
    "logs/**",
    "node_modules",
    "node_modules/**",
    "**/node_modules",
    "**/node_modules/**",
    "**/dist",
    "**/dist/**",
    "**/target",
    "**/target/**",
    "**/coverage",
    "**/coverage/**",
    "npm-debug.log*",
    ".env",
    ".env.*",
    "EOF_DOCKERIGNORE",
    "context_ignore_entries=$(wc -l < .dockerignore | tr -d ' ')",
    "write_meta context_ignore_entries \"$context_ignore_entries\"",
    "chmod -R a+rwX /workspace",
    "trap - EXIT",
  ].join("\n");
}

export function sentinelPublishImageBuildShell(state: SentinelCicdState, jobName: string): string {
  const monitorWeb = record(state.image.monitorWeb);
  const imageBuildPackageMode = stringAt(monitorWeb, "imageBuildPackageMode");
  const imageBuildNetworkMode = stringAt(monitorWeb, "imageBuildNetworkMode");
  const imageBuildProxySource = stringAt(monitorWeb, "imageBuildProxySource");
  const imageBuildProxy = state.spec.networkProfile.imageBuildProxy;
  const imageBuildNoProxy = imageBuildProxy.noProxy.join(",");
  return [
    "set -eu",
    `job_name=${shellQuote(jobName)}`,
    `image_ref=${shellQuote(state.image.ref)}`,
    `image_build_builder=${shellQuote(requireSentinelBuildkitImage(state))}`,
    `image_build_package_mode=${shellQuote(imageBuildPackageMode)}`,
    `image_build_network_mode=${shellQuote(imageBuildNetworkMode)}`,
    `image_build_proxy_source=${shellQuote(imageBuildProxySource)}`,
    `image_build_http_proxy=${shellQuote(imageBuildProxy.http)}`,
    `image_build_https_proxy=${shellQuote(imageBuildProxy.https)}`,
    `image_build_all_proxy=${shellQuote(imageBuildProxy.all)}`,
    `image_build_no_proxy=${shellQuote(imageBuildNoProxy)}`,
    "meta_dir=/workspace/meta",
    "event_log=/workspace/publish-events.log",
    "build_log=/workspace/image-build.log",
    "now_ms() { seconds=$(date +%s); printf '%s\\n' $((seconds * 1000)); }",
    "write_meta() { printf '%s' \"$2\" > \"$meta_dir/$1\"; }",
    "emit_stage() { stage=$1; status=$2; started=$3; current_phase=$stage; export current_phase; finished=$(now_ms); elapsed=$((finished - started)); trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"event\":\"sentinel-publish-stage\",\"stage\":\"%s\",\"status\":\"%s\",\"elapsedMs\":%s,\"traceId\":\"%s\",\"valuesRedacted\":true}\\n' \"$stage\" \"$status\" \"$elapsed\" \"$trace_id\" | tee -a \"$event_log\"; }",
    "failure_code=child-process-exit-nonzero",
    "failure_reason='image build command exited non-zero'",
    "failure_error_type=ChildProcessError",
    "failure_error_code=EXIT_NONZERO",
    "buildkitd_pid=''",
    "isolate_buildkit_otel() { unset TRACEPARENT TRACESTATE OTEL_EXPORTER_OTLP_ENDPOINT OTEL_EXPORTER_OTLP_TRACES_ENDPOINT OTEL_EXPORTER_OTLP_PROTOCOL OTEL_EXPORTER_OTLP_TRACES_PROTOCOL OTEL_EXPORTER_OTLP_HEADERS OTEL_EXPORTER_OTLP_TRACES_HEADERS; export OTEL_SDK_DISABLED=true OTEL_TRACES_EXPORTER=none; }",
    "cleanup_buildkitd() { if [ -n \"$buildkitd_pid\" ] && kill -0 \"$buildkitd_pid\" 2>/dev/null; then kill -TERM \"$buildkitd_pid\" 2>/dev/null || true; cleanup_attempt=0; while [ \"$cleanup_attempt\" -lt 5 ] && kill -0 \"$buildkitd_pid\" 2>/dev/null; do cleanup_attempt=$((cleanup_attempt + 1)); sleep 1; done; if kill -0 \"$buildkitd_pid\" 2>/dev/null; then kill -KILL \"$buildkitd_pid\" 2>/dev/null || true; fi; wait \"$buildkitd_pid\" 2>/dev/null || true; fi; }",
    "emit_failed() { code=$?; cleanup_buildkitd; if [ \"$code\" -ne 0 ]; then trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"ok\":false,\"status\":\"failed\",\"traceId\":\"%s\",\"firstBreak\":{\"code\":\"%s\",\"phase\":\"%s\",\"reason\":\"%s\",\"valuesRedacted\":true},\"error\":{\"type\":\"%s\",\"code\":\"%s\",\"phase\":\"%s\",\"exitCode\":%s,\"stderrSummary\":\"bounded step logs contain the command failure\",\"valuesRedacted\":true},\"exitCode\":%s,\"jobName\":\"%s\",\"valuesRedacted\":true}\\n' \"$trace_id\" \"$failure_code\" \"${current_phase:-image-build}\" \"$failure_reason\" \"$failure_error_type\" \"$failure_error_code\" \"${current_phase:-image-build}\" \"$code\" \"$code\" \"$job_name\" | tee -a \"$event_log\"; fi; exit \"$code\"; }",
    "trap emit_failed EXIT",
    "cd /workspace/source",
    "image_build_http_proxy_present=false; if [ -n \"$image_build_http_proxy\" ]; then image_build_http_proxy_present=true; fi",
    "image_build_https_proxy_present=false; if [ -n \"$image_build_https_proxy\" ]; then image_build_https_proxy_present=true; fi",
    "image_build_all_proxy_present=false; if [ -n \"$image_build_all_proxy\" ]; then image_build_all_proxy_present=true; fi",
    "image_build_no_proxy_present=false; if [ -n \"$image_build_no_proxy\" ]; then image_build_no_proxy_present=true; fi",
    "write_meta image_build_builder \"$image_build_builder\"",
    "write_meta image_build_package_mode \"$image_build_package_mode\"",
    "write_meta image_build_network_mode \"$image_build_network_mode\"",
    "write_meta image_build_proxy_source \"$image_build_proxy_source\"",
    "write_meta image_build_http_proxy_present \"$image_build_http_proxy_present\"",
    "write_meta image_build_https_proxy_present \"$image_build_https_proxy_present\"",
    "write_meta image_build_all_proxy_present \"$image_build_all_proxy_present\"",
    "write_meta image_build_no_proxy_present \"$image_build_no_proxy_present\"",
    "image_build_started_ms=$(now_ms)",
    "write_meta image_build_started_ms \"$image_build_started_ms\"",
    "emit_stage image-build running \"$image_build_started_ms\"",
    "buildkit_socket=/run/user/$(id -u)/buildkit/buildkitd.sock",
    "buildkit_address=unix://$buildkit_socket",
    "buildkit_log=/workspace/buildkitd.log",
    "mkdir -p \"$(dirname \"$buildkit_socket\")\"",
    "rm -f \"$buildkit_socket\"",
    "( isolate_buildkit_otel; exec rootlesskit buildkitd --addr \"$buildkit_address\" ${BUILDKITD_FLAGS:-} ) > \"$buildkit_log\" 2>&1 &",
    "buildkitd_pid=$!",
    "buildkit_ready=false",
    "buildkit_probe_attempt=0",
    "while [ \"$buildkit_probe_attempt\" -lt 30 ]; do buildkit_probe_attempt=$((buildkit_probe_attempt + 1)); if [ -S \"$buildkit_socket\" ] && ( isolate_buildkit_otel; exec buildctl --addr \"$buildkit_address\" debug workers ) >/dev/null 2>&1; then buildkit_ready=true; break; fi; if ! kill -0 \"$buildkitd_pid\" 2>/dev/null; then break; fi; sleep 1; done",
    "if [ \"$buildkit_ready\" != true ]; then cat \"$buildkit_log\"; failure_code=buildkit-not-ready; failure_reason=readiness-timeout; failure_error_type=BuildKitReadinessError; failure_error_code=BUILDKIT_NOT_READY; emit_stage image-build failed \"$image_build_started_ms\"; exit 1; fi",
    "build_status=0",
    "( isolate_buildkit_otel; exec env HTTP_PROXY=\"$image_build_http_proxy\" HTTPS_PROXY=\"$image_build_https_proxy\" ALL_PROXY=\"$image_build_all_proxy\" NO_PROXY=\"$image_build_no_proxy\" http_proxy=\"$image_build_http_proxy\" https_proxy=\"$image_build_https_proxy\" all_proxy=\"$image_build_all_proxy\" no_proxy=\"$image_build_no_proxy\" buildctl --addr \"$buildkit_address\" build --allow network.host --frontend dockerfile.v0 --local context=/workspace/source --local dockerfile=/workspace/source --opt filename=Containerfile.web-probe-sentinel --opt \"network=$image_build_network_mode\" --opt \"build-arg:HTTP_PROXY=$image_build_http_proxy\" --opt \"build-arg:HTTPS_PROXY=$image_build_https_proxy\" --opt \"build-arg:ALL_PROXY=$image_build_all_proxy\" --opt \"build-arg:NO_PROXY=$image_build_no_proxy\" --opt \"build-arg:http_proxy=$image_build_http_proxy\" --opt \"build-arg:https_proxy=$image_build_https_proxy\" --opt \"build-arg:all_proxy=$image_build_all_proxy\" --opt \"build-arg:no_proxy=$image_build_no_proxy\" --metadata-file /workspace/build-metadata.json --output \"type=image,name=$image_ref,push=true,registry.insecure=true\" ) > \"$build_log\" 2>&1 || build_status=$?",
    "cat \"$build_log\"",
    "image_build_finished_ms=$(now_ms)",
    "write_meta image_build_finished_ms \"$image_build_finished_ms\"",
    "metadata_compact=''",
    "if [ -s /workspace/build-metadata.json ]; then metadata_compact=$(tr -d '\\n' < /workspace/build-metadata.json); fi",
    "digest=$(printf '%s' \"$metadata_compact\" | sed -n 's/.*\"containerimage.digest\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p' | head -n 1)",
    "if [ -z \"$digest\" ]; then digest=$(sed -n 's/.*exporting manifest \\(sha256:[0-9a-f]\\{64\\}\\).*/\\1/p' \"$build_log\" | tail -n 1); fi",
    "if [ \"$build_status\" -ne 0 ] && [ -z \"$digest\" ]; then emit_stage image-build failed \"$image_build_started_ms\"; exit \"$build_status\"; fi",
    "if [ \"$build_status\" -ne 0 ]; then printf '{\"event\":\"sentinel-publish-warning\",\"stage\":\"image-build\",\"warning\":\"buildctl returned non-zero after producing image digest; continuing with digest-pinned publish\",\"exitCode\":%s,\"valuesRedacted\":true}\\n' \"$build_status\" | tee -a \"$event_log\"; fi",
    "test -n \"$digest\"",
    "repo_no_tag=${image_ref%:*}",
    "digest_ref=\"$repo_no_tag@$digest\"",
    "write_meta digest \"$digest\"",
    "write_meta digest_ref \"$digest_ref\"",
    "emit_stage image-build succeeded \"$image_build_started_ms\"",
    "cleanup_buildkitd",
    "buildkitd_pid=''",
    "trap - EXIT",
  ].join("\n");
}

export function sentinelPublishShell(state: SentinelCicdState, jobName: string, publishGitops: boolean, featureConfigSchemaStage = ""): 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");
  return [
    "set -eu",
    `job_name=${shellQuote(jobName)}`,
    `image_ref=${shellQuote(state.image.ref)}`,
    `image_repository=${shellQuote(state.image.repository)}`,
    `gitops_branch=${shellQuote(stringAt(state.cicd, "argo.targetRevision"))}`,
    "gitops_read_url=${GITOPS_READ_URL:?GITOPS_READ_URL is required}",
    "gitops_username=${GITOPS_USERNAME:?GITOPS_USERNAME is required}",
    `files_b64=${shellQuote(filesB64)}`,
    "meta_dir=/workspace/meta",
    "event_log=/workspace/publish-events.log",
    "build_log=/workspace/image-build.log",
    "now_ms() { seconds=$(date +%s); printf '%s\\n' $((seconds * 1000)); }",
    "read_meta() { cat \"$meta_dir/$1\"; }",
    "emit_stage() { stage=$1; status=$2; started=$3; current_phase=$stage; export current_phase; finished=$(now_ms); elapsed=$((finished - started)); trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"event\":\"sentinel-publish-stage\",\"stage\":\"%s\",\"status\":\"%s\",\"elapsedMs\":%s,\"traceId\":\"%s\",\"valuesRedacted\":true}\\n' \"$stage\" \"$status\" \"$elapsed\" \"$trace_id\"; }",
    "emit_failed() { code=$?; if [ \"$code\" -ne 0 ]; then trace_id=$(printf '%s' \"${TRACEPARENT:-}\" | cut -d- -f2); printf '{\"ok\":false,\"status\":\"failed\",\"traceId\":\"%s\",\"firstBreak\":{\"code\":\"child-process-exit-nonzero\",\"phase\":\"%s\",\"reason\":\"GitOps publish command exited non-zero\",\"valuesRedacted\":true},\"error\":{\"type\":\"ChildProcessError\",\"code\":\"EXIT_NONZERO\",\"phase\":\"%s\",\"exitCode\":%s,\"stderrSummary\":\"bounded step logs contain the command failure\",\"valuesRedacted\":true},\"exitCode\":%s,\"jobName\":\"%s\",\"valuesRedacted\":true}\\n' \"$trace_id\" \"${current_phase:-gitops-publish}\" \"${current_phase:-gitops-publish}\" \"$code\" \"$code\" \"$job_name\"; fi; exit \"$code\"; }",
    "trap emit_failed EXIT",
    "if [ -f \"$event_log\" ]; then cat \"$event_log\"; fi",
    "askpass=/workspace/gitea-askpass.sh",
    "cat >\"$askpass\" <<'ASKPASS'",
    "#!/bin/sh",
    "case \"$1\" in",
    "  *Username*) printf '%s\\n' \"${GITEA_USERNAME:?}\" ;;",
    "  *Password*) cat /workspace/gitea-auth/token ;;",
    "  *) exit 1 ;;",
    "esac",
    "ASKPASS",
    "chmod 700 \"$askpass\"",
    "export GITEA_USERNAME=\"$gitops_username\" GIT_ASKPASS=\"$askpass\" GIT_ASKPASS_REQUIRE=force GIT_TERMINAL_PROMPT=0",
    "started_ms=$(read_meta started_ms)",
    "source_commit=$(read_meta source_commit)",
    "source_stage_ref=$(read_meta source_stage_ref)",
    "mirror_commit=$(read_meta mirror_commit)",
    "source_fetch_started_ms=$(read_meta source_fetch_started_ms)",
    "source_fetch_finished_ms=$(read_meta source_fetch_finished_ms)",
    "monitor_web_verify_started_ms=$(read_meta monitor_web_verify_started_ms)",
    "monitor_web_verify_finished_ms=$(read_meta monitor_web_verify_finished_ms)",
    "image_build_started_ms=$(read_meta image_build_started_ms)",
    "image_build_finished_ms=$(read_meta image_build_finished_ms)",
    "digest_ref=$(read_meta digest_ref)",
    "env_reuse_mode=$(read_meta env_reuse_mode 2>/dev/null || printf 'k8s-buildkit-and-ci-node-deps')",
    "env_reuse_node_deps_path=$(read_meta env_reuse_node_deps_path 2>/dev/null || printf '-')",
    "env_reuse_node_deps_present=$(read_meta env_reuse_node_deps_present)",
    "env_reuse_node_deps_entries=$(read_meta env_reuse_node_deps_entries)",
    "env_reuse_linked_node_deps=$(read_meta env_reuse_linked_node_deps)",
    "image_build_builder=$(read_meta image_build_builder)",
    "image_build_package_mode=$(read_meta image_build_package_mode)",
    "image_build_network_mode=$(read_meta image_build_network_mode)",
    "image_build_proxy_source=$(read_meta image_build_proxy_source)",
    "image_build_http_proxy_present=$(read_meta image_build_http_proxy_present)",
    "image_build_https_proxy_present=$(read_meta image_build_https_proxy_present)",
    "image_build_all_proxy_present=$(read_meta image_build_all_proxy_present)",
    "image_build_no_proxy_present=$(read_meta image_build_no_proxy_present)",
    "context_ignore_entries=$(read_meta context_ignore_entries)",
    "image_build_cache_hits=$(grep -Eci '(^|[[:space:]])CACHED([[:space:]]|$)|Using cache|cache hit' \"$build_log\" 2>/dev/null || true)",
    "image_build_step_lines=$(grep -Eci '^(#|STEP|[[:space:]]*=>)' \"$build_log\" 2>/dev/null || true)",
    "image_build_log_tail_b64=$(tail -n 30 \"$build_log\" 2>/dev/null | tail -c 4000 | base64 | tr -d '\\n')",
    "gitops_commit=''",
    "changed=false",
    "file_count=0",
    "gitops_started_ms=$(now_ms)",
    "if [ \"$files_b64\" != \"W10=\" ]; then",
    "  emit_stage gitops running \"$gitops_started_ms\"",
    "  gitops_worktree=\"/tmp/$job_name/gitops\"",
    "  git clone --no-checkout \"$gitops_read_url\" \"$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",
    ...(featureConfigSchemaStage.length === 0 ? [] : [featureConfigSchemaStage]),
    "  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)",
    "  emit_stage gitops succeeded \"$gitops_started_ms\"",
    "else",
    "  emit_stage gitops skipped \"$gitops_started_ms\"",
    "fi",
    "gitops_finished_ms=$(now_ms)",
    "finished_ms=$(now_ms)",
    `source_authority=${shellQuote(state.sourceHead.sourceAuthority)}`,
    "node - \"$job_name\" \"$source_commit\" \"$source_stage_ref\" \"$mirror_commit\" \"$image_ref\" \"$digest_ref\" \"$gitops_commit\" \"$changed\" \"$file_count\" \"$started_ms\" \"$finished_ms\" \"$source_fetch_started_ms\" \"$source_fetch_finished_ms\" \"$monitor_web_verify_started_ms\" \"$monitor_web_verify_finished_ms\" \"$image_build_started_ms\" \"$image_build_finished_ms\" \"$gitops_started_ms\" \"$gitops_finished_ms\" \"$env_reuse_mode\" \"$env_reuse_node_deps_path\" \"$env_reuse_node_deps_present\" \"$env_reuse_node_deps_entries\" \"$env_reuse_linked_node_deps\" \"$image_build_cache_hits\" \"$image_build_step_lines\" \"$image_build_log_tail_b64\" \"$image_build_builder\" \"$image_build_package_mode\" \"$image_build_network_mode\" \"$image_build_proxy_source\" \"$image_build_http_proxy_present\" \"$image_build_https_proxy_present\" \"$image_build_all_proxy_present\" \"$image_build_no_proxy_present\" \"$context_ignore_entries\" \"$source_authority\" <<'NODE'",
    "const [jobName, sourceCommit, sourceStageRef, mirrorCommit, imageRef, digestRef, gitopsCommit, changed, fileCount, startedMs, finishedMs, sourceFetchStartedMs, sourceFetchFinishedMs, monitorWebVerifyStartedMs, monitorWebVerifyFinishedMs, imageBuildStartedMs, imageBuildFinishedMs, gitopsStartedMs, gitopsFinishedMs, envReuseMode, envReuseNodeDepsPath, envReuseNodeDepsPresent, envReuseNodeDepsEntries, envReuseLinkedNodeDeps, imageBuildCacheHits, imageBuildStepLines, imageBuildLogTailB64, imageBuildBuilder, imageBuildPackageMode, imageBuildNetworkMode, imageBuildProxySource, imageBuildHttpProxyPresent, imageBuildHttpsProxyPresent, imageBuildAllProxyPresent, imageBuildNoProxyPresent, contextIgnoreEntries, sourceAuthority] = process.argv.slice(2);",
    "const elapsed = (start, finish) => Number(finish) - Number(start);",
    "const cacheHits = Number(imageBuildCacheHits || 0);",
    "console.log(JSON.stringify({ ok:true, status:'succeeded', jobName, sourceCommit, sourceStageRef, sourceAuthority, mirrorCommit, imageRef, digestRef, gitopsCommit: gitopsCommit || null, changed: changed === 'true', fileCount: Number(fileCount || 0), elapsedMs: elapsed(startedMs, finishedMs), stageTimings: { sourceFetchMs: elapsed(sourceFetchStartedMs, sourceFetchFinishedMs), monitorWebVerifyMs: elapsed(monitorWebVerifyStartedMs, monitorWebVerifyFinishedMs), imageBuildMs: elapsed(imageBuildStartedMs, imageBuildFinishedMs), gitopsMs: elapsed(gitopsStartedMs, gitopsFinishedMs), totalMs: elapsed(startedMs, finishedMs), valuesRedacted:true }, envReuse: { mode: envReuseMode, nodeDepsPath: envReuseNodeDepsPath, nodeDepsPresent: envReuseNodeDepsPresent === 'true', nodeDepsEntries: Number(envReuseNodeDepsEntries || 0), linkedNodeDeps: Number(envReuseLinkedNodeDeps || 0), dependencyReuse: envReuseNodeDepsPresent === 'true' ? 'hit' : 'miss', valuesRedacted:true }, imageBuild: { builder: 'k8s-buildkit-rootless', builderImage: imageBuildBuilder, cacheHitLines: cacheHits, stepLines: Number(imageBuildStepLines || 0), layerCache: cacheHits > 0 ? 'hit' : 'unknown-or-miss', packageMode: imageBuildPackageMode, networkMode: imageBuildNetworkMode, proxySource: imageBuildProxySource, proxy: { httpProxyPresent: imageBuildHttpProxyPresent === 'true', httpsProxyPresent: imageBuildHttpsProxyPresent === 'true', allProxyPresent: imageBuildAllProxyPresent === 'true', noProxyPresent: imageBuildNoProxyPresent === 'true', valuesRedacted:true }, contextIgnoreEntries: Number(contextIgnoreEntries || 0), verifyLocation: 'pre-image-build', logTail: Buffer.from(imageBuildLogTailB64 || '', 'base64').toString('utf8'), valuesRedacted:true }, completedStages: ['source-fetch', 'monitor-web-verify', 'image-build', gitopsCommit ? 'gitops' : 'gitops-skipped'], 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`,
  }];
}

export 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 };
}

export 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 createTektonPipelineRunScript(namespace: string, manifest: Record<string, unknown>): string {
  const yaml = `${Bun.YAML.stringify(manifest).trim()}\n`;
  const pipelineRunName = stringAt(manifest, "metadata.name");
  return [
    "set -eu",
    `pipeline_run=${shellQuote(pipelineRunName)}`,
    `namespace=${shellQuote(namespace)}`,
    "tmp=$(mktemp)",
    `cat >"$tmp" <<'YAML'\n${yaml}YAML`,
    "if kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" >/dev/null 2>&1; then",
    "  printf '%s\\n' \"sentinel publish PipelineRun already exists; reusing $pipeline_run\"",
    "  exit 0",
    "fi",
    "if ! kubectl create -f \"$tmp\"; then",
    "  if kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" >/dev/null 2>&1; then",
    "    printf '%s\\n' \"sentinel publish PipelineRun appeared concurrently; reusing $pipeline_run\"",
    "    exit 0",
    "  fi",
    "  exit 1",
    "fi",
  ].join("\n");
}

export 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)",
    "active=$(kubectl -n \"$namespace\" get job \"$job\" -o jsonpath='{.status.active}' 2>/dev/null)",
    "pod=$(kubectl -n \"$namespace\" get pod -l job-name=\"$job\" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)",
    "pod_phase=''",
    "reason=''",
    "containers_b64=''",
    "if [ -n \"$pod\" ]; then pod_phase=$(kubectl -n \"$namespace\" get pod \"$pod\" -o jsonpath='{.status.phase}' 2>/dev/null); reason=$(kubectl -n \"$namespace\" get pod \"$pod\" -o jsonpath='{.status.reason}' 2>/dev/null); containers_b64=$(kubectl -n \"$namespace\" get pod \"$pod\" -o json 2>/dev/null | node -e 'let body=\"\";process.stdin.on(\"data\",c=>body+=c).on(\"end\",()=>{try{const pod=JSON.parse(body);const all=[...(pod.status?.initContainerStatuses||[]),...(pod.status?.containerStatuses||[])];console.log(Buffer.from(JSON.stringify(all.map(item=>({name:item.name,phase:item.state?.terminated?\"terminated\":item.state?.waiting?\"waiting\":item.state?.running?\"running\":\"unknown\",exitCode:item.state?.terminated?.exitCode??null,reason:item.state?.terminated?.reason??item.state?.waiting?.reason??null,message:item.state?.terminated?.message??item.state?.waiting?.message??null})))).toString(\"base64\"))}catch{console.log(\"\")}})' | tr -d '\\n'); fi",
    "logs_tail=''",
    "container_logs_b64=''",
    "if [ -n \"$pod\" ]; then logs_tail=$(kubectl -n \"$namespace\" logs \"$pod\" --all-containers=true --tail=80 2>/dev/null | tail -c 6000 | base64 | tr -d '\\n'); container_logs_b64=$(for container in $(kubectl -n \"$namespace\" get pod \"$pod\" -o jsonpath='{.spec.initContainers[*].name} {.spec.containers[*].name}' 2>/dev/null); do printf '%s\\t%s\\n' \"$container\" \"$(kubectl -n \"$namespace\" logs \"$pod\" -c \"$container\" --tail=80 2>/dev/null | tail -c 6000 | base64 | tr -d '\\n')\"; done | base64 | tr -d '\\n'); fi",
    "node - \"$succeeded\" \"$failed\" \"$active\" \"$pod\" \"$pod_phase\" \"$reason\" \"$containers_b64\" \"$logs_tail\" \"$container_logs_b64\" <<'NODE'",
    "const [succeeded, failed, active, pod, podPhase, reason, containersB64, logsB64, containerLogsB64] = process.argv.slice(2);",
    "let containers=[];try{containers=JSON.parse(Buffer.from(containersB64 || '', 'base64').toString('utf8'))}catch{}",
    "const containerLogs={};for(const line of Buffer.from(containerLogsB64 || '', 'base64').toString('utf8').split(/\\r?\\n/)){const tab=line.indexOf('\\t');if(tab>0)containerLogs[line.slice(0,tab)]=Buffer.from(line.slice(tab+1),'base64').toString('utf8')}",
    "console.log(JSON.stringify({ succeeded: Number(succeeded || 0) > 0, failed: Number(failed || 0) > 0, active: Number(active || 0) > 0, pod: pod || null, podPhase: podPhase || null, reason: reason || null, containers, logsTail: Buffer.from(logsB64 || '', 'base64').toString('utf8'), containerLogs, valuesRedacted: true }));",
    "NODE",
  ].join("\n");
}

function probeTektonPipelineRunScript(namespace: string, pipelineRunName: string): string {
  return [
    "set +e",
    `namespace=${shellQuote(namespace)}`,
    `pipeline_run=${shellQuote(pipelineRunName)}`,
    "condition_status=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[?(@.type==\"Succeeded\")].status}' 2>/dev/null || true)",
    "condition_reason=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[?(@.type==\"Succeeded\")].reason}' 2>/dev/null || true)",
    "condition_message_b64=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[?(@.type==\"Succeeded\")].message}' 2>/dev/null | head -c 1600 | base64 | tr -d '\\n' || true)",
    "if [ -z \"$condition_status\" ]; then condition_status=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[0].status}' 2>/dev/null || true); fi",
    "if [ -z \"$condition_reason\" ]; then condition_reason=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[0].reason}' 2>/dev/null || true); fi",
    "if [ -z \"$condition_message_b64\" ]; then condition_message_b64=$(kubectl -n \"$namespace\" get pipelinerun \"$pipeline_run\" -o jsonpath='{.status.conditions[0].message}' 2>/dev/null | head -c 1600 | base64 | tr -d '\\n' || true); fi",
    "task_run=$(kubectl -n \"$namespace\" get taskrun -l tekton.dev/pipelineRun=\"$pipeline_run\" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)",
    "pod=$(kubectl -n \"$namespace\" get pod -l tekton.dev/pipelineRun=\"$pipeline_run\" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)",
    "pod_phase=''",
    "if [ -n \"$pod\" ]; then pod_phase=$(kubectl -n \"$namespace\" get pod \"$pod\" -o jsonpath='{.status.phase}' 2>/dev/null || true); fi",
    "logs_tail=''",
    "if [ -n \"$pod\" ]; then logs_tail=$({ kubectl -n \"$namespace\" logs \"$pod\" --all-containers=true --tail=80 2>/dev/null || true; kubectl -n \"$namespace\" logs \"$pod\" -c step-publish --tail=100 2>/dev/null || true; } | tail -c 6000 | base64 | tr -d '\\n'); fi",
    "node - \"$condition_status\" \"$condition_reason\" \"$condition_message_b64\" \"$task_run\" \"$pod\" \"$pod_phase\" \"$logs_tail\" <<'NODE'",
    "const [conditionStatus, conditionReason, conditionMessageB64, taskRun, pod, podPhase, logsB64] = process.argv.slice(2);",
    "const message = Buffer.from(conditionMessageB64 || '', 'base64').toString('utf8');",
    "const active = conditionStatus === 'Unknown' || (!conditionStatus && (podPhase === 'Pending' || podPhase === 'Running'));",
    "console.log(JSON.stringify({ succeeded: conditionStatus === 'True', failed: conditionStatus === 'False', active, conditionStatus: conditionStatus || null, conditionReason: conditionReason || null, conditionMessage: message || null, taskRun: taskRun || null, pod: pod || null, podPhase: podPhase || null, logsTail: Buffer.from(logsB64 || '', 'base64').toString('utf8'), valuesRedacted: true }));",
    "NODE",
  ].join("\n");
}

export function sentinelPayloadFromLogs(logsTail: string): Record<string, unknown> {
  const parsed = lastJsonObjectFromText(logsTail);
  if (parsed === null) return {};
  const data = isRecord(parsed.data) ? parsed.data : null;
  if (data !== null && (data.ok === true || data.ok === false)) {
    return data.command === undefined && typeof parsed.command === "string" ? { ...data, command: parsed.command } : data;
  }
  return parsed.ok === true || parsed.ok === false ? parsed : {};
}

function lastJsonObjectFromText(text: string): Record<string, unknown> | null {
  let last: Record<string, unknown> | null = null;
  for (let start = text.indexOf("{"); start >= 0;) {
    const candidate = jsonObjectAt(text, start);
    if (candidate === null) {
      start = text.indexOf("{", start + 1);
      continue;
    }
    if (candidate.value.ok === true || candidate.value.ok === false) last = candidate.value;
    start = text.indexOf("{", candidate.end + 1);
  }
  return last;
}

function jsonObjectAt(text: string, start: number): { value: Record<string, unknown>; end: number } | null {
  let depth = 0;
  let inString = false;
  let escaped = false;
  for (let index = start; index < text.length; index += 1) {
    const char = text[index];
    if (inString) {
      if (escaped) escaped = false;
      else if (char === "\\") escaped = true;
      else if (char === "\"") inString = false;
      continue;
    }
    if (char === "\"") { inString = true; continue; }
    if (char === "{") { depth += 1; continue; }
    if (char === "}" && --depth === 0) {
      const value = parseJsonObject(text.slice(start, index + 1));
      return value === null ? null : { value, end: index };
    }
  }
  return null;
}

function withSentinelRemoteJobDiagnostics(state: SentinelCicdState, result: SentinelRemoteJobResult, domain: "source-mirror" | "publish"): SentinelRemoteJobResult {
  return { ...result, diagnostics: sentinelRemoteJobDiagnostics(state, result, domain), valuesRedacted: true };
}

function sentinelRemoteJobDiagnostics(state: SentinelCicdState, result: SentinelRemoteJobResult, domain: "source-mirror" | "publish"): Record<string, unknown> {
  const namespace = stringAt(state.cicd, "builder.namespace");
  const probe = record(result.probe);
  const logsTail = typeof probe.logsTail === "string" ? probe.logsTail : "";
  const events = sentinelStageEventsFromLogs(logsTail, domain);
  const envReuse = sentinelEnvReuseFromLogs(logsTail);
  const completedStages = sentinelCompletedStages(events, record(result.payload));
  const stageTimings = sentinelStageTimingSummary(events, record(result.payload), result.elapsedMs);
  const currentPhase = sentinelCurrentRemotePhase(result, events, domain);
  const isPipelineRun = result.resourceKind === "PipelineRun";
  const commands = {
    cliStatus: domain === "publish"
      ? `bun scripts/cli.ts web-probe sentinel control-plane status --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)}`
      : `bun scripts/cli.ts web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)}`,
    logs: result.jobName === "-"
      ? "-"
      : isPipelineRun
        ? `trans ${stringAt(state.controlPlaneNode, "kubeRoute")} kubectl -n ${namespace} logs -l tekton.dev/pipelineRun=${result.jobName} --all-containers=true --tail=120`
        : `trans ${stringAt(state.controlPlaneNode, "kubeRoute")} kubectl -n ${namespace} logs job/${result.jobName} --all-containers=true --tail=120`,
    describe: result.jobName === "-"
      ? "-"
      : isPipelineRun
        ? `trans ${stringAt(state.controlPlaneNode, "kubeRoute")} kubectl -n ${namespace} describe pipelinerun/${result.jobName}`
        : `trans ${stringAt(state.controlPlaneNode, "kubeRoute")} kubectl -n ${namespace} describe job/${result.jobName}`,
    gitMirrorStatus: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
    gitMirrorSync: `bun scripts/cli.ts hwlab nodes git-mirror sync --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm`,
    gitMirrorFlush: `bun scripts/cli.ts hwlab nodes git-mirror flush --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm --wait`,
    controlPlaneApply: `bun scripts/cli.ts web-probe sentinel control-plane apply --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --confirm --wait`,
    publishCurrent: `bun scripts/cli.ts web-probe sentinel publish-current --node ${state.spec.nodeId} --lane ${state.spec.lane}${sentinelCliSuffix(state)} --confirm --wait`,
    valuesRedacted: true,
  };
  return {
    domain,
    resourceKind: result.resourceKind ?? "Job",
    pipelineRun: isPipelineRun ? result.jobName : null,
    taskRun: probe.taskRun ?? null,
    currentPhase,
    completedStages,
    stageTimings,
    envReuse,
    pod: probe.pod ?? null,
    podPhase: probe.podPhase ?? null,
    active: probe.active ?? null,
    conditionStatus: probe.conditionStatus ?? null,
    conditionReason: probe.conditionReason ?? null,
    recentLogSummary: sentinelRecentLogSummary(logsTail),
    commands,
    valuesRedacted: true,
  };
}

function sentinelEnvReuseFromLogs(logsTail: string): Record<string, unknown> | null {
  const lines = logsTail.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
  for (let index = lines.length - 1; index >= 0; index -= 1) {
    const parsed = parseJsonObject(lines[index]);
    if (parsed !== null && parsed.event === "sentinel-publish-env-reuse") return { ...parsed, valuesRedacted: true };
  }
  return null;
}

function sentinelStageEventsFromLogs(logsTail: string, domain: "source-mirror" | "publish"): Record<string, unknown>[] {
  const expectedEvent = domain === "publish" ? "sentinel-publish-stage" : "sentinel-source-mirror-stage";
  return logsTail
    .split(/\r?\n/u)
    .map((line) => parseJsonObject(line.trim()))
    .filter((item): item is Record<string, unknown> => item !== null && item.event === expectedEvent);
}

function sentinelCompletedStages(events: readonly Record<string, unknown>[], payload: Record<string, unknown>): string[] {
  const completed = events
    .filter((event) => event.status === "succeeded" || event.status === "skipped")
    .map((event) => `${text(event.stage)}:${text(event.status)}`);
  const payloadStages = Array.isArray(payload.completedStages) ? payload.completedStages.map(text) : [];
  return Array.from(new Set([...completed, ...payloadStages])).filter((item) => item !== "-");
}

function sentinelStageTimingSummary(events: readonly Record<string, unknown>[], payload: Record<string, unknown>, fallbackTotalMs: unknown): Record<string, unknown> {
  const payloadTimings = record(payload.stageTimings);
  const eventElapsed = (stage: string): number | null => {
    const event = [...events].reverse().find((item) => item.stage === stage && (item.status === "succeeded" || item.status === "skipped" || item.status === "failed"));
    return event === undefined ? null : finiteNumberOrNull(event.elapsedMs);
  };
  const sourceFetchMs = finiteNumberOrNull(payloadTimings.sourceFetchMs) ?? eventElapsed("source-fetch") ?? eventElapsed("source-mirror-fetch");
  const monitorWebVerifyMs = finiteNumberOrNull(payloadTimings.monitorWebVerifyMs) ?? eventElapsed("monitor-web-verify");
  const imageBuildMs = finiteNumberOrNull(payloadTimings.imageBuildMs) ?? eventElapsed("image-build");
  const gitopsMs = finiteNumberOrNull(payloadTimings.gitopsMs) ?? eventElapsed("gitops");
  const known = [sourceFetchMs, monitorWebVerifyMs, imageBuildMs, gitopsMs].filter((item): item is number => item !== null);
  const summedTotalMs = known.length === 0 ? null : known.reduce((sum, item) => sum + item, 0);
  const totalMs = finiteNumberOrNull(payloadTimings.totalMs)
    ?? finiteNumberOrNull(payload.elapsedMs)
    ?? finiteNumberOrNull(fallbackTotalMs)
    ?? summedTotalMs;
  const result = {
    sourceFetchMs,
    monitorWebVerifyMs,
    imageBuildMs,
    gitopsMs,
    totalMs,
    valuesRedacted: true,
  };
  return Object.values(result).some((item) => item !== null && item !== true) ? result : {};
}

function sentinelCurrentRemotePhase(result: SentinelRemoteJobResult, events: readonly Record<string, unknown>[], domain: "source-mirror" | "publish"): string {
  if (result.phase === "job-succeeded" || result.phase === "pipelinerun-succeeded") return "completed";
  if (result.phase === "create-job" || result.phase === "create-pipelinerun") return result.phase;
  const reversed = [...events].reverse();
  const failed = reversed.find((event) => event.status === "failed");
  if (failed !== undefined) return text(failed.stage);
  const running = reversed.find((event) => event.status === "running");
  if (running !== undefined) return text(running.stage);
  const completed = new Set(events.filter((event) => event.status === "succeeded" || event.status === "skipped").map((event) => text(event.stage)));
  const order = domain === "publish" ? ["source-fetch", "monitor-web-verify", "image-build", "gitops"] : ["source-mirror-fetch"];
  const next = order.find((stage) => !completed.has(stage));
  return next ?? result.phase;
}

function sentinelRecentLogSummary(logsTail: string): string {
  const lines = logsTail
    .split(/\r?\n/u)
    .map((line) => line.trim())
    .filter((line) => line.length > 0 && !line.startsWith("{"))
    .slice(-5)
    .map((line) => short(line));
  return lines.length === 0 ? "-" : lines.join(" | ");
}

export function sentinelRemoteJobTimeoutWarnings(job: unknown, subject: string): string[] {
  const remote = record(job);
  if (remote.phase !== "job-timeout" && remote.phase !== "pipelinerun-timeout") return [];
  const diagnostics = record(remote.diagnostics);
  const commands = record(diagnostics.commands);
  return [`${subject} reached wait budget at phase=${text(diagnostics.currentPhase)} completed=${text(Array.isArray(diagnostics.completedStages) ? diagnostics.completedStages.join(",") : "")}; inspect logs with ${text(commands.logs)} and continue via ${text(commands.cliStatus)}.`];
}

export function publishSatisfiedByObservedWarnings(publish: unknown, flush: unknown, observedReady: boolean): string[] {
  if (!observedReady) return [];
  const warnings: string[] = [];
  const publishRecord = record(publish);
  if (Object.keys(publishRecord).length > 0 && publishRecord.ok !== true) {
    warnings.push(`sentinel publish did not finish cleanly in the foreground (phase=${text(publishRecord.phase)}), but follow-up control-plane observation proves source, registry, GitOps, Argo and runtime are aligned; treating the publish wait result as visibility warning.`);
  }
  const flushRecord = record(flush);
  if (Object.keys(flushRecord).length > 0 && flushRecord.ok !== true) {
    warnings.push("sentinel git-mirror flush did not finish cleanly in the foreground, but runtime alignment is already proven; use git-mirror status/flush drill-down for GitHub mirror closeout.");
  }
  return warnings;
}

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

export 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.`];
}

export 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.`];
}

export 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.mirrorCommit ?? state.sourceHead.commit,
      stageRef: state.sourceHead.stageRef,
      sourceAuthority: state.sourceHead.sourceAuthority,
      valuesRedacted: true,
    },
    polls: 0,
    elapsedMs: 0,
    valuesRedacted: true,
  };
}
