#!/usr/bin/env node
// SPEC: PJ2026-01060505 Workbench Performance; PJ2026-0106 平台运维
import assert from "node:assert/strict";
import { execFile } from "node:child_process";
import { createHash } from "node:crypto";
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { promisify } from "node:util";
import { fileURLToPath } from "node:url";

import {
  applyRuntimeLaneDeployConfig,
  defaultEndpointForRuntimeLane,
  defaultPortForRuntimeLane,
  isRuntimeLane,
  runtimeLaneMirrorSpecs,
  runtimeLaneConfig,
  versionNameForRuntimeLane
} from "./src/runtime-lane.ts";
import { readStructuredFile } from "./src/structured-config.mjs";

const execFileAsync = promisify(execFile);
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const defaultOutDir = "deploy/gitops/node";
const defaultRegistryPrefix = process.env.HWLAB_NODE_REGISTRY_PREFIX || "127.0.0.1:5000/hwlab";
const defaultSourceRepo = process.env.HWLAB_NODE_GIT_URL || "git@github.com:pikasTech/HWLAB.git";
const defaultGitReadUrl = process.env.HWLAB_NODE_GIT_READ_URL || null;
const defaultV02GitReadUrl = process.env.HWLAB_V02_GIT_READ_URL || "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
const defaultV02GitWriteUrl = process.env.HWLAB_V02_GIT_WRITE_URL || "http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
const defaultRuntimeLaneGitReadUrl = process.env.HWLAB_RUNTIME_LANE_GIT_READ_URL || defaultV02GitReadUrl;
const defaultRuntimeLaneGitWriteUrl = process.env.HWLAB_RUNTIME_LANE_GIT_WRITE_URL || defaultV02GitWriteUrl;
const defaultBranch = process.env.HWLAB_NODE_BRANCH || "node";
const defaultGitopsBranch = process.env.HWLAB_NODE_GITOPS_BRANCH || "node-gitops";
const defaultCatalogPath = process.env.HWLAB_ARTIFACT_CATALOG_PATH || "deploy/artifact-catalog.dev.json";
const defaultRuntimeEndpoint = process.env.HWLAB_NODE_RUNTIME_ENDPOINT || "http://74.48.78.17:17667";
const defaultWebEndpoint = process.env.HWLAB_NODE_WEB_ENDPOINT || "http://74.48.78.17:17666";
const defaultProdRuntimeEndpoint = process.env.HWLAB_NODE_PROD_RUNTIME_ENDPOINT || "http://74.48.78.17:18667";
const defaultProdWebEndpoint = process.env.HWLAB_NODE_PROD_WEB_ENDPOINT || "http://74.48.78.17:18666";
const defaultV02RuntimeEndpoint = process.env.HWLAB_V02_RUNTIME_ENDPOINT || "https://hwlab.74-48-78-17.nip.io";
const defaultV02WebEndpoint = process.env.HWLAB_V02_WEB_ENDPOINT || "https://hwlab.74-48-78-17.nip.io";
const defaultProxyUrl = process.env.HWLAB_NODE_PROXY_URL || "http://127.0.0.1:10808";
const defaultAllProxyUrl = process.env.HWLAB_NODE_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
const defaultNoProxy = process.env.HWLAB_NODE_NO_PROXY || "hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc,git-mirror-http,git-mirror-http.devops-infra,git-mirror-http.devops-infra.svc,git-mirror-http.devops-infra.svc.cluster.local,git-mirror-write,git-mirror-write.devops-infra,git-mirror-write.devops-infra.svc,git-mirror-write.devops-infra.svc.cluster.local";
const ciToolsRunnerImage = process.env.HWLAB_NODE_CI_TOOLS_IMAGE || "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1";
const buildkitRunnerImage = process.env.HWLAB_NODE_BUILDKIT_IMAGE || "moby/buildkit:rootless";
const defaultDevBaseImage = process.env.HWLAB_NODE_DEV_BASE_IMAGE || "127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim";
const defaultServiceIds = Object.freeze([
  "hwlab-cloud-api",
  "hwlab-cloud-web",
  "hwlab-gateway",
  "hwlab-edge-proxy",
  "hwlab-agent-skills"
]);
const v02ExtraObservableServices = Object.freeze([
  { serviceId: "hwlab-deepseek-proxy", port: 4000, healthPath: "/health/live" }
]);
const v02RemovedServiceIds = new Set([
  "hwlab-agent-mgr",
  "hwlab-agent-worker",
  "hwlab-agent-worker-template",
  "hwlab-code-agent-workspace",
  "hwlab-router",
  "hwlab-tunnel-client",
  "hwlab-gateway-simu",
  "hwlab-box-simu",
  "hwlab-patch-panel"
]);
const v02RemovedServiceEnvNames = new Set([
  "CODEX_HOME",
  "OPENAI_API_KEY",
  "HWLAB_CODE_AGENT_PROVIDER",
  "HWLAB_CODE_AGENT_MODEL",
  "HWLAB_CODE_AGENT_OPENAI_BASE_URL",
  "HWLAB_CODE_AGENT_WORKSPACE",
  "HWLAB_CODE_AGENT_CODEX_HOME",
  "HWLAB_CODE_AGENT_CODEX_WORKSPACE",
  "HWLAB_CODE_AGENT_CODEX_SANDBOX",
  "HWLAB_CODE_AGENT_CODEX_COMMAND",
  "HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED",
  "HWLAB_CODE_AGENT_CODEX_STDIO_SUPERVISOR",
  "HWLAB_M3_GATEWAY_SIMU_1_URL",
  "HWLAB_M3_GATEWAY_SIMU_2_URL",
  "HWLAB_M3_PATCH_PANEL_URL",
  "HWLAB_GATEWAY_SIMU_URL",
  "HWLAB_BOX_SIMU_URL",
  "HWLAB_PATCH_PANEL_URL",
  "HWLAB_ROUTER_URL",
  "HWLAB_TUNNEL_CLIENT_URL"
]);
const moonBridgeSourceRef = process.env.HWLAB_NODE_MOONBRIDGE_REF || "1b99888d3dae889b79ee602cb875c7907f7e76f2";
const moonBridgeImage = process.env.HWLAB_NODE_MOONBRIDGE_IMAGE || `${defaultRegistryPrefix}/moonbridge:${moonBridgeSourceRef.slice(0, 12)}`;
const deepSeekProfileModel = process.env.HWLAB_NODE_DEEPSEEK_PROFILE_MODEL || "deepseek-chat";
const codexApiProfileModel = process.env.HWLAB_NODE_CODEX_API_PROFILE_MODEL || "gpt-5.5";
const codexApiProfileBaseUrl = process.env.HWLAB_NODE_CODEX_API_PROFILE_BASE_URL || "http://127.0.0.1:49280/responses";
const codexApiForwarderPort = process.env.HWLAB_NODE_CODEX_API_FORWARDER_PORT || "49280";
const codexApiForwarderUpstreamBaseUrl = process.env.HWLAB_NODE_CODEX_API_UPSTREAM_BASE_URL || "https://hyueapi.com";
const sourceCommitPattern = /^[a-f0-9]{7,40}$/u;
const v02EnvReuseRuntimeMode = "env-reuse-git-mirror-checkout";

function k8sLabelHash(value) {
  return String(value || "").slice(0, 16);
}

const primitiveValidationTasks = Object.freeze([
  {
    name: "repo-reports-guard",
    commands: ["node scripts/repo-reports-guard.mjs"]
  },
  {
    name: "node-contract-check",
    commands: [
      "npm run gitops:ts:check",
      "node scripts/run-bun.mjs scripts/gitops-render.mjs --help >/dev/null",
      "render_check_revision=$(git rev-parse HEAD)",
      "render_check_dir=$(mktemp -d)",
      "node scripts/run-bun.mjs scripts/gitops-render.mjs --lane \"$(params.lane)\" --catalog-path \"$(params.catalog-path)\" --image-tag-mode \"$(params.image-tag-mode)\" --source-branch \"$(params.source-branch)\" --gitops-branch \"$(params.gitops-branch)\" --out \"$render_check_dir\" --source-revision \"$render_check_revision\"",
      "node scripts/run-bun.mjs scripts/gitops-render.mjs --lane \"$(params.lane)\" --catalog-path \"$(params.catalog-path)\" --image-tag-mode \"$(params.image-tag-mode)\" --source-branch \"$(params.source-branch)\" --gitops-branch \"$(params.gitops-branch)\" --out \"$render_check_dir\" --check --source-revision \"$render_check_revision\"",
      `node --input-type=module <<'NODE'
import { readdirSync, readFileSync, statSync } from "node:fs";
import path from "node:path";

const root = process.cwd();
const ciFileName = "CI" + ".json";
const forbiddenCiFragments = [
  "ci" + "-json",
  "HWLAB_NODE_TEKTON" + "_SINGLE_IMAGE_PUBLISH",
  "single" + "-dind",
  "docker" + ":29",
  "DOCKER" + "_HOST",
  "Docker" + "-in-Docker",
  "D" + "IND",
  "docker" + " push",
  "--build" + "-backend",
  "HWLAB_ARTIFACT" + "_BUILD_BACKEND",
  "--legacy" + "-source-images",
  "HWLAB_NODE_USE_DEPLOY_IMAGES" + "=0"
];
const scanTargets = [
  "scripts/gitops-render.mjs",
  "scripts/src/runtime-lane.ts",
  "scripts/artifact-publish.mjs",
  "scripts/src/ci-plan-lib.mjs",
  "deploy/gitops/node/tekton"
];
const skipDirs = new Set([".git", "node_modules", ".worktree"]);

function walkFiles(relativePath) {
  const absolutePath = path.join(root, relativePath);
  let stat;
  try {
    stat = statSync(absolutePath);
  } catch {
    return [];
  }
  if (stat.isFile()) return [relativePath];
  if (!stat.isDirectory()) return [];
  const files = [];
  for (const entry of readdirSync(absolutePath, { withFileTypes: true })) {
    if (entry.isDirectory() && skipDirs.has(entry.name)) continue;
    files.push(...walkFiles(path.join(relativePath, entry.name)));
  }
  return files;
}

const ciFiles = walkFiles(".").filter((filePath) => path.basename(filePath) === ciFileName);
const violations = [];
for (const filePath of scanTargets.flatMap(walkFiles)) {
  const text = readFileSync(path.join(root, filePath), "utf8");
  for (const fragment of forbiddenCiFragments) {
    if (text.includes(fragment)) violations.push({ filePath, fragment });
  }
}
if (ciFiles.length || violations.length) {
  console.error(JSON.stringify({ status: "failed", ciFiles, violations }, null, 2));
  process.exit(1);
}
NODE`,
      "node --check scripts/artifact-publish.mjs"
    ]
  },
  {
    name: "codex-api-forwarder-check",
    commands: [
      "node scripts/run-bun.mjs test cmd/hwlab-codex-api-responses-forwarder/main.test.ts"
    ]
  }
]);

function proxyEnv() {
  return [
    { name: "HTTP_PROXY", value: defaultProxyUrl },
    { name: "HTTPS_PROXY", value: defaultProxyUrl },
    { name: "ALL_PROXY", value: defaultAllProxyUrl },
    { name: "NO_PROXY", value: defaultNoProxy },
    { name: "http_proxy", value: defaultProxyUrl },
    { name: "https_proxy", value: defaultProxyUrl },
    { name: "all_proxy", value: defaultAllProxyUrl },
    { name: "no_proxy", value: defaultNoProxy }
  ];
}

function parseArgs(argv) {
  const args = {
    lane: process.env.HWLAB_GITOPS_LANE || "node",
    nodeId: process.env.HWLAB_NODE_ID || "node",
    outDir: defaultOutDir,
    gitopsRoot: defaultOutDir,
    catalogPath: defaultCatalogPath,
    imageTagMode: process.env.HWLAB_ARTIFACT_IMAGE_TAG_MODE || "short",
    registryPrefix: defaultRegistryPrefix,
    sourceRevision: null,
    sourceBranch: defaultBranch,
    gitopsBranch: defaultGitopsBranch,
    sourceRepo: defaultSourceRepo,
    gitReadUrl: defaultGitReadUrl,
    gitWriteUrl: null,
    runtimeEndpoint: defaultRuntimeEndpoint,
    webEndpoint: defaultWebEndpoint,
    prodRuntimeEndpoint: defaultProdRuntimeEndpoint,
    prodWebEndpoint: defaultProdWebEndpoint,
    useDeployImages: true,
    check: false,
    write: true,
    help: false
  };
  for (let index = 0; index < argv.length; index += 1) {
    const arg = argv[index];
    if (arg === "--lane") args.lane = readOption(argv, ++index, arg);
    else if (arg === "--node") args.nodeId = readOption(argv, ++index, arg);
    else if (arg === "--out") args.outDir = readOption(argv, ++index, arg);
    else if (arg === "--gitops-root") args.gitopsRoot = readOption(argv, ++index, arg);
    else if (arg === "--catalog-path") args.catalogPath = readOption(argv, ++index, arg);
    else if (arg === "--image-tag-mode") args.imageTagMode = readOption(argv, ++index, arg);
    else if (arg === "--registry-prefix") args.registryPrefix = readOption(argv, ++index, arg).replace(/\/+$/u, "");
    else if (arg === "--source-revision") args.sourceRevision = readOption(argv, ++index, arg);
    else if (arg === "--source-branch") args.sourceBranch = readOption(argv, ++index, arg);
    else if (arg === "--gitops-branch") args.gitopsBranch = readOption(argv, ++index, arg);
    else if (arg === "--source-repo") args.sourceRepo = readOption(argv, ++index, arg);
    else if (arg === "--git-read-url") args.gitReadUrl = readOption(argv, ++index, arg);
    else if (arg === "--git-write-url") args.gitWriteUrl = readOption(argv, ++index, arg);
    else if (arg === "--runtime-endpoint") args.runtimeEndpoint = readOption(argv, ++index, arg);
    else if (arg === "--web-endpoint") args.webEndpoint = readOption(argv, ++index, arg);
    else if (arg === "--prod-runtime-endpoint") args.prodRuntimeEndpoint = readOption(argv, ++index, arg);
    else if (arg === "--prod-web-endpoint") args.prodWebEndpoint = readOption(argv, ++index, arg);
    else if (arg === "--use-deploy-images") args.useDeployImages = true;
    else if (arg === "--check") {
      args.check = true;
      args.write = false;
    } else if (arg === "--no-write") args.write = false;
    else if (arg === "--help" || arg === "-h") args.help = true;
    else throw new Error(`unknown argument ${arg}`);
  }
  if (isRuntimeLane(args.lane)) {
    const versionName = versionNameForRuntimeLane(args.lane);
    const defaultLaneEndpoint = defaultEndpointForRuntimeLane(args.lane);
    if (args.sourceBranch === defaultBranch) args.sourceBranch = versionName;
    if (args.gitopsBranch === defaultGitopsBranch) args.gitopsBranch = `${versionName}-gitops`;
    if (args.catalogPath === defaultCatalogPath) args.catalogPath = `deploy/artifact-catalog.${args.lane}.json`;
    if (args.runtimeEndpoint === defaultRuntimeEndpoint) args.runtimeEndpoint = defaultLaneEndpoint;
    if (args.webEndpoint === defaultWebEndpoint) args.webEndpoint = defaultLaneEndpoint;
    if (args.imageTagMode === "short") args.imageTagMode = "full";
    if (!args.gitReadUrl) args.gitReadUrl = defaultRuntimeLaneGitReadUrl;
    if (!args.gitWriteUrl) args.gitWriteUrl = defaultRuntimeLaneGitWriteUrl;
  }
  if (!args.gitReadUrl) args.gitReadUrl = args.sourceRepo;
  if (!args.gitWriteUrl) args.gitWriteUrl = args.sourceRepo;
  assert.ok(args.lane === "node" || isRuntimeLane(args.lane), `unknown lane ${args.lane}`);
  assert.ok(["short", "full"].includes(args.imageTagMode), `unknown image tag mode ${args.imageTagMode}`);
  if (isRuntimeLane(args.lane)) {
    const versionName = versionNameForRuntimeLane(args.lane);
    assert.equal(args.sourceBranch, versionName, `${args.lane} source branch must be ${versionName}`);
    assert.equal(args.gitopsBranch, `${versionName}-gitops`, `${args.lane} GitOps branch must be ${versionName}-gitops`);
  }
  return args;
}

function readOption(argv, index, name) {
  const value = argv[index];
  if (!value || value.startsWith("--")) throw new Error(`${name} requires a value`);
  return value;
}

function usage() {
  return [
    "usage: node scripts/run-bun.mjs scripts/gitops-render.mjs [options]",
    "",
    "Render node-scoped Kubernetes-native CI/CD manifests from built-in Tekton CI primitives, deploy/deploy.yaml, and deploy/k8s/*.",
    "",
    "options:",
    "  --lane LANE              node or runtime lane such as v02/v03/v04; default: node",
    `  --node NODE              deployment node id from deploy.nodes; runtime lanes default from deploy.lanes.<lane>.node`,
    `  --out DIR                 default: ${defaultOutDir}`,
    `  --gitops-root DIR         path inside GitOps repo; default comes from deploy.nodes.<node>.gitopsRoot`,
    `  --catalog-path PATH       default: ${defaultCatalogPath}`,
    "  --image-tag-mode MODE    short or full; v02 uses full source commit IDs",
    `  --source-repo URL         default: ${defaultSourceRepo}`,
    "  --git-read-url URL       read-only source URL; runtime lanes default to devops-infra git mirror",
    "  --git-write-url URL      GitOps write URL; runtime lanes default to devops-infra git mirror write relay",
    `  --source-branch BRANCH    default: ${defaultBranch}`,
    `  --gitops-branch BRANCH    default: ${defaultGitopsBranch}`,
    "  --source-revision SHA    source commit used for image tags and runtime annotations; default: git rev-parse HEAD",
    `  --registry-prefix PREFIX  default: ${defaultRegistryPrefix}`,
    `  --runtime-endpoint URL    default: ${defaultRuntimeEndpoint}; runtime lane default is derived from deploy.yaml/public URL`,
    `  --web-endpoint URL        default: ${defaultWebEndpoint}; runtime lane default is derived from deploy.yaml/public URL`,
    `  --prod-runtime-endpoint URL default: ${defaultProdRuntimeEndpoint}`,
    `  --prod-web-endpoint URL   default: ${defaultProdWebEndpoint}`,
    "  --use-deploy-images      default and only supported mode: render workload images from deploy/artifact-catalog.dev.json per service",
    "  --check                  verify generated files are current without writing",
    "  --no-write               plan and print generated file list without writing"
  ].join("\n");
}

function generatedPath(filePath) {
  return path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath);
}

async function readJson(relativePath) {
  return readStructuredFile(repoRoot, relativePath);
}

async function readJsonIfPresent(relativePath, fallback = null) {
  try {
    return await readJson(relativePath);
  } catch (error) {
    if (error && error.code === "ENOENT") return fallback;
    throw error;
  }
}

async function gitValue(args) {
  const result = await execFileAsync("git", args, { cwd: repoRoot, timeout: 10000, maxBuffer: 1024 * 1024 });
  return result.stdout.trim();
}

async function resolveSourceRevision(value) {
  const revision = value || await gitValue(["rev-parse", "HEAD"]);
  const full = sourceCommitPattern.test(revision) && revision.length === 40
    ? revision
    : await gitValue(["rev-parse", revision]);
  assert.match(full, /^[a-f0-9]{40}$/u, "source revision must resolve to a 40-char git commit");
  return { full, short: full.slice(0, 7) };
}

function jsonManifest(value) {
  return `${JSON.stringify(value, null, 2)}\n`;
}

function textFile(value) {
  return value.endsWith("\n") ? value : `${value}\n`;
}

function cloneJson(value) {
  return JSON.parse(JSON.stringify(value));
}

function ensureObject(value, name) {
  assert.ok(value && typeof value === "object" && !Array.isArray(value), `${name} must be an object`);
  return value;
}

function asItems(list, name) {
  assert.equal(list?.kind, "List", `${name} must be a Kubernetes List`);
  assert.ok(Array.isArray(list.items), `${name}.items must be an array`);
  return list.items;
}

function serviceIdForWorkload(item, container) {
  return (
    item?.metadata?.labels?.["hwlab.pikastech.local/service-id"] ||
    item?.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/service-id"] ||
    container?.name
  );
}

function upsertEnv(envList, name, value) {
  if (!Array.isArray(envList)) return;
  const existing = envList.find((entry) => entry?.name === name);
  if (existing) {
    delete existing.valueFrom;
    existing.value = value;
  } else {
    envList.push({ name, value });
  }
}

function upsertEnvEntry(envList, entry) {
  if (!Array.isArray(envList) || !entry?.name) return;
  const existing = envList.find((item) => item?.name === entry.name);
  if (existing) {
    delete existing.value;
    delete existing.valueFrom;
    Object.assign(existing, cloneJson(entry));
  } else {
    envList.push(cloneJson(entry));
  }
}

function syncCodeAgentWorkspaceInitContainer(initContainers, { image, runtimeCommit, runtimeImageTag }) {
  const initContainer = Array.isArray(initContainers)
    ? initContainers.find((entry) => entry?.name === "hwlab-code-agent-workspace-init")
    : null;
  if (!initContainer) return;
  initContainer.image = image;
  initContainer.imagePullPolicy = "IfNotPresent";
  initContainer.env ??= [];
  upsertEnv(initContainer.env, "HWLAB_WORKSPACE_SOURCE_COMMIT", runtimeCommit);
  upsertEnv(initContainer.env, "HWLAB_IMAGE", image);
  upsertEnv(initContainer.env, "HWLAB_IMAGE_TAG", runtimeImageTag);
}

function annotate(metadata, annotations) {
  metadata.annotations = { ...(metadata.annotations ?? {}), ...annotations };
}

function label(metadata, labels) {
  metadata.labels = { ...(metadata.labels ?? {}), ...labels };
}

function imageFor(registryPrefix, serviceId, imageTag) {
  return `${registryPrefix}/${serviceId}:${imageTag}`;
}

function imageTagFromReference(image) {
  const value = String(image ?? "");
  const slashIndex = value.lastIndexOf("/");
  const colonIndex = value.lastIndexOf(":");
  if (colonIndex <= slashIndex) return null;
  return value.slice(colonIndex + 1).split("@", 1)[0] || null;
}

function repositoryFromImage(image) {
  const value = String(image ?? "").split("@", 1)[0];
  const slashIndex = value.lastIndexOf("/");
  const colonIndex = value.lastIndexOf(":");
  return colonIndex > slashIndex ? value.slice(0, colonIndex) : value;
}

function digestPinnedImage(image, digest) {
  if (!/^sha256:[a-f0-9]{64}$/u.test(String(digest ?? ""))) return image;
  const repository = repositoryFromImage(image);
  return repository ? `${repository}@${digest}` : image;
}

function catalogServiceById(catalog, serviceId) {
  return (catalog?.services ?? []).find((service) => service?.serviceId === serviceId) ?? null;
}

function v02EnvReuseEnabled(catalog, serviceId, envReuseServiceIds = null) {
  if (envReuseServiceIds?.has(serviceId)) return true;
  const service = catalogServiceById(catalog, serviceId);
  return service?.runtimeMode === v02EnvReuseRuntimeMode || service?.envReuse === true;
}

function bootShForService(deployService, serviceId) {
  assert.ok(deployService?.bootSh, `deploy lane bootScripts.${serviceId} is required`);
  const value = deployService.bootSh;
  const text = String(value).replaceAll("\\", "/").replace(/^\.\//u, "");
  assert.ok(text && !text.startsWith("/") && !text.split("/").includes(".."), `${serviceId} boot script must be repo-relative`);
  return text;
}

function envReuseServiceIdsForLane(deploy, lane) {
  if (!isRuntimeLane(lane)) return new Set();
  const configured = deploy?.lanes?.[lane]?.envReuseServices;
  const allowed = new Set(serviceIdsForLane(lane, deploy));
  return new Set((Array.isArray(configured) ? configured : []).filter((serviceId) => allowed.has(serviceId)));
}

function deployServiceForBoot(deploy, serviceId, lane = "v02") {
  return {
    serviceId,
    bootSh: deploy?.lanes?.[lane]?.bootScripts?.[serviceId]
  };
}

function bootMetadataForService({ args, catalog, deployService, serviceId, source }) {
  const catalogService = catalogServiceById(catalog, serviceId);
  const environmentImage = catalogService?.environmentImage ?? imageFor(args.registryPrefix, `${serviceId}-env`, `env-${String(catalogService?.environmentInputHash ?? source.full).slice(0, 12)}`);
  const environmentDigest = catalogService?.environmentDigest ?? catalogService?.digest ?? null;
  return {
    runtimeMode: v02EnvReuseRuntimeMode,
    environmentImage,
    environmentDigest,
    environmentInputHash: catalogService?.environmentInputHash ?? null,
    codeInputHash: catalogService?.codeInputHash ?? null,
    bootRepo: catalogService?.bootRepo ?? args.sourceRepo,
    bootCommit: catalogService?.bootCommit ?? source.full,
    bootSh: catalogService?.bootSh ?? bootShForService(deployService, serviceId)
  };
}

function envReuseBootShForContainer({ serviceId, container, defaultBootSh }) {
  if (serviceId === "hwlab-cloud-api" && container?.name === "hwlab-codex-api-forwarder") {
    return "deploy/runtime/boot/hwlab-codex-api-responses-forwarder.sh";
  }
  return defaultBootSh;
}

function applyEnvReuseBootEnv(container, bootMetadata, { sourceBranch, gitReadUrl, bootSh = bootMetadata?.bootSh } = {}) {
  if (!container || !bootMetadata) return;
  delete container.command;
  delete container.args;
  container.env ??= [];
  upsertEnv(container.env, "HWLAB_RUNTIME_MODE", bootMetadata.runtimeMode);
  upsertEnv(container.env, "HWLAB_BOOT_REPO", bootMetadata.bootRepo);
  upsertEnv(container.env, "HWLAB_BOOT_COMMIT", bootMetadata.bootCommit);
  upsertEnv(container.env, "HWLAB_BOOT_REF", sourceBranch);
  upsertEnv(container.env, "HWLAB_BOOT_SH", bootSh);
  upsertEnv(container.env, "HWLAB_BOOT_READ_URL", gitReadUrl ?? defaultV02GitReadUrl);
  upsertEnv(container.env, "HWLAB_ENVIRONMENT_IMAGE", bootMetadata.environmentImage ?? "");
  upsertEnv(container.env, "HWLAB_ENVIRONMENT_DIGEST", bootMetadata.environmentDigest ?? "");
  upsertEnv(container.env, "HWLAB_ENVIRONMENT_INPUT_HASH", bootMetadata.environmentInputHash ?? "");
  upsertEnv(container.env, "HWLAB_CODE_INPUT_HASH", bootMetadata.codeInputHash ?? "");
  upsertEnv(container.env, "HWLAB_IMAGE_DIGEST", bootMetadata.environmentDigest ?? "unknown");
  applyEnvReuseStartupProbe(container);
}

function applyEnvReuseStartupProbe(container) {
  const probe = container.readinessProbe ?? container.livenessProbe;
  if (!probe?.httpGet && !probe?.tcpSocket && !probe?.exec) return;
  container.startupProbe ??= {
    ...cloneJson(probe),
    periodSeconds: 10,
    timeoutSeconds: Math.max(Number(probe.timeoutSeconds ?? 1), 2),
    failureThreshold: 30,
    successThreshold: 1
  };
}

function applyServiceHealthProbe(container, healthProbe) {
  if (!healthProbe || typeof healthProbe !== "object" || Array.isArray(healthProbe)) return;
  for (const [probeName, key] of [["readinessProbe", "readiness"], ["livenessProbe", "liveness"], ["startupProbe", "startup"]]) {
    const probe = container?.[probeName];
    const timing = normalizeProbeTiming(healthProbe[key]);
    if (!probe || Object.keys(timing).length === 0) continue;
    Object.assign(probe, timing);
  }
}

function normalizeProbeTiming(value) {
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
  const result = {};
  for (const field of ["initialDelaySeconds", "periodSeconds", "timeoutSeconds", "failureThreshold", "successThreshold"]) {
    const raw = value[field];
    const minimum = field === "initialDelaySeconds" ? 0 : 1;
    if (Number.isInteger(raw) && raw >= minimum) result[field] = raw;
  }
  return result;
}

function useLocalHealthProbe(container, pathValue = "/health") {
  if (!container) return;
  for (const probeName of ["readinessProbe", "livenessProbe"]) {
    const probe = container[probeName];
    if (!probe?.httpGet) continue;
    probe.httpGet.path = pathValue;
  }
}

function annotateEnvReusePodTemplate(podMetadata, bootMetadata) {
  if (!podMetadata || !bootMetadata) return;
  annotate(podMetadata, {
    "hwlab.pikastech.local/runtime-mode": bootMetadata.runtimeMode,
    "hwlab.pikastech.local/boot-repo": bootMetadata.bootRepo,
    "hwlab.pikastech.local/boot-commit": bootMetadata.bootCommit,
    "hwlab.pikastech.local/boot-sh": bootMetadata.bootSh,
    "hwlab.pikastech.local/environment-digest": bootMetadata.environmentDigest ?? "not_published",
    "hwlab.pikastech.local/environment-input-hash": bootMetadata.environmentInputHash ?? "unknown",
    "hwlab.pikastech.local/code-input-hash": bootMetadata.codeInputHash ?? "unknown"
  });
  label(podMetadata, {
    "hwlab.pikastech.local/runtime-mode": bootMetadata.runtimeMode,
    "hwlab.pikastech.local/boot-commit": bootMetadata.bootCommit
  });
}

function runtimeArtifactForService({ catalog, deploy, serviceId, source, registryPrefix, useDeployImages = false, digestPin = false, envReuseServiceIds = null }) {
  const catalogService = catalogServiceById(catalog, serviceId);
  if (v02EnvReuseEnabled(catalog, serviceId, envReuseServiceIds)) {
    const environmentImage = catalogService?.environmentImage ?? imageFor(registryPrefix, `${serviceId}-env`, `env-${String(catalogService?.environmentInputHash ?? source.full).slice(0, 12)}`);
    const runtimeImage = digestPin && useDeployImages ? digestPinnedImage(environmentImage, catalogService?.environmentDigest ?? catalogService?.digest) : environmentImage;
    return {
      image: runtimeImage,
      imageTag: imageTagFromReference(environmentImage) ?? source.imageTag ?? source.short,
      commit: catalogService?.bootCommit ?? source.full,
      runtimeMode: v02EnvReuseRuntimeMode,
      environmentDigest: catalogService?.environmentDigest ?? catalogService?.digest ?? null
    };
  }
  const fallbackImageTag = source.imageTag ?? source.short;
  const image = useDeployImages && catalogService?.image
    ? catalogService.image
    : imageFor(registryPrefix, serviceId, fallbackImageTag);
  const runtimeImage = digestPin && useDeployImages ? digestPinnedImage(image, catalogService?.digest) : image;
  const imageTag = useDeployImages && catalogService?.imageTag
    ? catalogService.imageTag
    : imageTagFromReference(image) ?? fallbackImageTag;
  const commit = useDeployImages
    ? catalogService?.sourceCommitId ?? catalogService?.commitId ?? imageTag ?? source.full
    : source.full;
  return { image: runtimeImage, imageTag, commit };
}

function runtimeImageForService(options) {
  return runtimeArtifactForService(options).image;
}

function runtimeCommitForService(options) {
  return runtimeArtifactForService(options).commit;
}

function runtimeImageTagForService(options) {
  return runtimeArtifactForService(options).imageTag;
}

function artifactEnvironment(args) {
  return isRuntimeLane(args.lane) ? args.lane : "dev";
}

function artifactEndpoint(args) {
  return isRuntimeLane(args.lane) ? args.runtimeEndpoint : defaultRuntimeEndpoint;
}

function serviceIdsForLane(lane, deploy = null) {
  return isRuntimeLane(lane) ? runtimeLaneServiceIdsFromDeploy(deploy, lane) : defaultServiceIds;
}

function serviceIdsForProfile(profile, deploy = null) {
  return isRuntimeLane(profile) ? runtimeLaneServiceIdsFromDeploy(deploy, profile) : defaultServiceIds;
}

function runtimeLaneServiceIdsFromDeploy(deploy, lane) {
  const laneConfig = runtimeLaneConfig(deploy, lane);
  const serviceIds = uniquePreserveOrder((Array.isArray(laneConfig.envReuseServices) ? laneConfig.envReuseServices : [])
    .map((item) => String(item ?? "").trim())
    .filter(Boolean));
  assert.ok(serviceIds.length > 0, `deploy.lanes.${lane}.envReuseServices must not be empty`);
  return serviceIds;
}

function v02ServiceIdsFromDeploy(deploy) {
  return runtimeLaneServiceIdsFromDeploy(deploy, "v02");
}

function runtimeLaneObservableServicesForDeploy(deploy, lane) {
  const laneConfig = runtimeLaneConfig(deploy, lane);
  const declarations = laneConfig.serviceDeclarations ?? {};
  const serviceIds = new Set(runtimeLaneServiceIdsFromDeploy(deploy, lane));
  const declared = Object.entries(declarations)
    .filter(([serviceId, declaration]) => serviceIds.has(serviceId) && declaration?.observable !== false && Number.isInteger(declaration?.healthPort))
    .map(([serviceId, declaration]) => ({
      serviceId,
      port: declaration.healthPort,
      healthPath: declaration.healthPath || "/health/live"
    }));
  return [...declared, ...v02ExtraObservableServices];
}

function v02ObservableServicesForDeploy(deploy) {
  return runtimeLaneObservableServicesForDeploy(deploy, "v02");
}

function v02ObservableService(deploy, serviceId) {
  return v02ObservableServicesForDeploy(deploy).find((item) => item.serviceId === serviceId) ?? null;
}

function runtimeLaneObservableService(deploy, lane, serviceId) {
  return runtimeLaneObservableServicesForDeploy(deploy, lane).find((item) => item.serviceId === serviceId) ?? null;
}

function runtimeLaneObservableServiceIdsForDeploy(deploy, lane) {
  return new Set(runtimeLaneObservableServicesForDeploy(deploy, lane).map((item) => item.serviceId));
}

function v02ObservableServiceIdsForDeploy(deploy) {
  return runtimeLaneObservableServiceIdsForDeploy(deploy, "v02");
}

function servicesParamForLane(lane, deploy = null) {
  return serviceIdsForLane(lane, deploy).join(",");
}

function uniquePreserveOrder(values) {
  const seen = new Set();
  const result = [];
  for (const value of values) {
    if (seen.has(value)) continue;
    seen.add(value);
    result.push(value);
  }
  return result;
}

function isV02RemovedServiceId(serviceId) {
  return v02RemovedServiceIds.has(serviceId);
}

function artifactCatalogSkeleton({ args, deploy, source }) {
  const environment = artifactEnvironment(args);
  const namespace = isRuntimeLane(args.lane) ? namespaceNameForProfile(args.lane) : "hwlab-dev";
  const tag = imageTagForSource(args, source);
  return {
    catalogVersion: "v1",
    kind: "hwlab-artifact-catalog",
    environment,
    profile: environment,
    namespace,
    endpoint: artifactEndpoint(args),
    commitId: tag,
    artifactState: "contract-skeleton",
    publish: {
      registryPrefix: args.registryPrefix,
      sourceCommitId: source.full,
      imageTag: tag,
      publishedAt: null
    },
    allowedProfiles: [environment],
    forbiddenProfiles: isRuntimeLane(args.lane) ? ["dev", "prod"] : ["prod"],
    services: serviceIdsForLane(args.lane, deploy).map((serviceId) => artifactCatalogSkeletonService({ args, deploy, source, serviceId, environment, namespace, tag }))
  };
}

function artifactCatalogSkeletonService({ args, deploy, source, serviceId, environment, namespace, tag }) {
  const base = {
    serviceId,
    profile: environment,
    namespace,
    commitId: tag,
    sourceCommitId: source.full,
    image: imageFor(args.registryPrefix, serviceId, tag),
    imageTag: tag,
    digest: null,
    buildBackend: "contract-skeleton"
  };
  const envReuseServiceIds = envReuseServiceIdsForLane(deploy, args.lane);
  if (!envReuseServiceIds.has(serviceId)) return base;
  const bootSh = bootShForService(deployServiceForBoot(deploy, serviceId, args.lane), serviceId);
  const environmentImage = imageFor(args.registryPrefix, `${serviceId}-env`, `env-${String(source.full).slice(0, 12)}`);
  return {
    ...base,
    image: environmentImage,
    imageTag: imageTagFromReference(environmentImage),
    runtimeMode: v02EnvReuseRuntimeMode,
    envReuse: true,
    environmentImage,
    environmentDigest: null,
    environmentInputHash: null,
    bootRepo: args.sourceRepo,
    bootCommit: source.full,
    bootSh,
    codeInputHash: null,
    bootEnvEvidence: {
      env: {
        HWLAB_BOOT_REPO: args.sourceRepo,
        HWLAB_BOOT_COMMIT: source.full,
        HWLAB_BOOT_SH: bootSh
      }
    }
  };
}

function namespaceNameForProfile(profile) {
  if (isRuntimeLane(profile)) return `hwlab-${profile}`;
  return profile === "prod" ? "hwlab-prod" : "hwlab-dev";
}

function runtimePathForProfile(profile) {
  if (isRuntimeLane(profile)) return `runtime-${profile}`;
  return profile === "prod" ? "runtime-prod" : "runtime-dev";
}

function runtimeLabelForProfile(profile) {
  if (isRuntimeLane(profile)) return profile;
  return profile === "prod" ? "prod" : "dev";
}

function gitopsTargetForProfile(profile) {
  return isRuntimeLane(profile) ? profile : "node";
}

function gitopsRootForArgs(args) {
  return String(args.gitopsRoot || defaultOutDir).replace(/\/+$/u, "");
}

function gitopsPathForProfile(args, profile) {
  return `${gitopsRootForArgs(args)}/${runtimePathForProfile(profile)}`;
}

function gitopsPathFor(args, relativePath) {
  return `${gitopsRootForArgs(args)}/${String(relativePath).replace(/^\/+/, "")}`;
}

function profileEndpoint(args, profile) {
  if (isRuntimeLane(profile)) return { runtimeEndpoint: args.runtimeEndpoint, webEndpoint: args.webEndpoint };
  return profile === "prod"
    ? { runtimeEndpoint: args.prodRuntimeEndpoint, webEndpoint: args.prodWebEndpoint }
    : { runtimeEndpoint: args.runtimeEndpoint, webEndpoint: args.webEndpoint };
}

function laneRuntimeProfiles(args) {
  return isRuntimeLane(args.lane) ? [args.lane] : ["dev", "prod"];
}

function laneNames(args) {
  if (isRuntimeLane(args.lane)) {
    const namespace = namespaceNameForProfile(args.lane);
    return {
      gitopsTarget: args.lane,
      pipeline: `${namespace}-ci-image-publish`,
      poller: `${namespace}-branch-poller`,
      reconciler: `${namespace}-control-plane-reconciler`,
      serviceAccount: `${namespace}-tekton-runner`,
      pipelineRunPrefix: `${namespace}-ci-poll-`,
      runtimeNamespace: namespace,
      runtimePath: gitopsPathForProfile(args, args.lane),
      argoApplications: [`argocd/hwlab-node-${args.lane}`]
    };
  }
  return {
    gitopsTarget: "node",
    pipeline: "hwlab-node-ci-image-publish",
    poller: "hwlab-node-branch-poller",
    reconciler: "hwlab-node-control-plane-reconciler",
    serviceAccount: "hwlab-tekton-runner",
    pipelineRunPrefix: "hwlab-node-ci-poll-",
    runtimeNamespace: "hwlab-dev",
    runtimePath: gitopsPathForProfile(args, "dev"),
    argoApplications: ["argocd/hwlab-node-dev", "argocd/hwlab-node-prod"]
  };
}

function argoApplicationName(profile) {
  return `hwlab-node-${profile}`;
}

function imageTagForSource(args, source) {
  return args.imageTagMode === "full" ? source.full : source.short;
}

function deepSeekBaseUrl(namespace) {
  return `http://hwlab-deepseek-proxy.${namespace}.svc.cluster.local:4000/v1/responses`;
}

function codeAgentNoProxy(namespace) {
  return [
    `${namespace}.svc.cluster.local`,
    ".svc",
    ".cluster.local",
    "hyueapi.com",
    ".hyueapi.com",
    "hyui.com",
    ".hyui.com",
    "127.0.0.1",
    "localhost",
    "::1",
    "10.0.0.0/8",
    "10.42.0.0/16",
    "10.43.0.0/16",
    "api.minimaxi.com",
    ".minimaxi.com"
  ].join(",");
}

function namespaceScopedHost(value, namespace) {
  if (typeof value !== "string") return value;
  return value.replace(/\.hwlab-dev\.svc\.cluster\.local/gu, `.${namespace}.svc.cluster.local`);
}

function secretNameForProfile(secretName, profile) {
  if (!isRuntimeLane(profile)) return secretName;
  if (secretName === "hwlab-cloud-api-dev-db") return `hwlab-cloud-api-${profile}-db`;
  if (secretName === "hwlab-code-agent-provider") return `hwlab-${profile}-code-agent-provider`;
  if (secretName === "hwlab-code-agent-codex-auth") return `hwlab-${profile}-code-agent-codex-auth`;
  if (secretName === "hwlab-bootstrap-admin") return `hwlab-${profile}-bootstrap-admin`;
  return secretName;
}

function rewritePodSecretRefs(podSpec, profile) {
  if (!podSpec || !isRuntimeLane(profile)) return;
  for (const volume of podSpec.volumes ?? []) {
    if (volume?.secret?.secretName) volume.secret.secretName = secretNameForProfile(volume.secret.secretName, profile);
  }
}

function deployEnvEntry(name, value, namespace, profile = "dev") {
  if (typeof value === "string" && value.startsWith("secretRef:")) {
    const ref = value.slice("secretRef:".length);
    const slashIndex = ref.indexOf("/");
    if (slashIndex > 0 && slashIndex < ref.length - 1) {
      return {
        name,
        valueFrom: {
          secretKeyRef: {
            name: secretNameForProfile(ref.slice(0, slashIndex), profile),
            key: ref.slice(slashIndex + 1),
            optional: true
          }
        }
      };
    }
  }
  return { name, value: namespaceScopedHost(value, namespace) };
}

function applyDeployEnv(envList, deployService, namespace, profile = "dev") {
  if (!deployService?.env || typeof deployService.env !== "object" || Array.isArray(deployService.env)) return;
  for (const [name, value] of Object.entries(deployService.env)) {
    upsertEnvEntry(envList, deployEnvEntry(name, value, namespace, profile));
  }
}

function removeV02LegacySimulatorEnv(envList) {
  if (!Array.isArray(envList)) return envList;
  return envList.filter((entry) => !v02RemovedServiceEnvNames.has(entry?.name));
}

function removeV02RepoOwnedCodeAgentPodConfig(podSpec) {
  if (!podSpec) return;
  podSpec.initContainers = (podSpec.initContainers ?? []).filter((entry) => entry?.name !== "hwlab-code-agent-workspace-init");
  const removedVolumeNames = new Set([
    "hwlab-code-agent-workspace",
    "hwlab-code-agent-codex-home",
    "hwlab-code-agent-codex-config",
    "hwlab-code-agent-codex-auth"
  ]);
  podSpec.volumes = (podSpec.volumes ?? []).filter((volume) => !removedVolumeNames.has(volume?.name));
  for (const container of podSpec.containers ?? []) {
    container.volumeMounts = (container.volumeMounts ?? []).filter((mount) => !removedVolumeNames.has(mount?.name));
  }
}

function deployServicesForProfile(deploy, profile) {
  const allowed = new Set(serviceIdsForProfile(profile, deploy));
  const services = new Map((deploy.services ?? [])
    .filter((service) => allowed.has(service.serviceId))
    .map((service) => {
      const copy = cloneJson(service);
      copy.env = mergeEnvMaps(
        copy.env,
        serviceDeclarationEnvForProfile(deploy, profile, service.serviceId),
        runtimeStoreEnvForProfile(deploy, profile, service.serviceId),
        workbenchRuntimeClientEnvForProfile(deploy, profile, service.serviceId),
        workbenchRuntimeFactsQueryEnvForProfile(deploy, profile, service.serviceId),
        workbenchRuntimeSessionsSummaryEnvForProfile(deploy, profile, service.serviceId),
        workbenchRuntimePostgresEnvForProfile(deploy, profile, service.serviceId),
        workbenchRuntimeRedisEnvForProfile(deploy, profile, service.serviceId)
      );
      return [service.serviceId, copy];
    }));
  const laneServices = isRuntimeLane(profile) && Array.isArray(deploy.lanes?.[profile]?.services)
    ? deploy.lanes[profile].services
    : [];
  for (const override of laneServices) {
    const existing = services.get(override.serviceId) ?? {
      serviceId: override.serviceId,
      env: mergeEnvMaps(
        serviceDeclarationEnvForProfile(deploy, profile, override.serviceId),
        runtimeStoreEnvForProfile(deploy, profile, override.serviceId),
        workbenchRuntimeClientEnvForProfile(deploy, profile, override.serviceId),
        workbenchRuntimeFactsQueryEnvForProfile(deploy, profile, override.serviceId),
        workbenchRuntimeSessionsSummaryEnvForProfile(deploy, profile, override.serviceId),
        workbenchRuntimePostgresEnvForProfile(deploy, profile, override.serviceId),
        workbenchRuntimeRedisEnvForProfile(deploy, profile, override.serviceId)
      )
    };
    services.set(override.serviceId, {
      ...existing,
      ...cloneJson(override),
      env: mergeEnvMaps(existing.env, override.env)
    });
  }
  return services;
}

function serviceDeclarationEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile)) return {};
  const env = deploy?.lanes?.[profile]?.serviceDeclarations?.[serviceId]?.env;
  if (!env || typeof env !== "object" || Array.isArray(env)) return {};
  return cloneJson(env);
}

function runtimeWorkbenchTraceTimelinePolicy(deploy, profile) {
  if (!isRuntimeLane(profile)) return null;
  const traceTimeline = runtimeLaneConfig(deploy, profile)?.workbench?.traceTimeline;
  if (!traceTimeline || typeof traceTimeline !== "object" || Array.isArray(traceTimeline)) return null;
  const result = {};
  if (typeof traceTimeline.autoExpandRunning === "boolean") result.autoExpandRunning = traceTimeline.autoExpandRunning;
  if (typeof traceTimeline.autoCollapseTerminal === "boolean") result.autoCollapseTerminal = traceTimeline.autoCollapseTerminal;
  return Object.keys(result).length > 0 ? result : null;
}

function runtimeTraceExplorerUrlTemplate(deploy, profile) {
  if (!isRuntimeLane(profile)) return null;
  const template = runtimeLaneConfig(deploy, profile)?.observability?.traceExplorerUrlTemplate;
  return typeof template === "string" && template.trim().length > 0 ? template.trim() : null;
}

function runtimeStoreEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-cloud-api") return {};
  const postgres = runtimeLaneConfig(deploy, profile)?.runtimeStore?.postgres;
  if (!postgres || typeof postgres !== "object" || Array.isArray(postgres)) return {};
  const env = {};
  if (Number.isInteger(postgres.poolMax)) env.HWLAB_CLOUD_DB_POOL_MAX = String(postgres.poolMax);
  if (Number.isInteger(postgres.connectionTimeoutMs)) {
    env.HWLAB_CLOUD_DB_PROBE_TIMEOUT_MS = String(postgres.connectionTimeoutMs);
  }
  if (Number.isInteger(postgres.queryTimeoutMs)) {
    env.HWLAB_CLOUD_DB_QUERY_TIMEOUT_MS = String(postgres.queryTimeoutMs);
  }
  if (Number.isInteger(postgres.queryRetryMaxAttempts)) {
    env.HWLAB_CLOUD_DB_QUERY_RETRY_MAX_ATTEMPTS = String(postgres.queryRetryMaxAttempts);
  }
  if (Number.isInteger(postgres.queryRetryInitialDelayMs)) {
    env.HWLAB_CLOUD_DB_QUERY_RETRY_INITIAL_DELAY_MS = String(postgres.queryRetryInitialDelayMs);
  }
  if (Number.isInteger(postgres.queryRetryMaxDelayMs)) {
    env.HWLAB_CLOUD_DB_QUERY_RETRY_MAX_DELAY_MS = String(postgres.queryRetryMaxDelayMs);
  }
  return env;
}

function workbenchRuntimeRedisEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-workbench-runtime") return {};
  const redis = workbenchRuntimeRedisConfigForProfile(deploy, profile);
  if (!redis || typeof redis !== "object" || Array.isArray(redis)) return {};
  const env = {
    HWLAB_WORKBENCH_CACHE_REDIS_ENABLED: booleanEnv(Boolean(redis.enabled))
  };
  const namespace = typeof redis.namespace === "string" ? redis.namespace.trim() : "";
  const serviceName = typeof redis.serviceName === "string" ? redis.serviceName.trim() : "";
  const port = Number.isInteger(redis.port) ? redis.port : null;
  if (namespace) env.HWLAB_WORKBENCH_CACHE_REDIS_NAMESPACE = namespace;
  if (serviceName) env.HWLAB_WORKBENCH_CACHE_REDIS_SERVICE_NAME = serviceName;
  if (port !== null) env.HWLAB_WORKBENCH_CACHE_REDIS_PORT = String(port);
  if (namespace && serviceName && port !== null) {
    env.HWLAB_WORKBENCH_CACHE_REDIS_URL = `redis://${serviceName}.${namespace}.svc.cluster.local:${port}/0`;
  }
  const ttl = redis.ttl ?? {};
  if (Number.isInteger(ttl.sessionsSummaryMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_TTL_SESSIONS_SUMMARY_MS = String(ttl.sessionsSummaryMs);
  if (Number.isInteger(ttl.terminalTurnMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_TTL_TERMINAL_TURN_MS = String(ttl.terminalTurnMs);
  if (Number.isInteger(ttl.terminalTracePageMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_TTL_TERMINAL_TRACE_PAGE_MS = String(ttl.terminalTracePageMs);
  if (Number.isInteger(ttl.runningPageMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_TTL_RUNNING_PAGE_MS = String(ttl.runningPageMs);
  const limits = redis.limits ?? {};
  if (Number.isInteger(limits.maxKeyBytes)) env.HWLAB_WORKBENCH_CACHE_REDIS_MAX_KEY_BYTES = String(limits.maxKeyBytes);
  if (Number.isInteger(limits.maxPayloadBytes)) env.HWLAB_WORKBENCH_CACHE_REDIS_MAX_PAYLOAD_BYTES = String(limits.maxPayloadBytes);
  const timeouts = redis.timeouts ?? {};
  if (Number.isInteger(timeouts.connectMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_CONNECT_TIMEOUT_MS = String(timeouts.connectMs);
  if (Number.isInteger(timeouts.operationMs)) env.HWLAB_WORKBENCH_CACHE_REDIS_OPERATION_TIMEOUT_MS = String(timeouts.operationMs);
  const labels = redis.metrics?.labels;
  if (labels && typeof labels === "object" && !Array.isArray(labels)) {
    env.HWLAB_WORKBENCH_CACHE_REDIS_METRICS_LABELS = JSON.stringify(labels);
  }
  const behavior = redis.unavailableBehavior ?? {};
  if (typeof behavior.livenessFailure === "boolean") env.HWLAB_WORKBENCH_CACHE_REDIS_UNAVAILABLE_LIVENESS_FAILURE = booleanEnv(behavior.livenessFailure);
  if (typeof behavior.readMode === "string") env.HWLAB_WORKBENCH_CACHE_REDIS_UNAVAILABLE_READ_MODE = behavior.readMode;
  if (typeof behavior.fallbackStateSource === "boolean") env.HWLAB_WORKBENCH_CACHE_REDIS_UNAVAILABLE_FALLBACK_STATE_SOURCE = booleanEnv(behavior.fallbackStateSource);
  if (typeof redis.disableSwitchEnv === "string" && redis.disableSwitchEnv.trim()) {
    env[redis.disableSwitchEnv.trim()] = booleanEnv(Boolean(redis.enabled));
  }
  return env;
}

function workbenchRuntimeClientEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-cloud-api") return {};
  const client = runtimeLaneConfig(deploy, profile)?.workbenchRuntime?.client;
  if (!client || typeof client !== "object" || Array.isArray(client)) return {};
  const env = {};
  if (Number.isInteger(client.timeoutMs)) env.HWLAB_WORKBENCH_RUNTIME_TIMEOUT_MS = String(client.timeoutMs);
  return env;
}

function workbenchRuntimeFactsQueryEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-cloud-api") return {};
  const factsQuery = runtimeLaneConfig(deploy, profile)?.workbenchRuntime?.factsQuery;
  if (!factsQuery || typeof factsQuery !== "object" || Array.isArray(factsQuery)) return {};
  const env = {};
  if (Number.isInteger(factsQuery.maxAttempts)) env.HWLAB_WORKBENCH_FACTS_QUERY_MAX_ATTEMPTS = String(factsQuery.maxAttempts);
  if (Number.isInteger(factsQuery.backoffBaseMs)) env.HWLAB_WORKBENCH_FACTS_QUERY_BACKOFF_BASE_MS = String(factsQuery.backoffBaseMs);
  if (Number.isInteger(factsQuery.backoffMaxMs)) env.HWLAB_WORKBENCH_FACTS_QUERY_BACKOFF_MAX_MS = String(factsQuery.backoffMaxMs);
  return env;
}

function workbenchRuntimeSessionsSummaryEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-workbench-runtime") return {};
  const sessionsSummary = runtimeLaneConfig(deploy, profile)?.workbenchRuntime?.sessionsSummary;
  if (!sessionsSummary || typeof sessionsSummary !== "object" || Array.isArray(sessionsSummary)) return {};
  const env = {};
  if (Number.isInteger(sessionsSummary.maxAttempts)) env.HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_MAX_ATTEMPTS = String(sessionsSummary.maxAttempts);
  if (Number.isInteger(sessionsSummary.attemptTimeoutMs)) env.HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_ATTEMPT_TIMEOUT_MS = String(sessionsSummary.attemptTimeoutMs);
  if (Number.isInteger(sessionsSummary.backoffMs)) env.HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_BACKOFF_MS = String(sessionsSummary.backoffMs);
  return env;
}

function workbenchRuntimePostgresEnvForProfile(deploy, profile, serviceId) {
  if (!isRuntimeLane(profile) || serviceId !== "hwlab-workbench-runtime") return {};
  const postgres = runtimeLaneConfig(deploy, profile)?.workbenchRuntime?.postgres;
  if (!postgres || typeof postgres !== "object" || Array.isArray(postgres)) return {};
  const env = {};
  if (Number.isInteger(postgres.poolMax)) env.HWLAB_WORKBENCH_RUNTIME_DB_POOL_MAX = String(postgres.poolMax);
  if (Number.isInteger(postgres.queryTimeoutMs)) env.HWLAB_WORKBENCH_RUNTIME_QUERY_TIMEOUT_MS = String(postgres.queryTimeoutMs);
  if (Number.isInteger(postgres.readyTimeoutMs)) env.HWLAB_WORKBENCH_RUNTIME_READY_TIMEOUT_MS = String(postgres.readyTimeoutMs);
  return env;
}

function workbenchRuntimeRedisConfigForProfile(deploy, profile) {
  if (!isRuntimeLane(profile)) return null;
  const label = `deploy.lanes.${profile}.workbenchRuntime.cache.redis`;
  const redis = runtimeLaneConfig(deploy, profile)?.workbenchRuntime?.cache?.redis;
  if (!redis || redis.enabled !== true) return null;
  configObject(redis, label);
  const namespace = requiredConfigString(redis, "namespace", label);
  assert.equal(namespace, namespaceNameForProfile(profile), `${label}.namespace must match ${namespaceNameForProfile(profile)}`);
  const serviceName = requiredConfigString(redis, "serviceName", label);
  const image = requiredConfigString(redis, "image", label);
  const port = requiredConfigPositiveInteger(redis, "port", label);
  assert.ok(port <= 65535, `${label}.port must be a valid TCP port`);
  const resources = configObject(redis.resources, `${label}.resources`);
  configObject(resources.requests, `${label}.resources.requests`);
  configObject(resources.limits, `${label}.resources.limits`);
  const memoryPolicy = configObject(redis.memoryPolicy, `${label}.memoryPolicy`);
  assert.equal(memoryPolicy.persistence, "disabled", `${label}.memoryPolicy.persistence must be disabled`);
  requiredConfigString(memoryPolicy, "maxMemory", `${label}.memoryPolicy`);
  requiredConfigString(memoryPolicy, "eviction", `${label}.memoryPolicy`);
  return redis;
}

function booleanEnv(value) {
  return value ? "1" : "0";
}

function mergeEnvMaps(...values) {
  const result = {};
  for (const value of values) {
    if (!value || typeof value !== "object" || Array.isArray(value)) continue;
    Object.assign(result, value);
  }
  return result;
}

function runtimeNodeIdForProfile(deploy, profile, fallback = "node") {
  if (!isRuntimeLane(profile)) return fallback;
  const nodeId = deploy?.lanes?.[profile]?.node;
  return typeof nodeId === "string" && nodeId.length > 0 ? nodeId : fallback;
}

function v02MetricsLabels(serviceId) {
  return {
    "hwlab.pikastech.local/monitoring": "enabled",
    "hwlab.pikastech.local/service-id": serviceId
  };
}

function v02MetricsSidecarVolume(profile = "v02") {
  return { name: "hwlab-metrics-sidecar", configMap: { name: `hwlab-${profile}-metrics-sidecar` } };
}

function v02MetricsSidecarAnnotations(metricsSidecarSha256) {
  return metricsSidecarSha256 ? { "hwlab.pikastech.local/metrics-sidecar-sha256": metricsSidecarSha256 } : {};
}

function v02MetricsSidecarContainer({ deploy, serviceId, namespace, gitopsTarget, profile = "v02" }) {
  const service = runtimeLaneObservableService(deploy, profile, serviceId);
  assert.ok(service, `unknown ${profile} observable service ${serviceId}`);
  const extraMetricsEnv = serviceId === "hwlab-cloud-api"
    ? [
        { name: "HWLAB_METRICS_EXTRA_URL", value: `http://127.0.0.1:${service.port}/v1/web-performance/metrics` },
        { name: "HWLAB_METRICS_EXTRA_TIMEOUT_MS", value: "2000" }
      ]
    : [];
  return {
    name: "hwlab-metrics",
    image: ciToolsRunnerImage,
    imagePullPolicy: "IfNotPresent",
    command: ["node", "/metrics/metrics-sidecar.mjs"],
    env: [
      { name: "HWLAB_METRICS_SERVICE_ID", value: serviceId },
      { name: "HWLAB_METRICS_NAMESPACE", value: namespace },
      { name: "HWLAB_METRICS_GITOPS_TARGET", value: gitopsTarget },
      { name: "HWLAB_METRICS_PORT", value: "9100" },
      { name: "HWLAB_METRICS_TARGET_URL", value: `http://127.0.0.1:${service.port}${service.healthPath}` },
      { name: "HWLAB_METRICS_TARGET_TIMEOUT_MS", value: "2000" },
      ...extraMetricsEnv
    ],
    ports: [{ name: "metrics", containerPort: 9100 }],
    readinessProbe: { httpGet: { path: "/health/live", port: "metrics" }, initialDelaySeconds: 3, periodSeconds: 10 },
    livenessProbe: { httpGet: { path: "/health/live", port: "metrics" }, initialDelaySeconds: 10, periodSeconds: 20 },
    volumeMounts: [{ name: "hwlab-metrics-sidecar", mountPath: "/metrics", readOnly: true }]
  };
}

function upsertV02MetricsSidecar(podSpec, options) {
  if (!podSpec || !Array.isArray(podSpec.containers)) return;
  podSpec.containers = podSpec.containers.filter((container) => container?.name !== "hwlab-metrics");
  podSpec.containers.push(v02MetricsSidecarContainer(options));
  podSpec.volumes ??= [];
  podSpec.volumes = podSpec.volumes.filter((volume) => volume?.name !== "hwlab-metrics-sidecar");
  podSpec.volumes.push(v02MetricsSidecarVolume(options.profile));
}

function upsertV02MetricsPort(service) {
  service.spec ??= {};
  service.spec.ports ??= [];
  service.spec.ports = service.spec.ports.filter((port) => port?.name !== "metrics");
  service.spec.ports.push({ name: "metrics", port: 9100, targetPort: "metrics" });
}

function transformWorkloads({ workloads, deploy, catalog, source, sourceBranch = defaultBranch, gitReadUrl, registryPrefix, runtimeEndpoint, webEndpoint, profile = "dev", useDeployImages = false, metricsSidecarSha256 = null }) {
  const result = cloneJson(workloads);
  const deployServices = deployServicesForProfile(deploy, profile);
  const namespace = namespaceNameForProfile(profile);
  const profileLabel = runtimeLabelForProfile(profile);
  const gitopsTarget = gitopsTargetForProfile(profile);
  const runtimeLane = isRuntimeLane(profile);
  const digestPin = runtimeLane;
  const envReuseServiceIds = envReuseServiceIdsForLane(deploy, profile);
  const runtimeObservableServiceIds = runtimeLane ? runtimeLaneObservableServiceIdsForDeploy(deploy, profile) : new Set();
  const stableRuntimeLabels = {
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/environment": profileLabel,
    "hwlab.pikastech.local/profile": profileLabel
  };
  result.items = asItems(result, "workloads").filter((item) => !(runtimeLane && isV02RemovedServiceId(serviceIdForWorkload(item, null))));
  for (const item of asItems(result, "workloads")) {
    item.metadata.namespace = namespace;
    label(item.metadata, {
      ...stableRuntimeLabels,
      "hwlab.pikastech.local/gitops-target": gitopsTarget,
      "hwlab.pikastech.local/gitops-render-source-commit": source.full,
      "hwlab.pikastech.local/source-commit": source.full,
      "unidesk.ai/node-staging": profile === "dev" ? "true" : "false"
    });
    annotate(item.metadata, {
      "hwlab.pikastech.local/gitops-note": profile === "v02" ? "HWLAB v0.2 GitOps target." : profile === "prod" ? "node PROD GitOps target." : "node DEV GitOps target.",
      "hwlab.pikastech.local/gitops-render-source-commit": source.full,
      "hwlab.pikastech.local/source-commit": source.full
    });
    if (item.kind === "Job") {
      annotate(item.metadata, {
        "argocd.argoproj.io/sync-options": "Force=true,Replace=true"
      });
      if (item.spec?.suspend === true) {
        annotate(item.metadata, {
          "argocd.argoproj.io/ignore-healthcheck": "true"
        });
      }
    }
    const podTemplate = item?.spec?.template;
    if (!podTemplate?.spec?.containers) continue;
    const templateServiceId = serviceIdForWorkload(item, podTemplate.spec.containers[0]);
    const templateArtifact = runtimeArtifactForService({ catalog, deploy, serviceId: templateServiceId, source, registryPrefix, useDeployImages, digestPin, envReuseServiceIds });
    const templateSourceCommit = runtimeLane ? (templateArtifact.commit ?? source.full) : source.full;
    const templateArtifactCommit = templateArtifact.commit;
    label(podTemplate.metadata ??= {}, {
      ...stableRuntimeLabels,
      "hwlab.pikastech.local/gitops-target": gitopsTarget,
      "hwlab.pikastech.local/gitops-render-source-commit": source.full,
      "hwlab.pikastech.local/source-commit": templateSourceCommit,
      "hwlab.pikastech.local/artifact-source-commit": templateArtifactCommit
    });
    if (runtimeLane && runtimeObservableServiceIds.has(templateServiceId)) {
      label(item.metadata, v02MetricsLabels(templateServiceId));
      label(podTemplate.metadata, v02MetricsLabels(templateServiceId));
      annotate(podTemplate.metadata, v02MetricsSidecarAnnotations(metricsSidecarSha256));
      upsertV02MetricsSidecar(podTemplate.spec, { deploy, serviceId: templateServiceId, namespace, gitopsTarget, profile });
    }
    if ((item.kind === "Deployment" || item.kind === "StatefulSet") && item.spec?.selector?.matchLabels) {
      item.spec.selector.matchLabels = {
        ...item.spec.selector.matchLabels,
        ...stableRuntimeLabels
      };
    }
    annotate(podTemplate.metadata, {
      "hwlab.pikastech.local/gitops-render-source-commit": source.full,
      "hwlab.pikastech.local/source-commit": templateSourceCommit,
      "hwlab.pikastech.local/artifact-source-commit": templateArtifactCommit,
      "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs"
    });
    for (const container of podTemplate.spec.containers) {
      if (container.name === "hwlab-metrics") continue;
      const serviceId = serviceIdForWorkload(item, container);
      const deployService = deployServices.get(serviceId);
      if (!deployService) continue;
      const artifact = runtimeArtifactForService({ catalog, deploy, serviceId, source, registryPrefix, useDeployImages, digestPin, envReuseServiceIds });
      const envReuse = runtimeLane && v02EnvReuseEnabled(catalog, serviceId, envReuseServiceIds);
      const bootDeployService = envReuse ? deployServiceForBoot(deploy, serviceId, profile) : null;
      const bootMetadata = envReuse ? bootMetadataForService({ args: { sourceRepo: deploy?.lanes?.[profile]?.sourceRepo || defaultSourceRepo, registryPrefix }, catalog, deployService: bootDeployService, serviceId, source }) : null;
      const image = artifact.image;
      const runtimeCommit = artifact.commit;
      const runtimeImageTag = artifact.imageTag;
      container.image = image;
      container.imagePullPolicy = "IfNotPresent";
      container.env ??= [];
      for (const entry of container.env) {
        if (Object.hasOwn(entry, "value")) entry.value = namespaceScopedHost(entry.value, namespace);
      }
      applyDeployEnv(container.env, deployService, namespace, profile);
      if (runtimeLane) container.env = removeV02LegacySimulatorEnv(container.env);
      upsertEnv(container.env, "HWLAB_ENVIRONMENT", profileLabel);
      upsertEnv(container.env, "HWLAB_COMMIT_ID", runtimeCommit);
      upsertEnv(container.env, "HWLAB_IMAGE", image);
      upsertEnv(container.env, "HWLAB_IMAGE_TAG", runtimeImageTag);
      if (serviceId === "hwlab-agent-skills") {
        upsertEnv(container.env, "HWLAB_SKILLS_COMMIT_ID", runtimeCommit);
      }
      upsertEnv(container.env, "HWLAB_GITOPS_TARGET", gitopsTarget);
      upsertEnv(container.env, "HWLAB_GITOPS_PROFILE", profileLabel);
      upsertEnv(container.env, "HWLAB_GITOPS_SOURCE_COMMIT", runtimeLane ? runtimeCommit : source.full);
      if (runtimeLane && serviceId === "hwlab-cloud-api") {
        upsertEnv(container.env, "HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT", runtimeCommit);
      }
      if (bootMetadata) {
        applyEnvReuseBootEnv(container, bootMetadata, {
          sourceBranch,
          gitReadUrl,
          bootSh: envReuseBootShForContainer({ serviceId, container, defaultBootSh: bootMetadata.bootSh })
        });
        if (container.name === serviceId) annotateEnvReusePodTemplate(podTemplate.metadata, bootMetadata);
      }
      if (runtimeLane && container.name === serviceId) {
        applyServiceHealthProbe(container, deploy?.lanes?.[profile]?.serviceDeclarations?.[serviceId]?.healthProbe);
      }
      if (serviceId === "hwlab-cloud-api" || serviceId === "hwlab-edge-proxy") {
        upsertEnv(container.env, "HWLAB_PUBLIC_ENDPOINT", runtimeEndpoint);
      }
      if (runtimeLane && serviceId === "hwlab-edge-proxy") {
        useLocalHealthProbe(container, "/health");
      }
      if (serviceId === "hwlab-cloud-api") {
        if (runtimeLane) {
          removeV02RepoOwnedCodeAgentPodConfig(podTemplate.spec);
          upsertEnv(container.env, "HWLAB_M3_IO_CONTROL_ENABLED", "false");
          upsertEnv(container.env, "HWLAB_CODE_AGENT_AGENTRUN_REPO_URL", gitReadUrl ?? defaultRuntimeLaneGitReadUrl);
          upsertEnv(container.env, "HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID", runtimeNodeIdForProfile(deploy, profile));
          upsertEnv(container.env, "HWLAB_OPENFGA_MODE", "enforce");
          upsertEnv(container.env, "HWLAB_OPENFGA_API_URL", `http://hwlab-openfga.${namespace}.svc.cluster.local:8080`);
          upsertEnvEntry(container.env, deployEnvEntry("HWLAB_OPENFGA_AUTHN_TOKEN", `secretRef:hwlab-${profile}-openfga/authn-preshared-key`, namespace, profile));
          upsertEnv(container.env, "UNIDESK_MAIN_SERVER_IP", "http://74.48.78.17:18081");
        } else {
          syncCodeAgentWorkspaceInitContainer(podTemplate.spec.initContainers, { image, runtimeCommit, runtimeImageTag });
        }
        upsertEnv(container.env, "HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE", "deepseek");
        upsertEnv(container.env, "HWLAB_CODE_AGENT_DEEPSEEK_MODEL", deepSeekProfileModel);
        upsertEnv(container.env, "HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL", deepSeekBaseUrl(namespace));
        upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_MODEL", codexApiProfileModel);
        upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_BASE_URL", codexApiProfileBaseUrl);
        upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_UPSTREAM_BASE_URL", codexApiForwarderUpstreamBaseUrl);
        upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_FORWARDER_PORT", codexApiForwarderPort);
        upsertEnv(container.env, "HWLAB_PREINSTALLED_SKILLS_DIR", "/app/skills");
        upsertEnv(container.env, "HWLAB_USER_SKILLS_DIR", "/data/user-skills");
        upsertEnv(container.env, "HWLAB_CODE_AGENT_SKILLS_DIRS", "/app/skills:/data/user-skills");
        upsertEnv(container.env, "NO_PROXY", codeAgentNoProxy(namespace));
        upsertEnv(container.env, "no_proxy", codeAgentNoProxy(namespace));
      }
      if (serviceId === "hwlab-cloud-web") {
        upsertEnv(container.env, "HWLAB_API_BASE_URL", `http://hwlab-cloud-api.${namespace}.svc.cluster.local:6667`);
        upsertEnv(container.env, "HWLAB_PUBLIC_ENDPOINT", webEndpoint);
        const traceTimelinePolicy = runtimeWorkbenchTraceTimelinePolicy(deploy, profile);
        if (typeof traceTimelinePolicy?.autoExpandRunning === "boolean") {
          upsertEnv(container.env, "HWLAB_WORKBENCH_TRACE_AUTO_EXPAND_RUNNING", booleanEnv(traceTimelinePolicy.autoExpandRunning));
        }
        if (typeof traceTimelinePolicy?.autoCollapseTerminal === "boolean") {
          upsertEnv(container.env, "HWLAB_WORKBENCH_TRACE_AUTO_COLLAPSE_TERMINAL", booleanEnv(traceTimelinePolicy.autoCollapseTerminal));
        }
        const traceExplorerUrlTemplate = runtimeTraceExplorerUrlTemplate(deploy, profile);
        if (traceExplorerUrlTemplate) {
          upsertEnv(container.env, "HWLAB_WORKBENCH_TRACE_EXPLORER_URL_TEMPLATE", traceExplorerUrlTemplate);
        }
      }
    }
    rewritePodSecretRefs(podTemplate.spec, profile);
  }
  return result;
}

function transformHealthContract(value, namespace, labels, annotations, runtimeEndpoint, webEndpoint, profile = "dev") {
  const result = transformListNamespace(value, namespace, labels, annotations);
  if (result.metadata?.name === "hwlab-dev-health-contract") {
    result.metadata.name = `hwlab-${profile}-health-contract`;
  }
  if (result.metadata?.labels && Object.hasOwn(result.metadata.labels, "app.kubernetes.io/name")) {
    result.metadata.labels["app.kubernetes.io/name"] = `hwlab-${profile}-health-contract`;
  }
  if (result.data && typeof result.data === "object") {
    if (Object.hasOwn(result.data, "endpoint")) result.data.endpoint = runtimeEndpoint;
    if (Object.hasOwn(result.data, "cloud-web")) {
      result.data["cloud-web"] = `GET /health/live on ${webEndpoint}; consumes cloud-api only`;
    }
    if (Object.hasOwn(result.data, "cloud-api")) {
      result.data["cloud-api"] = `GET /health/live through ${runtimeEndpoint}`;
    }
    if (Object.hasOwn(result.data, "tunnel-client")) {
      result.data["tunnel-client"] = "disabled for node GitOps; no FRP or production traffic tunnel is required";
    }
  }
  return result;
}

function transformListNamespace(value, namespace, labels, annotations) {
  const result = cloneJson(value);
  if (result.kind === "List") {
    for (const item of result.items ?? []) {
      item.metadata ??= {};
      item.metadata.namespace = namespace;
      label(item.metadata, labels);
      annotate(item.metadata, annotations);
    }
  } else {
    result.metadata ??= {};
    result.metadata.namespace = namespace;
    label(result.metadata, labels);
    annotate(result.metadata, annotations);
  }
  return result;
}

function transformServices({ services, namespace, labels, annotations, profile = "dev", deploy = null }) {
  const observableServiceIds = isRuntimeLane(profile) ? runtimeLaneObservableServiceIdsForDeploy(deploy, profile) : new Set();
  const result = transformListNamespace(services, namespace, labels, annotations);
  if (result.kind === "List") {
    result.items = (result.items ?? []).filter((item) => !(isRuntimeLane(profile) && isV02RemovedServiceId(serviceIdForWorkload(item, null))));
    for (const item of result.items) {
      const serviceId = serviceIdForWorkload(item, null);
      if (!isRuntimeLane(profile) || !observableServiceIds.has(serviceId)) continue;
      label(item.metadata ??= {}, v02MetricsLabels(serviceId));
      upsertV02MetricsPort(item);
    }
  }
  return result;
}

function observabilityManifest({ deploy, profile, namespace, labels, annotations, metricsSidecarScript }) {
  assert.ok(isRuntimeLane(profile), `observability profile must be a runtime lane, got ${profile}`);
  const baseLabels = {
    ...labels,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/monitoring": "enabled"
  };
  const serviceMonitors = runtimeLaneObservableServicesForDeploy(deploy, profile).map((service) => ({
    apiVersion: "monitoring.coreos.com/v1",
    kind: "ServiceMonitor",
    metadata: {
      name: `hwlab-${profile}-${service.serviceId}`,
      namespace,
      labels: { ...baseLabels, "hwlab.pikastech.local/service-id": service.serviceId },
      annotations
    },
    spec: {
      namespaceSelector: { matchNames: [namespace] },
      selector: {
        matchLabels: {
          "hwlab.pikastech.local/gitops-target": profile,
          "hwlab.pikastech.local/monitoring": "enabled",
          "hwlab.pikastech.local/service-id": service.serviceId
        }
      },
      targetLabels: [
        "hwlab.pikastech.local/gitops-target",
        "hwlab.pikastech.local/service-id"
      ],
      endpoints: [{ port: "metrics", path: "/metrics", interval: "30s", scrapeTimeout: "10s" }]
    }
  }));
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: `hwlab-${profile}-metrics-sidecar`, namespace, labels: baseLabels, annotations },
        data: { "metrics-sidecar.mjs": metricsSidecarScript }
      },
      ...serviceMonitors,
      {
        apiVersion: "monitoring.coreos.com/v1",
        kind: "PrometheusRule",
        metadata: { name: `hwlab-${profile}-observability`, namespace, labels: baseLabels, annotations },
        spec: {
          groups: [{
            name: `hwlab-${profile}-observability`,
            rules: [
              {
                alert: `HWLAB${profile.toUpperCase()}MetricsTargetDown`,
                expr: `up{namespace="${namespace}"} == 0`,
                for: "5m",
                labels: { severity: "warning", lane: profile },
                annotations: { summary: `HWLAB ${versionNameForRuntimeLane(profile)} metrics target is down`, description: `Prometheus cannot scrape a HWLAB ${versionNameForRuntimeLane(profile)} metrics target.` }
              },
              {
                alert: `HWLAB${profile.toUpperCase()}ServiceHealthProbeFailed`,
                expr: `hwlab_service_health_probe_success{namespace="${namespace}"} == 0`,
                for: "5m",
                labels: { severity: "warning", lane: profile },
                annotations: { summary: "HWLAB v0.2 service health probe failed", description: "The metrics sidecar cannot reach the service health endpoint inside the pod network." }
              }
            ]
          }]
        }
      }
    ]
  };
}

function shellSingleQuote(value) {
  return `'${String(value).replace(/'/g, `'"'"'`)}'`;
}

function ciTimingShellFunction() {
  return `ci_now_ms() {
  node -e 'console.log(Date.now())'
}

ci_timing_emit() {
  stage="$1"
  status="$2"
  started_ms="$3"
  finished_ms="$(ci_now_ms)"
  duration_ms="$((finished_ms - started_ms))"
  service_id="\${HWLAB_TIMING_SERVICE_ID:-}"
  node -e 'const [stage,status,durationMs,serviceId]=process.argv.slice(1); const payload={event:"node-cicd-timing",schemaVersion:"v1",stage,status,durationMs:Number(durationMs),pipelineRun:process.env.HWLAB_TEKTON_PIPELINERUN||null,taskRun:process.env.HWLAB_TEKTON_TASKRUN||null,task:process.env.HWLAB_TEKTON_TASK||null,revision:process.env.HWLAB_SOURCE_REVISION||null,serviceId:serviceId||null,source:"scripts/gitops-render.mjs",at:new Date().toISOString()}; console.log(JSON.stringify(payload));' "$stage" "$status" "$duration_ms" "$service_id"
}
`;
}

function dependencyProxyProbeScript(phase, targetUrl) {
  return `HWLAB_PROXY_PROBE_PHASE=${shellSingleQuote(phase)} HWLAB_PROXY_PROBE_URL=${shellSingleQuote(targetUrl)} node <<'NODE' || echo '{"event":"dependency-proxy-probe-nonblocking","phase":"${phase}","ok":false,"reason":"probe-failed-but-continuing"}'
const net = require("node:net");

const phase = process.env.HWLAB_PROXY_PROBE_PHASE || "unknown";
const target = new URL(process.env.HWLAB_PROXY_PROBE_URL || "http://deb.debian.org/debian/dists/bookworm/InRelease");
const proxyRaw = process.env.HTTP_PROXY || process.env.http_proxy || "";

function redactProxy(value) {
  if (!value) return "";
  try {
    const parsed = new URL(value);
    if (parsed.username || parsed.password) {
      parsed.username = "***";
      parsed.password = "";
    }
    return parsed.toString();
  } catch {
    return "<invalid-proxy-url>";
  }
}

function emit(payload, exitCode = 0) {
  console.log(JSON.stringify({
    event: "dependency-proxy-probe",
    phase,
    target: target.href,
    proxy: redactProxy(proxyRaw),
    ...payload
  }));
  if (exitCode) process.exit(exitCode);
}

if (!proxyRaw) emit({ ok: false, reason: "proxy-env-missing" }, 21);

let proxy;
try {
  proxy = new URL(proxyRaw);
} catch (error) {
  emit({ ok: false, reason: "proxy-url-invalid", error: error.message }, 22);
}

if (proxy.protocol !== "http:" && proxy.protocol !== "https:") {
  emit({ ok: false, reason: "http-proxy-required", protocol: proxy.protocol }, 23);
}

const startedAt = Date.now();
const socket = net.createConnection({ host: proxy.hostname, port: Number(proxy.port || (proxy.protocol === "https:" ? 443 : 80)) });
let bytes = 0;
let firstByteMs = null;
let responseHead = "";
let finished = false;

const timeout = setTimeout(() => {
  if (finished) return;
  finished = true;
  socket.destroy();
  emit({ ok: false, reason: "timeout", timeoutMs: 15000 }, 24);
}, 15000);

socket.on("connect", () => {
  socket.write("GET " + target.href + " HTTP/1.1\\r\\nHost: " + target.host + "\\r\\nUser-Agent: hwlab-node-proxy-probe\\r\\nConnection: close\\r\\n\\r\\n");
});

socket.on("data", (chunk) => {
  if (firstByteMs === null) firstByteMs = Date.now() - startedAt;
  bytes += chunk.length;
  if (responseHead.length < 240) responseHead += chunk.toString("utf8", 0, Math.min(chunk.length, 240 - responseHead.length));
});

socket.on("end", () => {
  if (finished) return;
  finished = true;
  clearTimeout(timeout);
  const totalMs = Date.now() - startedAt;
  const statusLine = responseHead.split("\\r\\n", 1)[0] || "";
  const statusCode = Number(statusLine.split(" ")[1] || 0);
  const ok = statusLine.startsWith("HTTP/") && statusCode >= 200 && statusCode < 400;
  emit({
    ok,
    reason: ok ? null : "bad-http-status",
    statusLine,
    statusCode,
    firstByteMs,
    totalMs,
    bytes,
    speedBytesPerSecond: totalMs > 0 ? Math.round(bytes * 1000 / totalMs) : 0
  }, ok ? 0 : 25);
});

socket.on("error", (error) => {
  if (finished) return;
  finished = true;
  clearTimeout(timeout);
  emit({ ok: false, reason: "proxy-connect-failed", error: error.message, totalMs: Date.now() - startedAt }, 26);
});
NODE`;
}

function curlDownloadProbeFunction() {
  return `redact_proxy_value() {
  printf '%s' "\${1:-}" | sed -E 's#(https?://)[^/@]+@#\\1***@#; s#(socks5h?://)[^/@]+@#\\1***@#'
}

curl_dependency_probe() {
  phase="$1"
  url="$2"
  proxy="\${HTTPS_PROXY:-\${https_proxy:-\${HTTP_PROXY:-\${http_proxy:-}}}}"
  if [ -z "$proxy" ]; then
    echo '{"event":"dependency-curl-probe","phase":"'"$phase"'","ok":false,"reason":"proxy-env-missing"}'
    return 21
  fi
  safe_proxy="$(redact_proxy_value "$proxy")"
  echo '{"event":"dependency-curl-probe-start","phase":"'"$phase"'","proxy":"'"$safe_proxy"'","target":"'"$url"'"}'
  curl -sS -L --range 0-1048575 -o /dev/null --connect-timeout 15 --max-time 60 --proxy "$proxy" \
    -w '{"event":"dependency-curl-probe","phase":"'"$phase"'","http_code":"%{http_code}","time_namelookup":%{time_namelookup},"time_connect":%{time_connect},"time_starttransfer":%{time_starttransfer},"time_total":%{time_total},"speed_download":%{speed_download},"size_download":%{size_download},"remote_ip":"%{remote_ip}"}\n' \
    "$url"
}`;
}

function gitSshShellFunction() {
  return `git_ssh_setup() {
  mkdir -p /root/.ssh
  cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa
  chmod 600 /root/.ssh/id_rsa
  timeout 10 ssh-keyscan github.com >> /root/.ssh/known_hosts 2>/dev/null || true
  timeout 10 ssh-keyscan -p 443 ssh.github.com >> /root/.ssh/known_hosts 2>/dev/null || true
  write_github_proxy_command
  export GIT_SSH_COMMAND="ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 -o ServerAliveInterval=10 -o ServerAliveCountMax=2 -o ProxyCommand='node /tmp/hwlab-github-proxy-connect.mjs 127.0.0.1 10808 %h %p'"
  git config --global url."ssh://git@ssh.github.com:443/".insteadOf "git@github.com:"
  git config --global url."ssh://git@ssh.github.com:443/".insteadOf "ssh://git@github.com/"
}

write_github_proxy_command() {
  cat > /tmp/hwlab-github-proxy-connect.mjs <<'NODE_PROXY'
#!/usr/bin/env node
import net from "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("usage: hwlab-github-proxy-connect <proxyHost> <proxyPort> <targetHost> <targetPort>");
  process.exit(64);
}

const socket = net.createConnection({ host: proxyHost, port: proxyPort });
let buffer = Buffer.alloc(0);

socket.setTimeout(10000, () => {
  console.error("proxy connect timeout " + proxyHost + ":" + proxyPort + " -> " + targetHost + ":" + targetPort);
  socket.destroy();
  process.exit(65);
});

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) => {
  console.error("proxy connect failed: " + error.message);
  process.exit(66);
});

function onData(chunk) {
  buffer = Buffer.concat([buffer, chunk]);
  const headerEnd = buffer.indexOf("\\r\\n\\r\\n");
  if (headerEnd === -1 && buffer.length < 8192) 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) {
    console.error("proxy CONNECT rejected: " + (statusLine || "missing-status"));
    socket.destroy();
    process.exit(67);
  }
  socket.off("data", onData);
  socket.setTimeout(0);
  const rest = buffer.slice(headerEnd + 4);
  if (rest.length) process.stdout.write(rest);
  process.stdin.pipe(socket);
  socket.pipe(process.stdout);
}

socket.on("data", onData);
socket.on("close", () => process.exit(0));
NODE_PROXY
  chmod 0700 /tmp/hwlab-github-proxy-connect.mjs
}

git_now_ms() {
  node -e 'console.log(Date.now())' 2>/dev/null || date +%s000
}

git_timed() {
  phase="$1"
  timeout_seconds="$2"
  shift 2
  started_ms="$(git_now_ms)"
  echo '{"event":"git-operation","phase":"'"$phase"'","status":"started","timeoutSeconds":'"$timeout_seconds"'}' >&2
  set +e
  timeout "$timeout_seconds" "$@"
  status="$?"
  set -e
  finished_ms="$(git_now_ms)"
  duration_ms="$((finished_ms - started_ms))"
  if [ "$status" -eq 0 ]; then
    echo '{"event":"git-operation","phase":"'"$phase"'","status":"succeeded","durationMs":'"$duration_ms"'}' >&2
    return 0
  fi
  if [ "$status" -eq 124 ] || [ "$status" -eq 137 ]; then
    echo '{"event":"git-operation","phase":"'"$phase"'","status":"failed","reason":"timeout","durationMs":'"$duration_ms"',"timeoutSeconds":'"$timeout_seconds"'}' >&2
  else
    echo '{"event":"git-operation","phase":"'"$phase"'","status":"failed","exitCode":'"$status"',"durationMs":'"$duration_ms"'}' >&2
  fi
  return "$status"
}
`;
}

function prepareSourceScript() {
  const lines = [
    "#!/bin/sh",
    "set -eu",
    ciTimingShellFunction(),
    "export HWLAB_TEKTON_PIPELINERUN=\"$(context.pipelineRun.name)\"",
    "export HWLAB_TEKTON_TASKRUN=\"$(context.taskRun.name)\"",
    "export HWLAB_TEKTON_TASK=\"prepare-source\"",
    "export HWLAB_SOURCE_REVISION=\"$(params.revision)\"",
    `echo '{"event":"ci-base-image","phase":"prepare-source","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'`,
    "for tool in node git timeout; do command -v \"$tool\" >/dev/null 2>&1 || { echo '{\"event\":\"ci-base-image\",\"ok\":false,\"reason\":\"missing-tool\",\"tool\":\"'\"$tool\"'\"}'; exit 31; }; done",
    "node -e 'console.log(JSON.stringify({event:\"ci-base-image\",phase:\"prepare-source\",ok:true,node:process.version}))'",
    gitSshShellFunction(),
    "git_url_requires_ssh() { case \"$1\" in git@*|ssh://*) return 0 ;; *) return 1 ;; esac; }",
    "git_read_url=\"$(params.git-read-url)\"",
    "if git_url_requires_ssh \"$git_read_url\"; then",
    "  for tool in ssh ssh-keyscan; do command -v \"$tool\" >/dev/null 2>&1 || { echo '{\"event\":\"ci-base-image\",\"ok\":false,\"reason\":\"missing-tool\",\"tool\":\"'\"$tool\"'\"}'; exit 31; }; done",
    "  git_ssh_setup",
    "else",
    "  echo '{\"event\":\"git-ssh-setup\",\"phase\":\"prepare-source\",\"status\":\"skipped\",\"reason\":\"non-ssh-git-read-url\"}'",
    "fi",
    "rm -rf /workspace/source/repo",
    "source_clone_started_ms=\"$(ci_now_ms)\"",
    "git_timed source-clone 180 git clone --branch \"$(params.source-branch)\" \"$git_read_url\" /workspace/source/repo",
    "cd /workspace/source/repo",
    "git config --global --add safe.directory /workspace/source/repo",
    "git remote set-url origin \"$git_read_url\"",
    "git checkout \"$(params.revision)\"",
    "test \"$(git rev-parse HEAD)\" = \"$(params.revision)\"",
    "git merge-base --is-ancestor \"$(params.revision)\" \"origin/$(params.source-branch)\" || { echo '{\"event\":\"source-ancestry\",\"status\":\"failed\",\"revision\":\"'\"$(params.revision)\"'\",\"sourceBranch\":\"'\"$(params.source-branch)\"'\"}'; exit 32; }",
    "ci_timing_emit source-clone succeeded \"$source_clone_started_ms\"",
    "prepare_source_dependencies_started_ms=\"$(ci_now_ms)\"",
    "if node -e 'require.resolve(\"yaml\")' >/dev/null 2>&1; then",
    "  echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"cached\",\"dependency\":\"yaml\"}'",
    "elif [ -f package-lock.json ]; then",
    "  command -v npm >/dev/null 2>&1 || { echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"failed\",\"reason\":\"missing-tool\",\"tool\":\"npm\"}'; exit 31; }",
    "  npm ci --ignore-scripts --no-audit --prefer-offline",
    "  echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"installed\",\"manager\":\"npm\",\"dependency\":\"yaml\"}'",
    "elif [ -f bun.lock ] || [ -f bun.lockb ]; then",
    "  command -v bun >/dev/null 2>&1 || { echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"failed\",\"reason\":\"missing-tool\",\"tool\":\"bun\"}'; exit 31; }",
    "  bun install --frozen-lockfile --ignore-scripts",
    "  echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"installed\",\"manager\":\"bun\",\"dependency\":\"yaml\"}'",
    "else",
    "  echo '{\"event\":\"prepare-source-dependencies\",\"status\":\"failed\",\"reason\":\"lockfile-missing\",\"dependency\":\"yaml\"}'",
    "  exit 33",
    "fi",
    "ci_timing_emit prepare-source-dependencies succeeded \"$prepare_source_dependencies_started_ms\"",
    "catalog_path=\"$(params.catalog-path)\"",
    "mkdir -p \"$(dirname \"$catalog_path\")\"",
    "catalog_fetch_started_ms=\"$(ci_now_ms)\"",
    "if git_timed catalog-ls-remote 45 git ls-remote --exit-code --heads \"$git_read_url\" \"$(params.gitops-branch)\" >/dev/null; then",
    "  git remote set-url gitops-catalog \"$git_read_url\" 2>/dev/null || git remote add gitops-catalog \"$git_read_url\"",
    "  git_timed catalog-fetch 90 git fetch --depth 1 gitops-catalog \"$(params.gitops-branch)\" >/dev/null || true",
    "  if git cat-file -e FETCH_HEAD:\"$catalog_path\" 2>/dev/null; then",
    "    git show FETCH_HEAD:\"$catalog_path\" > /tmp/hwlab-gitops-artifact-catalog.json",
    "    if node --input-type=module - /tmp/hwlab-gitops-artifact-catalog.json deploy/deploy.yaml \"$(params.services)\" <<'NODE'",
    "import fs from \"node:fs\";",
    "import { readStructuredFile } from \"./scripts/src/structured-config.mjs\";",
    "const [catalogPath, deployPath, selectedServices] = process.argv.slice(2);",
    "const ids = (doc) => (doc.services || []).map((service) => service.serviceId).filter(Boolean);",
    "const selected = (selectedServices || \"\").split(\",\").map((item) => item.trim()).filter(Boolean);",
    "const uniqueSorted = (items) => [...new Set(items)].sort();",
    "const gitops = JSON.parse(fs.readFileSync(catalogPath, \"utf8\"));",
    "const deploy = await readStructuredFile(process.cwd(), deployPath);",
    "const expected = selected.length ? selected : ids(deploy);",
    "const actual = ids(gitops);",
    "const expectedSet = uniqueSorted(expected);",
    "const actualSet = uniqueSorted(actual);",
    "const sameServices = expectedSet.length === actualSet.length && expectedSet.every((item, index) => item === actualSet[index]);",
    "if (!sameServices) {",
    "  const missing = expectedSet.filter((item) => !actualSet.includes(item));",
    "  const extra = actualSet.filter((item) => !expectedSet.includes(item));",
    "  console.error(JSON.stringify({ event: \"gitops-artifact-catalog\", phase: \"prepare-source\", status: \"ignored-stale\", reason: \"service-ids-mismatch\", expected, actual, missing, extra }));",
    "  process.exit(42);",
    "}",
    "NODE",
    "    then",
    "      cp /tmp/hwlab-gitops-artifact-catalog.json \"$catalog_path\"",
    "      echo '{\"event\":\"gitops-artifact-catalog\",\"phase\":\"prepare-source\",\"status\":\"loaded\",\"branch\":\"'\"$(params.gitops-branch)\"'\"}'",
    "    else",
    "      echo '{\"event\":\"gitops-artifact-catalog\",\"phase\":\"prepare-source\",\"status\":\"ignored-stale\",\"reason\":\"service-ids-mismatch\",\"branch\":\"'\"$(params.gitops-branch)\"'\"}'",
    "    fi",
    "  else",
    "    echo '{\"event\":\"gitops-artifact-catalog\",\"phase\":\"prepare-source\",\"status\":\"seed\",\"reason\":\"missing-on-gitops-branch\"}'",
    "  fi",
    "else",
    "  echo '{\"event\":\"gitops-artifact-catalog\",\"phase\":\"prepare-source\",\"status\":\"seed\",\"reason\":\"gitops-branch-missing\"}'",
    "fi",
    "if [ ! -s \"$catalog_path\" ] && [ \"$(params.lane)\" = \"v02\" ]; then",
    "  node --input-type=module - \"$catalog_path\" \"$(params.revision)\" \"$(params.registry-prefix)\" \"$(params.image-tag-mode)\" \"$(params.services)\" <<'NODE'",
    "import fs from 'node:fs';",
    "import { readStructuredFile } from './scripts/src/structured-config.mjs';",
    "const [catalogPath, revision, registryPrefix, imageTagMode, selectedServices] = process.argv.slice(2);",
    "const deploy = await readStructuredFile(process.cwd(), 'deploy/deploy.yaml');",
    "const tag = imageTagMode === 'full' ? revision : revision.slice(0, 7);",
    "const namespace = 'hwlab-v02';",
    "const selected = (selectedServices || '').split(',').filter(Boolean);",
    "const serviceIds = selected.length ? selected : (deploy.services || []).map((service) => service.serviceId);",
    "const services = serviceIds.map((serviceId) => {",
    "  const service = { serviceId, profile: 'v02', namespace, commitId: tag, sourceCommitId: revision, image: `${registryPrefix}/${serviceId}:${tag}`, imageTag: tag, digest: null, buildBackend: 'contract-skeleton' };",
    "  return service;",
    "});",
    "fs.mkdirSync(path.dirname(catalogPath), { recursive: true });",
    `fs.writeFileSync(catalogPath, JSON.stringify({ catalogVersion: 'v1', kind: 'hwlab-artifact-catalog', environment: 'v02', profile: 'v02', namespace, endpoint: ${JSON.stringify(defaultV02RuntimeEndpoint)}, commitId: tag, artifactState: 'contract-skeleton', publish: { registryPrefix, sourceCommitId: revision, imageTag: tag, publishedAt: null }, allowedProfiles: ['v02'], forbiddenProfiles: ['dev', 'prod'], services }, null, 2) + '\\n');`,
    "NODE",
    "  echo '{\"event\":\"gitops-artifact-catalog\",\"phase\":\"prepare-source\",\"status\":\"seeded-v02-skeleton\"}'",
    "fi",
    "ci_timing_emit catalog-fetch succeeded \"$catalog_fetch_started_ms\"",
    `echo ${shellSingleQuote(`node prepare-source complete; validation task count=${primitiveValidationTasks.length}`)}`
  ];
  return `${lines.join("\n")}\n`;
}

function sourceValidationScript(commands) {
  return [
    "#!/bin/sh",
    "set -eu",
    "git config --global --add safe.directory /workspace/source/repo",
    "cd /workspace/source/repo",
    "test \"$(git rev-parse HEAD)\" = \"$(params.revision)\"",
    ...commands
  ].join("\n") + "\n";
}

function primitiveValidationTaskNames() {
  return primitiveValidationTasks.map((task) => task.name);
}

function primitiveValidationTask(task) {
  return {
    name: task.name,
    runAfter: ["prepare-source"],
    workspaces: [{ name: "source", workspace: "source" }],
    taskSpec: {
      params: [
        { name: "revision" },
        { name: "lane" },
        { name: "catalog-path" },
        { name: "image-tag-mode" },
        { name: "source-branch" },
        { name: "gitops-branch" }
      ],
      workspaces: [{ name: "source" }],
      steps: [{ name: task.name, image: ciToolsRunnerImage, env: proxyEnv(), script: sourceValidationScript(task.commands) }]
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "lane", value: "$(params.lane)" },
      { name: "catalog-path", value: "$(params.catalog-path)" },
      { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
      { name: "source-branch", value: "$(params.source-branch)" },
      { name: "gitops-branch", value: "$(params.gitops-branch)" }
    ]
  };
}

function planArtifactsScript() {
  return `#!/bin/sh
set -eu
echo '{"event":"ci-base-image","phase":"plan-artifacts","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
for tool in node git; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"plan-artifacts","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
cd /workspace/source/repo
test "$(git rev-parse HEAD)" = "$(params.revision)"
node scripts/ci-plan.mjs --lane "$(params.lane)" --target-ref HEAD --deploy-config deploy/deploy.yaml --artifact-catalog "$(params.catalog-path)" --registry-prefix "$(params.registry-prefix)" --services "$(params.services)" --verify-reuse-registry > /workspace/source/ci-plan.json
node - <<'NODE'
const fs = require("node:fs");
const plan = JSON.parse(fs.readFileSync("/workspace/source/ci-plan.json", "utf8"));
const selected = String(process.env.HWLAB_SELECTED_SERVICES || "").split(",").map((item) => item.trim()).filter(Boolean);
const allServices = selected.length > 0 ? selected : ${JSON.stringify(defaultServiceIds)};
const affected = new Set(plan.affectedServices || []);
const plannedBuildServices = Array.isArray(plan.buildServices) ? new Set(plan.buildServices) : null;
const selectedSet = new Set(selected);
const byService = new Map((plan.services || []).map((service) => [service.serviceId, service]));
const entries = allServices.map((serviceId) => {
  const service = byService.get(serviceId) || {};
  const serviceSelected = selectedSet.has(serviceId);
  const rolloutAffected = serviceSelected && affected.has(serviceId);
  const envReuse = service.runtimeMode === "env-reuse-git-mirror-checkout" || service.envReuse === true;
  const buildRequired = serviceSelected && (plannedBuildServices ? plannedBuildServices.has(serviceId) : (envReuse ? service.envChanged === true : rolloutAffected));
  return {
    serviceId,
    selected: serviceSelected,
    affected: buildRequired,
    buildRequired,
    rolloutAffected,
    runtimeMode: service.runtimeMode || "service-image",
    envChanged: service.envChanged ?? null,
    codeChanged: service.codeChanged ?? null
  };
});
for (const entry of entries) {
  fs.writeFileSync("/tekton/results/affected-" + entry.serviceId, entry.affected ? "true" : "false");
}
fs.writeFileSync("/workspace/source/affected-services.json", JSON.stringify({
  sourceCommitId: plan.sourceCommitId,
  affectedServices: plan.affectedServices || [],
  rolloutServices: plan.rolloutServices || plan.affectedServices || [],
  buildServices: plan.buildServices || entries.filter((entry) => entry.buildRequired).map((entry) => entry.serviceId),
  reusedServices: plan.reusedServices || [],
  buildSkippedCount: plan.buildSkippedCount || 0,
  changedPathSummary: plan.changedPathSummary || null,
  ciCdPlan: plan.ciCdPlan || null,
  services: plan.services || [],
  entries
}, null, 2) + String.fromCharCode(10));
console.log(JSON.stringify({ event: "ci-plan", sourceCommitId: plan.sourceCommitId, affectedServices: plan.affectedServices || [], rolloutServices: plan.rolloutServices || plan.affectedServices || [], buildServices: plan.buildServices || [], reusedServices: plan.reusedServices || [], buildSkippedCount: plan.buildSkippedCount || 0 }));
NODE
`;
}

function perServicePublishScript() {
  return `#!/bin/sh
set -eu
${ciTimingShellFunction()}
export HWLAB_TEKTON_PIPELINERUN="$(context.pipelineRun.name)"
export HWLAB_TEKTON_TASKRUN="$(context.taskRun.name)"
export HWLAB_TEKTON_TASK="build-$(params.service-id)"
export HWLAB_SOURCE_REVISION="$(params.revision)"
export HWLAB_TIMING_SERVICE_ID="$(params.service-id)"
${dependencyProxyProbeScript("service-image-publish-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
echo '{"event":"ci-base-image","phase":"service-image-publish","serviceId":"'"$(params.service-id)"'","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
for tool in node npm git python3 ssh curl; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"service-image-publish","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
mkdir -p /workspace/service-work/home
export HOME=/workspace/service-work/home
git config --global --add safe.directory /workspace/source/repo
cd /workspace/source/repo
test "$(git rev-parse HEAD)" = "$(params.revision)"
export HWLAB_ARTIFACT_LANE="$(params.lane)"
export HWLAB_ARTIFACT_CATALOG_PATH="$(params.catalog-path)"
export HWLAB_DEPLOY_MANIFEST_PATH="deploy/deploy.yaml"
export HWLAB_ARTIFACT_IMAGE_TAG_MODE="$(params.image-tag-mode)"
mkdir -p /workspace/source/service-results
if [ -s /workspace/source/affected-services.json ] && ! node -e 'const fs=require("node:fs"); const p=JSON.parse(fs.readFileSync("/workspace/source/affected-services.json","utf8")); const service=process.argv[1]; const item=(p.entries||[]).find((entry)=>entry.serviceId===service); process.exit(item && item.affected ? 0 : 1);' "$(params.service-id)"; then
  node - "$(params.service-id)" <<'NODE'
const fs = require("node:fs");
const serviceId = process.argv[2];
const catalog = JSON.parse(fs.readFileSync(process.env.HWLAB_ARTIFACT_CATALOG_PATH, "utf8"));
const plan = fs.existsSync("/workspace/source/affected-services.json") ? JSON.parse(fs.readFileSync("/workspace/source/affected-services.json", "utf8")) : {};
const service = (catalog.services || []).find((item) => item.serviceId === serviceId) || {};
const planned = (plan.services || []).find((item) => item.serviceId === serviceId) || {};
const envReuse = planned.runtimeMode === "env-reuse-git-mirror-checkout" || service.runtimeMode === "env-reuse-git-mirror-checkout" || planned.envReuse === true || service.envReuse === true;
const image = envReuse ? (service.environmentImage || service.image || "") : (service.image || "");
const digest = envReuse ? (service.environmentDigest || service.digest || "not_published") : (service.digest || "not_published");
const imageTag = service.imageTag || (image.includes(":") ? image.slice(image.lastIndexOf(":") + 1) : "");
const repository = image.includes(":") ? image.slice(0, image.lastIndexOf(":")) : image;
const revision = process.env.HWLAB_SOURCE_REVISION || planned.bootCommit || service.bootCommit || service.sourceCommitId || service.commitId || imageTag;
const componentInputHash = envReuse ? (planned.componentInputHash || service.componentInputHash || "") : (service.componentInputHash || "");
const environmentInputHash = envReuse ? (service.environmentInputHash || planned.environmentInputHash || "") : (service.environmentInputHash || "");
const codeInputHash = envReuse ? (planned.codeInputHash || service.codeInputHash || "") : (service.codeInputHash || "");
const values = {
  "service-id": serviceId,
  status: /^sha256:[a-f0-9]{64}$/.test(digest) ? "reused" : "blocked_reuse_unavailable",
  image,
  "image-tag": imageTag,
  digest,
  "repository-digest": /^sha256:[a-f0-9]{64}$/.test(digest) && repository ? repository + "@" + digest : "",
  "source-commit-id": envReuse ? revision : (service.sourceCommitId || service.commitId || imageTag),
  "component-input-hash": componentInputHash,
  "environment-input-hash": environmentInputHash,
  "code-input-hash": codeInputHash,
  "runtime-mode": envReuse ? "env-reuse-git-mirror-checkout" : "service-image",
  "boot-repo": planned.bootRepo || service.bootRepo || "",
  "boot-commit": envReuse ? revision : (service.bootCommit || ""),
  "boot-sh": planned.bootSh || service.bootSh || "",
  "build-created-at": service.buildCreatedAt || "",
  "build-backend": envReuse ? "reused-env-catalog" : "reused-catalog",
  "reused-from": (envReuse ? service.environmentInputHash : service.componentInputHash) || service.commitId || imageTag || "catalog"
};
for (const [name, value] of Object.entries(values)) fs.writeFileSync("/tekton/results/" + name, String(value || ""));
NODE
  echo '{"event":"service-build-skip","serviceId":"'"$(params.service-id)"'","reason":"component-inputs-unchanged"}'
  exit 0
fi
rm -rf /workspace/service-work/repo
mkdir -p /workspace/service-work/repo
tar -C /workspace/source/repo -cf - . | tar -C /workspace/service-work/repo -xo -f -
cd /workspace/service-work/repo
export HWLAB_CI_ARTIFACT_RUN_ID="$(context.pipelineRun.name)-$(params.service-id)"
export HWLAB_CI_ARTIFACT_RUN_OWNER="tekton"
export HWLAB_DEV_REGISTRY_PREFIX="$(params.registry-prefix)"
export HWLAB_DEV_REGISTRY_K8S_NATIVE=1
export HWLAB_NODE_CICD_TIMING=1
export HWLAB_TEKTON_PIPELINERUN
export HWLAB_TEKTON_TASKRUN
export HWLAB_TEKTON_TASK
export HWLAB_SOURCE_REVISION
export PATH="/workspace/buildkit-bin:$PATH"
export HWLAB_BUILDKIT_ADDR="unix:///workspace/buildkit-run/buildkitd.sock"
if [ -n "$(params.base-image)" ]; then export HWLAB_DEV_BASE_IMAGE="$(params.base-image)"; fi
if [ -n "\${HWLAB_DEV_BASE_IMAGE:-}" ]; then
  echo '{"event":"dependency-local-registry-probe-start","phase":"service-image-publish-pre-base-image","serviceId":"'"$(params.service-id)"'","target":"http://127.0.0.1:5000/v2/"}'
  registry_started_at="$(date +%s)"
  curl -fsS --max-time 10 http://127.0.0.1:5000/v2/ >/dev/null
  registry_finished_at="$(date +%s)"
  echo '{"event":"dependency-local-registry-probe","phase":"service-image-publish-pre-base-image","serviceId":"'"$(params.service-id)"'","ok":true,"durationSeconds":'"$((registry_finished_at - registry_started_at))"'}'
fi
buildkit_ready=0
for attempt in $(seq 1 60); do
  if /workspace/buildkit-bin/buildctl --addr "$HWLAB_BUILDKIT_ADDR" debug workers >/dev/null 2>&1; then
    buildkit_ready=1
    break
  fi
  sleep 1
done
if [ "$buildkit_ready" != "1" ]; then
  echo '{"event":"buildkit-sidecar-not-ready","serviceId":"'"$(params.service-id)"'","addr":"'"$HWLAB_BUILDKIT_ADDR"'"}' >&2
  exit 1
fi
HWLAB_CI_PLAN_VERIFY_REUSE_REGISTRY=1 node scripts/artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-config deploy/deploy.yaml --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --report "/workspace/source/service-results/$(params.service-id).json" --tekton-results-dir /tekton/results --quiet-build --concurrency 1 --services "$(params.service-id)" --buildkit-command /workspace/buildkit-bin/buildctl --buildkit-addr "$HWLAB_BUILDKIT_ADDR"
`;
}

function collectArtifactsScript() {
  return `#!/bin/sh
set -eu
echo '{"event":"ci-base-image","phase":"collect-artifacts","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
for tool in node git; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"collect-artifacts","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
cd /workspace/source/repo
test "$(git rev-parse HEAD)" = "$(params.revision)"
export HWLAB_CI_ARTIFACT_RUN_ID="$(context.pipelineRun.name)-collect"
export HWLAB_CI_ARTIFACT_RUN_OWNER="tekton"
export HWLAB_DEV_REGISTRY_PREFIX="$(params.registry-prefix)"
export HWLAB_DEV_REGISTRY_K8S_NATIVE=1
if [ -n "$(params.base-image)" ]; then export HWLAB_DEV_BASE_IMAGE="$(params.base-image)"; fi
export HWLAB_ARTIFACT_LANE="$(params.lane)"
export HWLAB_ARTIFACT_CATALOG_PATH="$(params.catalog-path)"
export HWLAB_DEPLOY_MANIFEST_PATH="deploy/deploy.yaml"
export HWLAB_ARTIFACT_IMAGE_TAG_MODE="$(params.image-tag-mode)"
HWLAB_CI_PLAN_VERIFY_REUSE_REGISTRY=1 node scripts/artifact-publish.mjs --publish --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-config deploy/deploy.yaml --image-tag-mode "$(params.image-tag-mode)" --registry-prefix "$(params.registry-prefix)" --report /workspace/source/dev-artifacts.json --quiet-build --concurrency 1 --services "$(params.services)" --external-service-report-dir /workspace/source/service-results
node scripts/refresh-artifact-catalog.mjs --lane "$(params.lane)" --catalog-path "$(params.catalog-path)" --deploy-config deploy/deploy.yaml --image-tag-mode "$(params.image-tag-mode)" --target-ref HEAD --publish-report /workspace/source/dev-artifacts.json --no-write
`;
}

function gitopsPromoteScript() {
  return `#!/bin/sh
set -eu
${ciTimingShellFunction()}
export HWLAB_TEKTON_PIPELINERUN="$(context.pipelineRun.name)"
export HWLAB_TEKTON_TASKRUN="$(context.taskRun.name)"
export HWLAB_TEKTON_TASK="gitops-promote"
export HWLAB_SOURCE_REVISION="$(params.revision)"
printf 'true' > /tekton/results/runtime-ready-required
echo '{"event":"ci-base-image","phase":"gitops-promote","image":"${ciToolsRunnerImage}","policy":"no-runtime-apt"}'
for tool in node git timeout; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"gitops-promote","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
${gitSshShellFunction()}
git_url_requires_ssh() { case "$1" in git@*|ssh://*) return 0 ;; *) return 1 ;; esac; }
lane="$(params.lane)"
case "$lane" in
  v[0-9][0-9]*) runtime_lane=true ;;
  *) runtime_lane=false ;;
esac
source_head_url_for_setup="$(params.git-url)"
gitops_read_url_for_setup="$(params.git-url)"
if [ "$runtime_lane" = "true" ]; then
  source_head_url_for_setup="$(params.git-read-url)"
  gitops_read_url_for_setup="$(params.git-read-url)"
fi
gitops_write_url_for_setup="$(params.git-write-url)"
if git_url_requires_ssh "$source_head_url_for_setup" || git_url_requires_ssh "$gitops_read_url_for_setup" || git_url_requires_ssh "$gitops_write_url_for_setup"; then
  for tool in ssh ssh-keyscan; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"gitops-promote","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
  git_ssh_setup
else
  echo '{"event":"git-ssh-setup","phase":"gitops-promote","status":"skipped","reason":"non-ssh-git-url"}'
fi
cd /workspace/source/repo
test "$(git rev-parse HEAD)" = "$(params.revision)"

check_source_head() {
  phase="$1"
  expected="\${2:-$(params.revision)}"
  source_head_url="$(params.git-url)"
  if [ "$runtime_lane" = "true" ]; then
    source_head_url="$(params.git-read-url)"
  fi
  latest_file="$(mktemp)"
  if ! git_timed "source-head-$phase" 45 git ls-remote "$source_head_url" "refs/heads/$(params.source-branch)" > "$latest_file"; then
    echo '{"status":"failed","reason":"source-head-check-failed","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'"}'
    exit 1
  fi
  latest="$(cut -f1 "$latest_file" | head -n 1)"
  if [ -z "$latest" ]; then
    echo '{"status":"failed","reason":"source-head-unresolved","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'"}'
    exit 1
  fi
  if [ "$latest" != "$expected" ]; then
    printf 'false' > /tekton/results/runtime-ready-required || true
    echo '{"status":"skipped-stale-source","verdict":"superseded","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'","expectedRevision":"'"$expected"'","latestRevision":"'"$latest"'"}'
    exit 0
  fi
}

check_source_head before-render
git config --global user.name "HWLAB node GitOps Bot"
git config --global user.email "hwlab-node-gitops-bot@users.noreply.github.com"
catalog_path="$(params.catalog-path)"
runtime_path="$(params.runtime-path)"
gitops_root_from_runtime_path() {
  path="$1"
  case "$path" in
    */*) printf '%s\n' "\${path%/*}" ;;
    *) printf '.\n' ;;
  esac
}
gitops_root="$(gitops_root_from_runtime_path "$runtime_path")"

argo_hard_refresh_runtime_lane() {
  if [ "$runtime_lane" != "true" ]; then return 0; fi
  ARGO_APPLICATION="hwlab-node-$lane" ARGO_FIELD_MANAGER="hwlab-$lane-gitops-promote" node <<'NODE'
const fs = require("node:fs");
const https = require("node:https");

const host = process.env.KUBERNETES_SERVICE_HOST;
const port = process.env.KUBERNETES_SERVICE_PORT || "443";
const startedAt = Date.now();
const application = process.env.ARGO_APPLICATION || "hwlab-node-v02";
const fieldManager = process.env.ARGO_FIELD_MANAGER || "hwlab-v02-gitops-promote";
const pipelineRun = process.env.HWLAB_TEKTON_PIPELINERUN || null;
const taskRun = process.env.HWLAB_TEKTON_TASKRUN || null;
const task = process.env.HWLAB_TEKTON_TASK || null;
const revision = process.env.HWLAB_SOURCE_REVISION || null;

function emit(payload) {
  console.log(JSON.stringify({
    event: "node-cicd-timing",
    schemaVersion: "v1",
    stage: "argo-hard-refresh",
    pipelineRun,
    taskRun,
    task,
    revision,
    application,
    source: "scripts/gitops-render.mjs",
    at: new Date().toISOString(),
    ...payload
  }));
}

function safeJson(text) {
  try {
    return JSON.parse(text);
  } catch {
    return null;
  }
}

function request(method, path, body, contentType = "application/merge-patch+json") {
  const token = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/token", "utf8");
  const ca = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
  const payload = body ? JSON.stringify(body) : "";
  const headers = { Authorization: "Bearer " + token };
  if (payload) {
    headers["Content-Type"] = contentType;
    headers["Content-Length"] = Buffer.byteLength(payload);
  }
  return new Promise((resolve, reject) => {
    const req = https.request({ host, port, method, path, ca, headers }, (res) => {
      let data = "";
      res.setEncoding("utf8");
      res.on("data", (chunk) => { data += chunk; });
      res.on("end", () => resolve({ statusCode: res.statusCode || 0, body: data, json: safeJson(data) }));
    });
    req.on("error", reject);
    if (payload) req.write(payload);
    req.end();
  });
}

(async () => {
  if (!host) {
    emit({ status: "skipped", reason: "kubernetes-service-host-missing", durationMs: Date.now() - startedAt });
    return;
  }
  const response = await request(
    "PATCH",
    "/apis/argoproj.io/v1alpha1/namespaces/argocd/applications/" + encodeURIComponent(application) + "?fieldManager=" + encodeURIComponent(fieldManager),
    { metadata: { annotations: { "argocd.argoproj.io/refresh": "hard" } } }
  );
  if (response.statusCode >= 200 && response.statusCode < 300) {
    emit({ status: "succeeded", durationMs: Date.now() - startedAt, statusCode: response.statusCode });
    return;
  }
  emit({ status: "degraded", reason: "argo-refresh-patch-failed", durationMs: Date.now() - startedAt, statusCode: response.statusCode, body: response.body.slice(0, 1000) });
})().catch((error) => {
  emit({ status: "degraded", reason: "argo-refresh-patch-error", durationMs: Date.now() - startedAt, error: error.message });
});
NODE
}

if [ -s /workspace/source/dev-artifacts.json ]; then
  node scripts/refresh-artifact-catalog.mjs --lane "$lane" --catalog-path "$catalog_path" --deploy-config deploy/deploy.yaml --image-tag-mode "$(params.image-tag-mode)" --target-ref "$(params.revision)" --publish-report /workspace/source/dev-artifacts.json --write
fi
gitops_render_started_ms="$(ci_now_ms)"
node scripts/run-bun.mjs scripts/gitops-render.mjs --lane "$lane" --catalog-path "$catalog_path" --image-tag-mode "$(params.image-tag-mode)" --source-revision "$(params.revision)" --source-repo "$(params.git-url)" --source-branch "$(params.source-branch)" --gitops-branch "$(params.gitops-branch)" --gitops-root "$gitops_root" --out "$gitops_root" --registry-prefix "$(params.registry-prefix)" --use-deploy-images
node scripts/run-bun.mjs scripts/gitops-render.mjs --lane "$lane" --catalog-path "$catalog_path" --image-tag-mode "$(params.image-tag-mode)" --source-revision "$(params.revision)" --source-repo "$(params.git-url)" --source-branch "$(params.source-branch)" --gitops-branch "$(params.gitops-branch)" --gitops-root "$gitops_root" --out "$gitops_root" --registry-prefix "$(params.registry-prefix)" --use-deploy-images --check
ci_timing_emit gitops-render succeeded "$gitops_render_started_ms"
check_source_head before-push
workdir="$(mktemp -d)"
gitops_read_url="$(params.git-url)"
gitops_write_url="$(params.git-write-url)"
if [ "$runtime_lane" = "true" ]; then
  gitops_read_url="$(params.git-read-url)"
fi
gitops_clone_started_ms="$(ci_now_ms)"
git_timed gitops-clone 180 git clone --no-checkout "$gitops_read_url" "$workdir/gitops"
cd "$workdir/gitops"
git remote set-url origin "$gitops_write_url"
old_runtime_snapshot="$workdir/old-runtime-snapshot"
if git_timed gitops-branch-ls 45 git ls-remote --exit-code --heads origin "$(params.gitops-branch)" >/dev/null; then
  git_timed gitops-fetch 90 git fetch origin "$(params.gitops-branch)"
  git checkout -B "$(params.gitops-branch)" "origin/$(params.gitops-branch)"
  if [ "$runtime_lane" = "true" ] && [ -d "$runtime_path" ]; then
    mkdir -p "$old_runtime_snapshot"
    cp -a "$runtime_path"/. "$old_runtime_snapshot"/
  fi
  if [ "$runtime_lane" = "true" ]; then rm -rf "$runtime_path" "$catalog_path"; else rm -rf deploy/gitops/node "$catalog_path"; fi
else
  git checkout --orphan "$(params.gitops-branch)"
  git rm -rf . >/dev/null 2>&1 || true
fi
ci_timing_emit gitops-clone succeeded "$gitops_clone_started_ms"
mkdir -p "$(dirname "$runtime_path")" "$(dirname "$catalog_path")"
if [ "$runtime_lane" = "true" ]; then
  cp -a "/workspace/source/repo/$runtime_path" "$runtime_path"
  cp "/workspace/source/repo/$catalog_path" "$catalog_path"
  git add "$catalog_path" "$runtime_path"
else
  mkdir -p deploy/gitops
  cp -a /workspace/source/repo/deploy/gitops/node deploy/gitops/node
  cp "/workspace/source/repo/$catalog_path" "$catalog_path"
  git add "$catalog_path" deploy/gitops/node
fi
if [ "$runtime_lane" = "true" ] && [ -s /workspace/source/affected-services.json ]; then
  runtime_noop_decision="$(node - "$runtime_path" "$old_runtime_snapshot" /workspace/source/affected-services.json <<'NODE'
const fs = require("node:fs");
const path = require("node:path");

const [runtimePath, oldRuntimePath, planPath] = process.argv.slice(2);

function readJson(filePath) {
  return JSON.parse(fs.readFileSync(filePath, "utf8"));
}

function stable(value) {
  if (Array.isArray(value)) return "[" + value.map(stable).join(",") + "]";
  if (value && typeof value === "object") {
    return "{" + Object.keys(value).sort().map((key) => JSON.stringify(key) + ":" + stable(value[key])).join(",") + "}";
  }
  return JSON.stringify(value);
}

function scrub(value) {
  if (Array.isArray(value)) return value.map(scrub);
  if (!value || typeof value !== "object") return value;
  const result = {};
  for (const [key, child] of Object.entries(value)) {
    if (key === "hwlab.pikastech.local/source-commit" ||
        key === "hwlab.pikastech.local/artifact-source-commit" ||
        key === "hwlab.pikastech.local/boot-commit" ||
        key === "sourceCommitId" ||
        key === "bootCommit") {
      result[key] = "<runtime-source-identity>";
      continue;
    }
    const envName = String(value.name || "");
    if (key === "value" && /^HWLAB_.*COMMIT/.test(envName)) {
      result[key] = "<runtime-source-identity>";
      continue;
    }
    result[key] = scrub(child);
  }
  return result;
}

function listFiles(rootDir) {
  if (!rootDir || !fs.existsSync(rootDir)) return null;
  const files = [];
  function walk(current) {
    for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
      const fullPath = path.join(current, entry.name);
      if (entry.isDirectory()) walk(fullPath);
      else if (entry.isFile()) files.push(path.relative(rootDir, fullPath).replaceAll(path.sep, "/"));
    }
  }
  walk(rootDir);
  return files.sort();
}

function normalizedTree(rootDir) {
  const files = listFiles(rootDir);
  if (!files) return null;
  const entries = {};
  for (const relativePath of files) {
    const filePath = path.join(rootDir, relativePath);
    const text = fs.readFileSync(filePath, "utf8");
    try {
      entries[relativePath] = stable(scrub(JSON.parse(text)));
    } catch {
      entries[relativePath] = text.replace(/[a-f0-9]{40}/gu, "<runtime-source-identity>");
    }
  }
  return stable(entries);
}

const plan = readJson(planPath);
const buildServices = Array.isArray(plan.buildServices) ? plan.buildServices : [];
const rolloutServices = Array.isArray(plan.rolloutServices) ? plan.rolloutServices : [];
if (buildServices.length > 0 || rolloutServices.length > 0) {
  process.stdout.write("runtime-required");
  process.exit(0);
}

const oldTree = normalizedTree(oldRuntimePath);
const newTree = normalizedTree(runtimePath);
process.stdout.write(oldTree && newTree && oldTree === newTree ? "runtime-identity-only" : "runtime-required");
NODE
)"
  if [ "$runtime_noop_decision" = "runtime-identity-only" ]; then
    printf 'false' > /tekton/results/runtime-ready-required
    echo '{"status":"skipped-runtime-unchanged","reason":"runtime-identity-only","gitopsBranch":"'"$(params.gitops-branch)"'","sourceRevision":"'"$(params.revision)"'"}'
    ci_timing_emit gitops-commit skipped "$(ci_now_ms)"
    ci_timing_emit gitops-push skipped "$(ci_now_ms)"
    exit 0
  fi
fi
if git diff --cached --quiet; then
  printf 'false' > /tekton/results/runtime-ready-required
  echo '{"status":"unchanged","gitopsBranch":"'"$(params.gitops-branch)"'","sourceRevision":"'"$(params.revision)"'"}'
  ci_timing_emit gitops-commit unchanged "$(ci_now_ms)"
  ci_timing_emit gitops-push unchanged "$(ci_now_ms)"
  exit 0
fi
short="$(printf '%.7s' "$(params.revision)")"
gitops_commit_started_ms="$(ci_now_ms)"
git commit -m "chore: promote node GitOps source $short"
ci_timing_emit gitops-commit succeeded "$gitops_commit_started_ms"
gitops_push_started_ms="$(ci_now_ms)"
git_timed gitops-push 120 git push origin "HEAD:$(params.gitops-branch)"
ci_timing_emit gitops-push succeeded "$gitops_push_started_ms"
argo_hard_refresh_runtime_lane
echo '{"status":"pushed","gitopsBranch":"'"$(params.gitops-branch)"'","sourceRevision":"'"$(params.revision)"'","gitopsWriteUrl":"'"$gitops_write_url"'"}'
`;
}

function controlPlaneReconcileScript() {
  return `#!/bin/sh
set -eu
${dependencyProxyProbeScript("control-plane-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
echo '{"event":"ci-base-image","phase":"control-plane-reconciler","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
for tool in node npm git python3 ssh curl timeout; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"control-plane-reconciler","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
${gitSshShellFunction()}
git_ssh_setup
workdir="$(mktemp -d)"
git_timed control-plane-clone 180 git clone --depth 1 --branch "$SOURCE_BRANCH" "$GIT_READ_URL" "$workdir/repo"
cd "$workdir/repo"
git remote set-url origin "$GIT_READ_URL"
revision="$(git rev-parse HEAD)"
: "\${LANE:?LANE is required}"
: "\${CATALOG_PATH:?CATALOG_PATH is required}"
: "\${IMAGE_TAG_MODE:?IMAGE_TAG_MODE is required}"
: "\${RUNTIME_PATH:?RUNTIME_PATH is required}"
gitops_root="\${RUNTIME_PATH%/*}"
if [ "$gitops_root" = "$RUNTIME_PATH" ]; then gitops_root="."; fi
node scripts/run-bun.mjs scripts/gitops-render.mjs --lane "$LANE" --catalog-path "$CATALOG_PATH" --image-tag-mode "$IMAGE_TAG_MODE" --source-revision "$revision" --source-repo "$GIT_URL" --source-branch "$SOURCE_BRANCH" --gitops-branch "$GITOPS_BRANCH" --gitops-root "$gitops_root" --out "$gitops_root" --registry-prefix "$REGISTRY_PREFIX"
node scripts/run-bun.mjs scripts/gitops-render.mjs --lane "$LANE" --catalog-path "$CATALOG_PATH" --image-tag-mode "$IMAGE_TAG_MODE" --source-revision "$revision" --source-repo "$GIT_URL" --source-branch "$SOURCE_BRANCH" --gitops-branch "$GITOPS_BRANCH" --gitops-root "$gitops_root" --out "$gitops_root" --registry-prefix "$REGISTRY_PREFIX" --check
node <<'NODE'
const fs = require("node:fs");
const https = require("node:https");

function requiredEnv(name) {
  const value = process.env[name];
  if (!value) throw new Error(name + " is required");
  return value;
}

const namespace = requiredEnv("POD_NAMESPACE");
const host = process.env.KUBERNETES_SERVICE_HOST;
const port = process.env.KUBERNETES_SERVICE_PORT || "443";
if (!host) throw new Error("KUBERNETES_SERVICE_HOST is not available");

const token = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/token", "utf8");
const ca = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
const tektonDir = requiredEnv("TEKTON_DIR");
const argoFiles = String(process.env.ARGO_FILES || "").split(",").map((item) => item.trim()).filter(Boolean);
const fieldManager = requiredEnv("FIELD_MANAGER");
const eventName = requiredEnv("RECONCILE_EVENT");
const manifestFiles = [
  "deploy/gitops/node/" + tektonDir + "/rbac.yaml",
  "deploy/gitops/node/" + tektonDir + "/pipeline.yaml",
  ...(process.env.LANE === "v02" ? [] : [
    "deploy/gitops/node/" + tektonDir + "/poller.yaml",
    "deploy/gitops/node/" + tektonDir + "/control-plane-reconciler.yaml"
  ]),
  ...argoFiles
];
const plurals = new Map([
  ["ServiceAccount", "serviceaccounts"],
  ["Role", "roles"],
  ["RoleBinding", "rolebindings"],
  ["Pipeline", "pipelines"],
  ["CronJob", "cronjobs"],
  ["Application", "applications"],
  ["AppProject", "appprojects"]
]);

function encode(value) {
  return encodeURIComponent(String(value));
}

function itemsFrom(file) {
  const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
  return parsed.kind === "List" ? parsed.items || [] : [parsed];
}

function apiPath(item) {
  if (item.kind === "Namespace") return null;
  const name = item.metadata?.name;
  if (!name) throw new Error("manifest item is missing metadata.name");
  const ns = item.metadata?.namespace || namespace;
  const plural = plurals.get(item.kind);
  if (!plural) throw new Error("unsupported reconciler manifest kind " + item.kind);
  if (item.apiVersion === "v1") return "/api/v1/namespaces/" + encode(ns) + "/" + plural + "/" + encode(name);
  const parts = String(item.apiVersion || "").split("/");
  if (parts.length !== 2) throw new Error("unsupported apiVersion " + item.apiVersion + " for " + item.kind);
  return "/apis/" + encode(parts[0]) + "/" + encode(parts[1]) + "/namespaces/" + encode(ns) + "/" + plural + "/" + encode(name);
}

function reconcilePolicy(item) {
  const ns = item.metadata?.namespace || namespace;
  const crossNamespaceRbac = (item.kind === "Role" || item.kind === "RoleBinding") && ns !== namespace;
  if (crossNamespaceRbac && process.env.HWLAB_RECONCILE_CROSS_NAMESPACE_RBAC !== "1") {
    return { action: "skip", reason: "cross-namespace-rbac-bootstrap-managed", namespace: ns };
  }
  return { action: "apply", namespace: ns };
}

function request(method, path, body) {
  const payload = body ? JSON.stringify(body) : "";
  const headers = { Authorization: "Bearer " + token };
  if (payload) {
    headers["Content-Type"] = "application/apply-patch+yaml";
    headers["Content-Length"] = Buffer.byteLength(payload);
  }
  return new Promise((resolve, reject) => {
    const req = https.request({ host, port, method, path, ca, headers }, (res) => {
      let data = "";
      res.setEncoding("utf8");
      res.on("data", (chunk) => { data += chunk; });
      res.on("end", () => resolve({ statusCode: res.statusCode || 0, body: data }));
    });
    req.on("error", reject);
    if (payload) req.write(payload);
    req.end();
  });
}

(async () => {
  const results = [];
  for (const file of manifestFiles) {
    for (const item of itemsFrom(file)) {
      const policy = reconcilePolicy(item);
      if (policy.action === "skip") {
        results.push({ file, kind: item.kind, name: item.metadata?.name || null, namespace: policy.namespace, status: "skipped", reason: policy.reason });
        continue;
      }
      const path = apiPath(item);
      if (!path) {
        results.push({ file, kind: item.kind, name: item.metadata?.name || null, status: "skipped-cluster-scoped" });
        continue;
      }
      const response = await request("PATCH", path + "?fieldManager=" + encode(fieldManager) + "&force=true", item);
      if (response.statusCode < 200 || response.statusCode > 299) {
        throw new Error("apply failed for " + item.kind + "/" + item.metadata.name + " status=" + response.statusCode + " body=" + response.body.slice(0, 1000));
      }
      results.push({ file, kind: item.kind, name: item.metadata.name, status: "applied", statusCode: response.statusCode });
    }
  }
  console.log(JSON.stringify({ event: eventName, sourceRevision: process.env.RECONCILE_REVISION || null, results }, null, 2));
})().catch((error) => {
  console.error(error.stack || error.message);
  process.exitCode = 1;
});
NODE
`;
}

function pollerScript() {
  return `#!/bin/sh
set -eu
${dependencyProxyProbeScript("poller-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
echo '{"event":"ci-base-image","phase":"poller","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
for tool in node git ssh curl timeout; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"poller","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
${gitSshShellFunction()}
git_ssh_setup
workdir="$(mktemp -d)"
git_timed poller-clone 180 git clone --depth 1 --branch "$SOURCE_BRANCH" "$GIT_READ_URL" "$workdir/repo"
cd "$workdir/repo"
git remote set-url origin "$GIT_READ_URL"
revision="$(git rev-parse HEAD)"
subject="$(git log -1 --pretty=%s)"
case "$subject" in
  "chore: promote node GitOps source "*)
    echo "Skipping generated GitOps promotion commit $revision"
    exit 0
    ;;
esac
short="$(printf '%.12s' "$revision")"
: "\${PIPELINERUN_PREFIX:?PIPELINERUN_PREFIX is required}"
: "\${GITOPS_TARGET:?GITOPS_TARGET is required}"
prefix="$PIPELINERUN_PREFIX"
name="$prefix-$short"
export POLLER_REVISION="$revision"
export POLLER_PIPELINERUN="$name"
export POLLER_SOURCE_SUBJECT="$subject"
echo "Checking $GITOPS_TARGET source $revision with PipelineRun $name"
node <<'NODE'
const fs = require("node:fs");
const https = require("node:https");

function requiredEnv(name) {
  const value = process.env[name];
  if (!value) throw new Error(name + " is required");
  return value;
}

function optionalEnv(name) {
  return process.env[name] || "";
}

const namespace = requiredEnv("POD_NAMESPACE");
const name = requiredEnv("POLLER_PIPELINERUN");
const revision = requiredEnv("POLLER_REVISION");
const host = process.env.KUBERNETES_SERVICE_HOST;
const port = process.env.KUBERNETES_SERVICE_PORT || "443";
if (!host) throw new Error("KUBERNETES_SERVICE_HOST is not available");

const token = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/token", "utf8");
const ca = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");

function request(method, path, body) {
  const payload = body ? JSON.stringify(body) : "";
  const headers = { Authorization: "Bearer " + token };
  if (payload) {
    headers["Content-Type"] = "application/json";
    headers["Content-Length"] = Buffer.byteLength(payload);
  }
  return new Promise((resolve, reject) => {
    const req = https.request({ host, port, method, path, ca, headers }, (res) => {
      let data = "";
      res.setEncoding("utf8");
      res.on("data", (chunk) => { data += chunk; });
      res.on("end", () => resolve({ statusCode: res.statusCode || 0, body: data }));
    });
    req.on("error", reject);
    if (payload) req.write(payload);
    req.end();
  });
}

const labels = {
  "app.kubernetes.io/part-of": "hwlab",
  "hwlab.pikastech.local/gitops-target": requiredEnv("GITOPS_TARGET"),
  "hwlab.pikastech.local/source-commit": revision,
  "hwlab.pikastech.local/trigger": "polling"
};

const pipelineRun = {
  apiVersion: "tekton.dev/v1",
  kind: "PipelineRun",
  metadata: {
    name,
    namespace,
    labels,
    annotations: {
      "hwlab.pikastech.local/source-subject": optionalEnv("POLLER_SOURCE_SUBJECT"),
      "hwlab.pikastech.local/source-branch": requiredEnv("SOURCE_BRANCH"),
      "hwlab.pikastech.local/gitops-branch": requiredEnv("GITOPS_BRANCH")
    }
  },
  spec: {
    pipelineRef: { name: requiredEnv("PIPELINE_NAME") },
    taskRunTemplate: {
      serviceAccountName: requiredEnv("SERVICE_ACCOUNT_NAME"),
      podTemplate: { hostNetwork: true, dnsPolicy: "ClusterFirstWithHostNet", securityContext: { fsGroup: 1000 } }
    },
    params: [
      { name: "git-url", value: requiredEnv("GIT_URL") },
      { name: "git-read-url", value: requiredEnv("GIT_READ_URL") },
      { name: "source-branch", value: requiredEnv("SOURCE_BRANCH") },
      { name: "gitops-branch", value: requiredEnv("GITOPS_BRANCH") },
      { name: "lane", value: requiredEnv("LANE") },
      { name: "catalog-path", value: requiredEnv("CATALOG_PATH") },
      { name: "image-tag-mode", value: requiredEnv("IMAGE_TAG_MODE") },
      { name: "runtime-path", value: requiredEnv("RUNTIME_PATH") },
      { name: "revision", value: revision },
      { name: "registry-prefix", value: requiredEnv("REGISTRY_PREFIX") },
      { name: "services", value: requiredEnv("SERVICES") },
      { name: "base-image", value: requiredEnv("BASE_IMAGE") }
    ],
    workspaces: [
      { name: "source", volumeClaimTemplate: { spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: "8Gi" } } } } },
      { name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }
    ]
  }
};

const base = "/apis/tekton.dev/v1/namespaces/" + encodeURIComponent(namespace) + "/pipelineruns";
const item = base + "/" + encodeURIComponent(name);

(async () => {
  const existing = await request("GET", item);
  if (existing.statusCode === 200) {
    console.log(JSON.stringify({ status: "exists", pipelineRun: name, revision }));
    return;
  }
  if (existing.statusCode !== 404) {
    throw new Error("unexpected PipelineRun lookup status " + existing.statusCode + ": " + existing.body.slice(0, 500));
  }
  const created = await request("POST", base, pipelineRun);
  if (created.statusCode < 200 || created.statusCode > 299) {
    throw new Error("PipelineRun create failed with status " + created.statusCode + ": " + created.body.slice(0, 1000));
  }
  console.log(JSON.stringify({ status: "created", pipelineRun: name, revision }));
})().catch((error) => {
  console.error(error.stack || error.message);
  process.exitCode = 1;
});
NODE
`;
}

function ciLaneSettings(argsOrLane = "node") {
  const lane = typeof argsOrLane === "string" ? argsOrLane : argsOrLane.lane;
  if (isRuntimeLane(lane)) {
    const namespace = namespaceNameForProfile(lane);
    return {
      lane,
      profile: lane,
      gitopsTarget: lane,
      pipelineName: `${namespace}-ci-image-publish`,
      pipelineRunPrefix: `${namespace}-ci-poll`,
      serviceAccountName: `${namespace}-tekton-runner`,
      pollerName: `${namespace}-branch-poller`,
      controlPlaneReconcilerName: `${namespace}-control-plane-reconciler`,
      tektonDir: `tekton-${lane}`,
      catalogPath: typeof argsOrLane === "object" ? argsOrLane.catalogPath : `deploy/artifact-catalog.${lane}.json`,
      imageTagMode: typeof argsOrLane === "object" ? argsOrLane.imageTagMode : "full",
      runtimeNamespace: namespace
    };
  }
  return {
    lane: "node",
    profile: "dev",
    gitopsTarget: "node",
    pipelineName: "hwlab-node-ci-image-publish",
    pipelineRunPrefix: "hwlab-node-ci-poll",
    serviceAccountName: "hwlab-tekton-runner",
    pollerName: "hwlab-node-branch-poller",
    controlPlaneReconcilerName: "hwlab-node-control-plane-reconciler",
    tektonDir: "tekton",
    catalogPath: "deploy/artifact-catalog.dev.json",
    imageTagMode: "short",
    runtimeNamespace: "hwlab-dev"
  };
}

function tektonRbac(args = { lane: "node" }) {
  const settings = ciLaneSettings(args);
  if (isRuntimeLane(settings.lane)) {
    const runtimeObserverName = `${settings.runtimeNamespace}-runtime-observer`;
    const pipelineRunWriterName = `${settings.runtimeNamespace}-pipelinerun-writer`;
    const argoReconcilerName = `${settings.runtimeNamespace}-argocd-reconciler`;
    return {
      apiVersion: "v1",
      kind: "List",
      items: [
        { apiVersion: "v1", kind: "Namespace", metadata: { name: "hwlab-ci" } },
        { apiVersion: "v1", kind: "ServiceAccount", metadata: { name: settings.serviceAccountName, namespace: "hwlab-ci" } },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "Role",
          metadata: { name: runtimeObserverName, namespace: settings.runtimeNamespace },
          rules: [
            { apiGroups: [""], resources: ["pods", "services", "configmaps"], verbs: ["get", "list", "watch"] },
            { apiGroups: ["apps"], resources: ["deployments", "statefulsets"], verbs: ["get", "list", "watch"] },
            { apiGroups: ["batch"], resources: ["jobs"], verbs: ["get", "list", "watch"] }
          ]
        },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "RoleBinding",
          metadata: { name: runtimeObserverName, namespace: settings.runtimeNamespace },
          subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
          roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: runtimeObserverName }
        },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "Role",
          metadata: { name: pipelineRunWriterName, namespace: "hwlab-ci" },
          rules: [
            { apiGroups: ["tekton.dev"], resources: ["pipelineruns"], verbs: ["get", "list", "create"] },
            { apiGroups: ["tekton.dev"], resources: ["pipelines"], verbs: ["get", "patch", "create"] },
            { apiGroups: ["batch"], resources: ["cronjobs"], verbs: ["get", "patch", "create"] },
            { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] },
            { apiGroups: [""], resources: ["serviceaccounts"], verbs: ["get", "patch", "create"] }
          ]
        },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "RoleBinding",
          metadata: { name: pipelineRunWriterName, namespace: "hwlab-ci" },
          subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
          roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: pipelineRunWriterName }
        },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "Role",
          metadata: { name: argoReconcilerName, namespace: "argocd" },
          rules: [
            { apiGroups: ["argoproj.io"], resources: ["applications", "appprojects"], verbs: ["get", "patch", "create"] },
            { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }
          ]
        },
        {
          apiVersion: "rbac.authorization.k8s.io/v1",
          kind: "RoleBinding",
          metadata: { name: argoReconcilerName, namespace: "argocd" },
          subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
          roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: argoReconcilerName }
        }
      ]
    };
  }
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      { apiVersion: "v1", kind: "Namespace", metadata: { name: "hwlab-ci" } },
      { apiVersion: "v1", kind: "ServiceAccount", metadata: { name: "hwlab-tekton-runner", namespace: "hwlab-ci" } },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "Role",
        metadata: { name: "hwlab-node-control-plane-reconciler", namespace: "hwlab-dev" },
        rules: [
          { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }
        ]
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "RoleBinding",
        metadata: { name: "hwlab-node-control-plane-reconciler", namespace: "hwlab-dev" },
        subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
        roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-node-control-plane-reconciler" }
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "Role",
        metadata: { name: "hwlab-tekton-runtime-observer", namespace: "hwlab-dev" },
        rules: [
          { apiGroups: [""], resources: ["pods", "services", "configmaps"], verbs: ["get", "list", "watch"] },
          { apiGroups: ["apps"], resources: ["deployments", "statefulsets"], verbs: ["get", "list", "watch"] },
          { apiGroups: ["batch"], resources: ["jobs"], verbs: ["get", "list", "watch"] }
        ]
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "RoleBinding",
        metadata: { name: "hwlab-tekton-runtime-observer", namespace: "hwlab-dev" },
        subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
        roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-tekton-runtime-observer" }
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "Role",
        metadata: { name: "hwlab-tekton-pipelinerun-writer", namespace: "hwlab-ci" },
        rules: [
          { apiGroups: ["tekton.dev"], resources: ["pipelineruns"], verbs: ["get", "list", "create"] },
          { apiGroups: ["tekton.dev"], resources: ["pipelines"], verbs: ["get", "patch", "create"] },
          { apiGroups: ["batch"], resources: ["cronjobs"], verbs: ["get", "patch", "create"] },
          { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] },
          { apiGroups: [""], resources: ["serviceaccounts"], verbs: ["get", "patch", "create"] }
        ]
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "RoleBinding",
        metadata: { name: "hwlab-tekton-pipelinerun-writer", namespace: "hwlab-ci" },
        subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
        roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-tekton-pipelinerun-writer" }
      }
    ]
  };
}

function buildTaskName(serviceId) {
  return `build-${serviceId}`;
}

function affectedResultName(serviceId) {
  return `affected-${serviceId}`;
}

const serviceResultFields = Object.freeze([
  "status",
  "service-id",
  "image",
  "image-tag",
  "digest",
  "repository-digest",
  "source-commit-id",
  "component-input-hash",
  "environment-input-hash",
  "code-input-hash",
  "runtime-mode",
  "boot-repo",
  "boot-commit",
  "boot-sh",
  "build-created-at",
  "build-backend",
  "reused-from"
]);

function serviceResultParamName(serviceId, field) {
  return `${serviceId}-${field}`;
}

function serviceResultEnvName(serviceId, field) {
  return `HWLAB_SERVICE_RESULT_${serviceId.toUpperCase().replace(/[^A-Z0-9]+/gu, "_")}_${field.toUpperCase().replace(/[^A-Z0-9]+/gu, "_")}`;
}

function serviceResultParams(serviceIds = defaultServiceIds) {
  return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({ name: serviceResultParamName(serviceId, field), default: "" })));
}

function serviceResultParamValues(serviceIds = defaultServiceIds) {
  return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({
    name: serviceResultParamName(serviceId, field),
    value: `$(tasks.${buildTaskName(serviceId)}.results.${field})`
  })));
}

function serviceResultEnv(serviceIds = defaultServiceIds) {
  return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({
    name: serviceResultEnvName(serviceId, field),
    value: `$(params.${serviceResultParamName(serviceId, field)})`
  })));
}

function serviceWorkVolume() {
  return { name: "service-work", emptyDir: {} };
}

function buildkitBinVolume() {
  return { name: "buildkit-bin", emptyDir: {} };
}

function buildkitRunVolume() {
  return { name: "buildkit-run", emptyDir: {} };
}

function prepareBuildkitClientStep() {
  return {
    name: "prepare-buildkit-client",
    image: buildkitRunnerImage,
    securityContext: { runAsUser: 0, runAsGroup: 0 },
    volumeMounts: [{ name: "buildkit-bin", mountPath: "/workspace/buildkit-bin" }],
    script: `#!/bin/sh
set -eu
mkdir -p /workspace/buildkit-bin
cp /usr/bin/buildctl /workspace/buildkit-bin/
chmod +x /workspace/buildkit-bin/*
`
  };
}

function buildkitSidecar() {
  return {
    name: "buildkitd",
    image: buildkitRunnerImage,
    args: ["--addr", "unix:///workspace/buildkit-run/buildkitd.sock", "--oci-worker-no-process-sandbox"],
    env: proxyEnv(),
    volumeMounts: [{ name: "buildkit-run", mountPath: "/workspace/buildkit-run" }],
    securityContext: {
      runAsUser: 1000,
      runAsGroup: 1000,
      allowPrivilegeEscalation: true,
      appArmorProfile: { type: "Unconfined" },
      seccompProfile: { type: "Unconfined" }
    }
  };
}

function planArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
  return {
    name: "plan-artifacts",
    runAfter: primitiveValidationTaskNames(),
    workspaces: [{ name: "source", workspace: "source" }],
    taskSpec: {
      params: [
        { name: "revision" },
        { name: "catalog-path" },
        { name: "registry-prefix" },
        { name: "services" }
      ],
      results: serviceIds.map((serviceId) => ({ name: affectedResultName(serviceId), description: `${serviceId} changed according to ci-plan` })),
      workspaces: [{ name: "source" }],
      steps: [{
        name: "plan",
        image: ciToolsRunnerImage,
        env: [
          { name: "HWLAB_SELECTED_SERVICES", value: "$(params.services)" },
          { name: "HWLAB_DEV_REGISTRY_K8S_NATIVE", value: "1" },
          { name: "HWLAB_TEKTON_PIPELINERUN", value: "$(context.pipelineRun.name)" },
          ...proxyEnv()
        ],
        script: planArtifactsScript()
      }]
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "catalog-path", value: "$(params.catalog-path)" },
      { name: "registry-prefix", value: "$(params.registry-prefix)" },
      { name: "services", value: "$(params.services)" }
    ]
  };
}

function perServiceBuildTask(serviceId, { runAfter = ["plan-artifacts"] } = {}) {
  return {
    name: buildTaskName(serviceId),
    runAfter,
    workspaces: [{ name: "source", workspace: "source" }],
    when: [{ input: `$(tasks.plan-artifacts.results.${affectedResultName(serviceId)})`, operator: "in", values: ["true"] }],
    taskSpec: {
      params: [
        { name: "revision" },
        { name: "lane" },
        { name: "catalog-path" },
        { name: "image-tag-mode" },
        { name: "registry-prefix" },
        { name: "service-id" },
        { name: "base-image" }
      ],
      results: serviceResultFields.map((field) => ({ name: field, description: `${serviceId} ${field}` })),
      workspaces: [{ name: "source" }],
      volumes: [serviceWorkVolume(), buildkitBinVolume(), buildkitRunVolume()],
      sidecars: [buildkitSidecar()],
      steps: [
        prepareBuildkitClientStep(),
        {
          name: "publish",
          image: ciToolsRunnerImage,
          securityContext: { runAsUser: 1000, runAsGroup: 1000 },
          env: proxyEnv(),
          volumeMounts: [{ name: "service-work", mountPath: "/workspace/service-work" }, { name: "buildkit-bin", mountPath: "/workspace/buildkit-bin" }, { name: "buildkit-run", mountPath: "/workspace/buildkit-run" }],
          script: perServicePublishScript()
        }
      ]
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "lane", value: "$(params.lane)" },
      { name: "catalog-path", value: "$(params.catalog-path)" },
      { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
      { name: "registry-prefix", value: "$(params.registry-prefix)" },
      { name: "service-id", value: serviceId },
      { name: "base-image", value: "$(params.base-image)" }
    ]
  };
}

function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
  return {
    name: "collect-artifacts",
    runAfter: serviceIds.map(buildTaskName),
    workspaces: [{ name: "source", workspace: "source" }],
    taskSpec: {
      params: [
        { name: "revision" },
        { name: "lane" },
        { name: "catalog-path" },
        { name: "image-tag-mode" },
        { name: "registry-prefix" },
        { name: "services" },
        { name: "base-image" }
      ],
      workspaces: [{ name: "source" }],
      steps: [{ name: "collect", image: ciToolsRunnerImage, env: proxyEnv(), script: collectArtifactsScript() }]
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "lane", value: "$(params.lane)" },
      { name: "catalog-path", value: "$(params.catalog-path)" },
      { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
      { name: "registry-prefix", value: "$(params.registry-prefix)" },
      { name: "services", value: "$(params.services)" },
      { name: "base-image", value: "$(params.base-image)" }
    ]
  };
}

function runtimeReadyScript() {
  return `#!/bin/sh
set -eu
${ciTimingShellFunction()}
export HWLAB_TEKTON_PIPELINERUN="$(context.pipelineRun.name)"
export HWLAB_TEKTON_TASKRUN="$(context.taskRun.name)"
export HWLAB_TEKTON_TASK="runtime-ready"
export HWLAB_SOURCE_REVISION="$(params.revision)"
node <<'NODE'
const fs = require("node:fs");
const https = require("node:https");

const host = process.env.KUBERNETES_SERVICE_HOST;
const port = process.env.KUBERNETES_SERVICE_PORT || "443";
function requiredEnv(name) {
  const value = process.env[name];
  if (!value) throw new Error(name + " is required");
  return value;
}

const revision = requiredEnv("HWLAB_SOURCE_REVISION");
const runtimeNamespace = requiredEnv("HWLAB_RUNTIME_NAMESPACE");
const gitopsTarget = requiredEnv("HWLAB_GITOPS_TARGET");
const argoApplication = requiredEnv("HWLAB_ARGO_APPLICATION");
const pipelineRun = process.env.HWLAB_TEKTON_PIPELINERUN || null;
const taskRun = process.env.HWLAB_TEKTON_TASKRUN || null;
const task = process.env.HWLAB_TEKTON_TASK || null;
const timeoutMs = 240000;
const pollMs = 1000;
const progressEveryMs = 10000;

function emit(payload) {
  console.log(JSON.stringify({
    event: "node-cicd-timing",
    schemaVersion: "v1",
    pipelineRun,
    taskRun,
    task,
    revision,
    source: "scripts/gitops-render.mjs",
    at: new Date().toISOString(),
    ...payload
  }));
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function safeJson(text) {
  try {
    return JSON.parse(text);
  } catch {
    return null;
  }
}

if (!host) {
  emit({ stage: "argo-refresh", status: "failed", reason: "kubernetes-service-host-missing", durationMs: 0 });
  process.exit(1);
}

const token = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/token", "utf8");
const ca = fs.readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");

function request(method, path, body, contentType = "application/json") {
  const payload = body ? JSON.stringify(body) : "";
  const headers = { Authorization: "Bearer " + token };
  if (payload) {
    headers["Content-Type"] = contentType;
    headers["Content-Length"] = Buffer.byteLength(payload);
  }
  return new Promise((resolve, reject) => {
    const req = https.request({ host, port, method, path, ca, headers }, (res) => {
      let data = "";
      res.setEncoding("utf8");
      res.on("data", (chunk) => { data += chunk; });
      res.on("end", () => resolve({ statusCode: res.statusCode || 0, body: data, json: safeJson(data) }));
    });
    req.on("error", reject);
    if (payload) req.write(payload);
    req.end();
  });
}

function listPath(group, version, namespace, resource) {
  if (group) return "/apis/" + group + "/" + version + "/namespaces/" + encodeURIComponent(namespace) + "/" + resource;
  return "/api/" + version + "/namespaces/" + encodeURIComponent(namespace) + "/" + resource;
}

async function runtimeItems() {
  const [deployments, statefulsets] = await Promise.all([
    request("GET", listPath("apps", "v1", runtimeNamespace, "deployments")),
    request("GET", listPath("apps", "v1", runtimeNamespace, "statefulsets"))
  ]);
  if (deployments.statusCode === 403 || statefulsets.statusCode === 403) return { status: "rbac-denied", items: [] };
  const items = [...(deployments.json?.items || []), ...(statefulsets.json?.items || [])]
    .filter((item) => item.metadata?.labels?.["hwlab.pikastech.local/gitops-target"] === gitopsTarget);
  return { status: "ok", items };
}

function runtimeSourceCommit(item) {
  return item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/gitops-render-source-commit"] ||
    item.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/gitops-render-source-commit"] ||
    item.metadata?.labels?.["hwlab.pikastech.local/gitops-render-source-commit"] ||
    item.metadata?.annotations?.["hwlab.pikastech.local/gitops-render-source-commit"] ||
    item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
    item.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/source-commit"] ||
    item.metadata?.labels?.["hwlab.pikastech.local/source-commit"] ||
    item.metadata?.annotations?.["hwlab.pikastech.local/source-commit"] ||
    null;
}

function serviceIdForRuntimeItem(item) {
  return item.metadata?.labels?.["hwlab.pikastech.local/service-id"] ||
    item.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/service-id"] ||
    item.metadata?.labels?.["app.kubernetes.io/name"] ||
    item.metadata?.name ||
    null;
}

function readObservedServiceIds() {
  try {
    const plan = JSON.parse(fs.readFileSync("/workspace/source/affected-services.json", "utf8"));
    const rolloutServices = Array.isArray(plan.rolloutServices) ? plan.rolloutServices.filter(Boolean) : [];
    if (rolloutServices.length === 0) return null;
    return new Set(rolloutServices);
  } catch {
    return null;
  }
}

const observedServiceIds = readObservedServiceIds();
const readinessMode = observedServiceIds ? "service-rollout" : "infra-runtime-change";

function observedRuntimeItems(items) {
  if (!observedServiceIds) return items;
  return items.filter((item) => observedServiceIds.has(serviceIdForRuntimeItem(item)));
}

function readyWorkload(item) {
  const specReplicas = item.spec?.replicas ?? 1;
  if (specReplicas === 0) return { ready: true, skipped: true };
  const status = item.status || {};
  const desired = specReplicas;
  const ready = status.readyReplicas ?? 0;
  const updated = status.updatedReplicas ?? 0;
  const observedGeneration = status.observedGeneration ?? 0;
  const generation = item.metadata?.generation ?? 0;
  return { ready: observedGeneration >= generation && ready >= desired && updated >= desired, desired, readyReplicas: ready, updatedReplicas: updated };
}

function maybeEmitProgress(state, stage, startedAt, payload) {
  const now = Date.now();
  if (now - state.lastProgressAt < progressEveryMs) return;
  state.lastProgressAt = now;
  emit({ stage, status: "progress", durationMs: now - startedAt, readinessMode, ...payload });
}

async function argoApplicationState() {
  const path = "/apis/argoproj.io/v1alpha1/namespaces/argocd/applications/" + encodeURIComponent(argoApplication);
  const response = await request("GET", path);
  if (response.statusCode === 403) return { status: "rbac-denied", item: null, statusCode: response.statusCode };
  if (response.statusCode < 200 || response.statusCode > 299) return { status: "error", item: null, statusCode: response.statusCode, body: response.body.slice(0, 500) };
  return { status: "ok", item: response.json, statusCode: response.statusCode };
}

async function waitForArgoSyncedHealthy() {
  const startedAt = Date.now();
  const progressState = { lastProgressAt: 0 };
  for (;;) {
    const application = await argoApplicationState();
    if (application.status === "rbac-denied") {
      emit({ stage: "argo-sync-health", status: "failed", reason: "argocd-application-rbac-denied", durationMs: Date.now() - startedAt, readinessMode });
      process.exitCode = 1;
      return { observed: false };
    }
    if (application.status !== "ok") {
      emit({ stage: "argo-sync-health", status: "failed", reason: "argocd-application-read-failed", statusCode: application.statusCode, body: application.body || null, durationMs: Date.now() - startedAt, readinessMode });
      process.exitCode = 1;
      return { observed: false };
    }
    const syncStatus = application.item?.status?.sync?.status || null;
    const healthStatus = application.item?.status?.health?.status || null;
    const operationPhase = application.item?.status?.operationState?.phase || null;
    const operationMessage = application.item?.status?.operationState?.message || null;
    if (syncStatus === "Synced" && healthStatus === "Healthy") {
      emit({ stage: "argo-sync-health", status: "succeeded", durationMs: Date.now() - startedAt, readinessMode, syncStatus, healthStatus, operationPhase });
      return { observed: true };
    }
    if (Date.now() - startedAt >= timeoutMs) {
      emit({ stage: "argo-sync-health", status: "timeout", durationMs: Date.now() - startedAt, readinessMode, syncStatus, healthStatus, operationPhase, operationMessage });
      process.exitCode = 1;
      return { observed: false };
    }
    maybeEmitProgress(progressState, "argo-sync-health", startedAt, { syncStatus, healthStatus, operationPhase, operationMessage });
    await sleep(pollMs);
  }
}

async function waitForArgoRefresh() {
  const startedAt = Date.now();
  const progressState = { lastProgressAt: 0 };
  for (;;) {
    const runtime = await runtimeItems();
    if (runtime.status === "rbac-denied") {
      emit({ stage: "argo-refresh", status: "failed", reason: "runtime-observer-rbac-denied", durationMs: Date.now() - startedAt });
      process.exitCode = 1;
      return { observed: false, skipped: true };
    }
    const observed = observedRuntimeItems(runtime.items);
    const pending = observed
      .map((item) => ({ kind: item.kind, name: item.metadata?.name, sourceCommit: runtimeSourceCommit(item) }))
      .filter((item) => item.sourceCommit !== revision);
    if (observed.length > 0 && pending.length === 0) {
      emit({ stage: "argo-refresh", status: "succeeded", durationMs: Date.now() - startedAt, workloadCount: runtime.items.length, observedCount: observed.length });
      return { observed: true, skipped: false };
    }
    if (Date.now() - startedAt >= timeoutMs) {
      emit({ stage: "argo-refresh", status: "timeout", reason: "source-commit-refresh-timeout", durationMs: Date.now() - startedAt, workloadCount: runtime.items.length, observedCount: observed.length, pending: pending.slice(0, 8) });
      process.exitCode = 1;
      return { observed: false, skipped: false };
    }
    maybeEmitProgress(progressState, "argo-refresh", startedAt, { workloadCount: runtime.items.length, observedCount: observed.length, pending: pending.slice(0, 8) });
    await sleep(pollMs);
  }
}

async function waitForWorkloads() {
  const startedAt = Date.now();
  const progressState = { lastProgressAt: 0 };
  for (;;) {
    const runtime = await runtimeItems();
    if (runtime.status === "rbac-denied") {
      emit({ stage: "workload-ready", status: "failed", reason: "runtime-observer-rbac-denied", durationMs: Date.now() - startedAt });
      process.exitCode = 1;
      return;
    }
    const observed = observedRuntimeItems(runtime.items);
    const blocked = observed.map((item) => ({ kind: item.kind, name: item.metadata?.name, ...readyWorkload(item) })).filter((item) => !item.ready);
    if (observed.length > 0 && blocked.length === 0) {
      emit({ stage: "workload-ready", status: "succeeded", durationMs: Date.now() - startedAt, workloadCount: runtime.items.length, observedCount: observed.length });
      return;
    }
    if (Date.now() - startedAt >= timeoutMs) {
      emit({ stage: "workload-ready", status: "timeout", durationMs: Date.now() - startedAt, workloadCount: runtime.items.length, observedCount: observed.length, blocked: blocked.slice(0, 8) });
      process.exitCode = 1;
      return;
    }
    maybeEmitProgress(progressState, "workload-ready", startedAt, { workloadCount: runtime.items.length, observedCount: observed.length, blocked: blocked.slice(0, 8) });
    await sleep(pollMs);
  }
}

(async () => {
  emit({ stage: "runtime-ready", status: "started", readinessMode, observedServiceCount: observedServiceIds ? observedServiceIds.size : 0 });
  if (!observedServiceIds) {
    const argo = await waitForArgoSyncedHealthy();
    if (!argo.observed) return;
    await waitForWorkloads();
    return;
  }
  const refresh = await waitForArgoRefresh();
  if (!refresh.observed) return;
  await waitForWorkloads();
})().catch((error) => {
  emit({ stage: "runtime-ready", status: "failed", reason: error.message, durationMs: 0 });
  process.exitCode = 1;
});
NODE
`;
}

function runtimeReadyTask({ profile = "dev" } = {}) {
  return {
    name: "runtime-ready",
    runAfter: ["gitops-promote"],
    workspaces: [{ name: "source", workspace: "source" }],
    taskSpec: {
      params: [{ name: "revision" }, { name: "runtime-namespace" }, { name: "gitops-target" }, { name: "argo-application" }],
      workspaces: [{ name: "source" }],
      steps: [{
        name: "runtime-ready",
        image: ciToolsRunnerImage,
        env: [
          ...proxyEnv(),
          { name: "HWLAB_RUNTIME_NAMESPACE", value: "$(params.runtime-namespace)" },
          { name: "HWLAB_GITOPS_TARGET", value: "$(params.gitops-target)" },
          { name: "HWLAB_ARGO_APPLICATION", value: "$(params.argo-application)" }
        ],
        script: runtimeReadyScript()
      }]
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "runtime-namespace", value: namespaceNameForProfile(profile) },
      { name: "gitops-target", value: gitopsTargetForProfile(profile) },
      { name: "argo-application", value: argoApplicationName(profile) }
    ]
  };
}

function imagePublishTaskSet(args = { lane: "node" }, deploy = null) {
  const serviceIds = serviceIdsForLane(args.lane, deploy);
  const buildTasks = serviceIds.map((serviceId) => perServiceBuildTask(serviceId, {
    runAfter: ["plan-artifacts"]
  }));
  return [
    planArtifactsTask({ serviceIds }),
    ...buildTasks,
    collectArtifactsTask({ serviceIds })
  ];
}

function tektonPipeline(args = { lane: "node" }, deploy = null) {
  const settings = ciLaneSettings(args);
  const runtimePath = gitopsPathForProfile(args, settings.profile);
  return {
    apiVersion: "tekton.dev/v1",
    kind: "Pipeline",
    metadata: {
      name: settings.pipelineName,
      namespace: "hwlab-ci",
      labels: {
        "app.kubernetes.io/part-of": "hwlab",
        "hwlab.pikastech.local/gitops-target": settings.gitopsTarget
      },
      annotations: {
        "hwlab.pikastech.local/source-config": "scripts/gitops-render.mjs#tekton-native-primitive-ci",
        "hwlab.pikastech.local/ci-contract": "tekton-native-primitive-tasks",
        "hwlab.pikastech.local/policy": "native-per-service-taskrun-image-publish"
      }
    },
    spec: {
      params: [
        { name: "git-url", type: "string", default: defaultSourceRepo },
        { name: "git-read-url", type: "string", default: args.gitReadUrl },
        { name: "git-write-url", type: "string", default: args.gitWriteUrl },
        { name: "source-branch", type: "string", default: args.sourceBranch },
        { name: "gitops-branch", type: "string", default: args.gitopsBranch },
        { name: "lane", type: "string", default: settings.lane },
        { name: "catalog-path", type: "string", default: args.catalogPath || settings.catalogPath },
        { name: "image-tag-mode", type: "string", default: args.imageTagMode || settings.imageTagMode },
        { name: "runtime-path", type: "string", default: runtimePath },
        { name: "revision", type: "string", description: "Full git commit SHA; the only source truth for image tags." },
        { name: "registry-prefix", type: "string", default: defaultRegistryPrefix },
        { name: "services", type: "string", default: servicesParamForLane(args.lane, deploy) },
        { name: "base-image", type: "string", default: defaultDevBaseImage }
      ],
      workspaces: [
        { name: "source" },
        { name: "git-ssh" }
      ],
      tasks: [
        {
          name: "prepare-source",
          workspaces: [
            { name: "source", workspace: "source" },
            { name: "git-ssh", workspace: "git-ssh" }
          ],
          taskSpec: {
            params: [
              { name: "git-url" },
              { name: "git-read-url" },
              { name: "source-branch" },
              { name: "gitops-branch" },
              { name: "lane" },
              { name: "catalog-path" },
              { name: "image-tag-mode" },
              { name: "registry-prefix" },
              { name: "services" },
              { name: "revision" }
            ],
            workspaces: [{ name: "source" }, { name: "git-ssh" }],
            steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }]
          },
          params: [
            { name: "git-url", value: "$(params.git-url)" },
            { name: "git-read-url", value: "$(params.git-read-url)" },
            { name: "source-branch", value: "$(params.source-branch)" },
            { name: "gitops-branch", value: "$(params.gitops-branch)" },
            { name: "lane", value: "$(params.lane)" },
            { name: "catalog-path", value: "$(params.catalog-path)" },
            { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
            { name: "registry-prefix", value: "$(params.registry-prefix)" },
            { name: "services", value: "$(params.services)" },
            { name: "revision", value: "$(params.revision)" }
          ]
        },
        ...primitiveValidationTasks.map(primitiveValidationTask),
        ...imagePublishTaskSet(args, deploy),
        {
          name: "gitops-promote",
          runAfter: ["collect-artifacts"],
          workspaces: [
            { name: "source", workspace: "source" },
            { name: "git-ssh", workspace: "git-ssh" }
          ],
          taskSpec: {
            params: [
              { name: "git-url" },
              { name: "git-read-url" },
              { name: "git-write-url" },
              { name: "source-branch" },
              { name: "gitops-branch" },
              { name: "lane" },
              { name: "catalog-path" },
              { name: "image-tag-mode" },
              { name: "runtime-path" },
              { name: "revision" },
              { name: "registry-prefix" }
            ],
            results: [{ name: "runtime-ready-required", description: "true when GitOps promotion changed runtime desired state and runtime readiness must be observed" }],
            workspaces: [{ name: "source" }, { name: "git-ssh" }],
            steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }]
          },
          params: [
            { name: "git-url", value: "$(params.git-url)" },
            { name: "git-read-url", value: "$(params.git-read-url)" },
            { name: "git-write-url", value: "$(params.git-write-url)" },
            { name: "source-branch", value: "$(params.source-branch)" },
            { name: "gitops-branch", value: "$(params.gitops-branch)" },
            { name: "lane", value: "$(params.lane)" },
            { name: "catalog-path", value: "$(params.catalog-path)" },
            { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
            { name: "runtime-path", value: "$(params.runtime-path)" },
            { name: "revision", value: "$(params.revision)" },
            { name: "registry-prefix", value: "$(params.registry-prefix)" }
          ]
        },
        {
          ...runtimeReadyTask({ profile: settings.profile }),
          when: [{ input: "$(tasks.gitops-promote.results.runtime-ready-required)", operator: "in", values: ["true"] }]
        }
      ]
    }
  };
}

function tektonPipelineRunTemplate({ source, args }) {
  const settings = ciLaneSettings(args);
  const runtimePath = gitopsPathForProfile(args, settings.profile);
  return {
    apiVersion: "tekton.dev/v1",
    kind: "PipelineRun",
    metadata: {
      generateName: `${settings.pipelineRunPrefix}-manual-`,
      namespace: "hwlab-ci",
      labels: {
        "app.kubernetes.io/part-of": "hwlab",
        "hwlab.pikastech.local/gitops-target": settings.gitopsTarget,
        "hwlab.pikastech.local/source-commit": source.full
      }
    },
    spec: {
      pipelineRef: { name: settings.pipelineName },
      taskRunTemplate: {
        serviceAccountName: settings.serviceAccountName,
        podTemplate: {
          hostNetwork: true,
          dnsPolicy: "ClusterFirstWithHostNet",
          securityContext: { fsGroup: 1000 }
        }
      },
      params: [
        { name: "git-url", value: args.sourceRepo },
        { name: "git-read-url", value: args.gitReadUrl },
        { name: "git-write-url", value: args.gitWriteUrl },
        { name: "source-branch", value: args.sourceBranch },
        { name: "gitops-branch", value: args.gitopsBranch },
        { name: "lane", value: settings.lane },
        { name: "catalog-path", value: args.catalogPath || settings.catalogPath },
        { name: "image-tag-mode", value: args.imageTagMode || settings.imageTagMode },
        { name: "runtime-path", value: runtimePath },
        { name: "revision", value: source.full },
        { name: "registry-prefix", value: args.registryPrefix },
        { name: "base-image", value: defaultDevBaseImage }
      ],
      workspaces: [
        { name: "source", volumeClaimTemplate: { spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: "8Gi" } } } } },
        { name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }
      ]
    }
  };
}

function tektonPollerCronJob(args, deploy) {
  const settings = ciLaneSettings(args);
  if (settings.lane === "v02") throw new Error("v02 CI/CD is manually triggered by UniDesk CLI and must not render a branch poller CronJob");
  return {
    apiVersion: "batch/v1",
    kind: "CronJob",
    metadata: {
      name: settings.pollerName,
      namespace: "hwlab-ci",
      labels: {
        "app.kubernetes.io/part-of": "hwlab",
        "hwlab.pikastech.local/gitops-target": settings.gitopsTarget
      },
      annotations: {
        "hwlab.pikastech.local/source-branch": args.sourceBranch,
        "hwlab.pikastech.local/gitops-branch": args.gitopsBranch
      }
    },
    spec: {
      schedule: settings.lane === "v02" ? "*/10 * * * *" : "* * * * *",
      concurrencyPolicy: "Forbid",
      successfulJobsHistoryLimit: 3,
      failedJobsHistoryLimit: 3,
      jobTemplate: {
        spec: {
          backoffLimit: 1,
          template: {
            metadata: {
              labels: {
                "app.kubernetes.io/part-of": "hwlab",
                "hwlab.pikastech.local/gitops-target": settings.gitopsTarget
              }
            },
            spec: {
              serviceAccountName: settings.serviceAccountName,
              restartPolicy: "Never",
              hostNetwork: true,
              dnsPolicy: "ClusterFirstWithHostNet",
              containers: [{
                name: "poll",
                image: ciToolsRunnerImage,
                imagePullPolicy: "IfNotPresent",
                env: [
                  ...proxyEnv(),
                  { name: "POD_NAMESPACE", valueFrom: { fieldRef: { fieldPath: "metadata.namespace" } } },
                  { name: "PIPELINE_NAME", value: settings.pipelineName },
                  { name: "PIPELINERUN_PREFIX", value: settings.pipelineRunPrefix },
                  { name: "SERVICE_ACCOUNT_NAME", value: settings.serviceAccountName },
                  { name: "GITOPS_TARGET", value: settings.gitopsTarget },
                  { name: "LANE", value: settings.lane },
                  { name: "CATALOG_PATH", value: args.catalogPath || settings.catalogPath },
                  { name: "IMAGE_TAG_MODE", value: args.imageTagMode || settings.imageTagMode },
                  { name: "RUNTIME_PATH", value: gitopsPathForProfile(args, settings.profile) },
                  { name: "GIT_URL", value: args.sourceRepo },
                  { name: "GIT_READ_URL", value: args.gitReadUrl },
                  { name: "SOURCE_BRANCH", value: args.sourceBranch },
                  { name: "GITOPS_BRANCH", value: args.gitopsBranch },
                  { name: "REGISTRY_PREFIX", value: args.registryPrefix },
                  { name: "SERVICES", value: servicesParamForLane(args.lane, deploy) },
                  { name: "BASE_IMAGE", value: defaultDevBaseImage }
                ],
                volumeMounts: [{ name: "git-ssh", mountPath: "/workspace/git-ssh", readOnly: true }],
                command: ["/bin/sh", "-c"],
                args: [pollerScript()]
              }],
              volumes: [{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }]
            }
          }
        }
      }
    }
  };
}

function tektonControlPlaneReconcilerCronJob(args) {
  const settings = ciLaneSettings(args);
  if (settings.lane === "v02") throw new Error("v02 CI/CD is manually triggered by UniDesk CLI and must not render a control-plane reconciler CronJob");
  return {
    apiVersion: "batch/v1",
    kind: "CronJob",
    metadata: {
      name: settings.controlPlaneReconcilerName,
      namespace: "hwlab-ci",
      labels: {
        "app.kubernetes.io/part-of": "hwlab",
        "hwlab.pikastech.local/gitops-target": settings.gitopsTarget
      },
      annotations: {
        "hwlab.pikastech.local/source-branch": args.sourceBranch,
        "hwlab.pikastech.local/gitops-branch": args.gitopsBranch,
        "hwlab.pikastech.local/purpose": "render-and-apply-node-ci-control-plane"
      }
    },
    spec: {
      schedule: "*/10 * * * *",
      concurrencyPolicy: "Forbid",
      successfulJobsHistoryLimit: 3,
      failedJobsHistoryLimit: 3,
      jobTemplate: {
        spec: {
          backoffLimit: 1,
          template: {
            metadata: {
              labels: {
                "app.kubernetes.io/part-of": "hwlab",
                "hwlab.pikastech.local/gitops-target": settings.gitopsTarget
              }
            },
            spec: {
              serviceAccountName: settings.serviceAccountName,
              restartPolicy: "Never",
              hostNetwork: true,
              dnsPolicy: "ClusterFirstWithHostNet",
              containers: [{
                name: "reconcile",
                image: ciToolsRunnerImage,
                imagePullPolicy: "IfNotPresent",
                env: [
                  ...proxyEnv(),
                  { name: "POD_NAMESPACE", valueFrom: { fieldRef: { fieldPath: "metadata.namespace" } } },
                  { name: "LANE", value: settings.lane },
                  { name: "CATALOG_PATH", value: args.catalogPath || settings.catalogPath },
                  { name: "IMAGE_TAG_MODE", value: args.imageTagMode || settings.imageTagMode },
                  { name: "TEKTON_DIR", value: settings.tektonDir },
                  { name: "ARGO_FILES", value: settings.lane === "v02" ? `${gitopsPathFor(args, "argocd/project.yaml")},${gitopsPathFor(args, "argocd/application-v02.yaml")}` : "" },
                  { name: "FIELD_MANAGER", value: settings.controlPlaneReconcilerName },
                  { name: "RECONCILE_EVENT", value: `${settings.gitopsTarget}-control-plane-reconciled` },
                  { name: "GIT_URL", value: args.sourceRepo },
                  { name: "GIT_READ_URL", value: args.gitReadUrl },
                  { name: "SOURCE_BRANCH", value: args.sourceBranch },
                  { name: "GITOPS_BRANCH", value: args.gitopsBranch },
                  { name: "REGISTRY_PREFIX", value: args.registryPrefix }
                ],
                volumeMounts: [{ name: "git-ssh", mountPath: "/workspace/git-ssh", readOnly: true }],
                command: ["/bin/sh", "-c"],
                args: [controlPlaneReconcileScript()]
              }],
              volumes: [{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }]
            }
          }
        }
      }
    }
  };
}

function registryManifest() {
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      { apiVersion: "v1", kind: "Namespace", metadata: { name: "hwlab-ci" } },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name: "hwlab-registry", namespace: "hwlab-ci", labels: { "app.kubernetes.io/name": "hwlab-registry" } },
        spec: {
          replicas: 1,
          selector: { matchLabels: { "app.kubernetes.io/name": "hwlab-registry" } },
          template: {
            metadata: { labels: { "app.kubernetes.io/name": "hwlab-registry" } },
            spec: {
              hostNetwork: true,
              dnsPolicy: "ClusterFirstWithHostNet",
              containers: [{
                name: "registry",
                image: "registry:2.8.3",
                imagePullPolicy: "IfNotPresent",
                ports: [{ name: "registry", containerPort: 5000, hostPort: 5000 }],
                env: [{ name: "REGISTRY_STORAGE_DELETE_ENABLED", value: "true" }],
                volumeMounts: [{ name: "storage", mountPath: "/var/lib/registry" }],
                readinessProbe: { httpGet: { path: "/v2/", port: "registry" } },
                livenessProbe: { httpGet: { path: "/v2/", port: "registry" } }
              }],
              volumes: [{ name: "storage", hostPath: { path: "/var/lib/hwlab/registry", type: "DirectoryOrCreate" } }]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name: "hwlab-registry", namespace: "hwlab-ci", labels: { "app.kubernetes.io/name": "hwlab-registry" } },
        spec: { selector: { "app.kubernetes.io/name": "hwlab-registry" }, ports: [{ name: "registry", port: 5000, targetPort: "registry" }] }
      }
    ]
  };
}

function uniqueStrings(values) {
  return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
}

function configObject(value, label) {
  assert.ok(value && typeof value === "object" && !Array.isArray(value), `${label} must be an object`);
  return value;
}

function requiredConfigString(record, key, label) {
  const value = record[key];
  assert.ok(typeof value === "string" && value.length > 0, `${label}.${key} must be a non-empty string`);
  return value;
}

function optionalConfigString(record, key, label) {
  const value = record[key];
  if (value === undefined || value === null || value === "") return null;
  assert.ok(typeof value === "string", `${label}.${key} must be a string when set`);
  return value;
}

function requiredConfigPositiveInteger(record, key, label) {
  const value = record[key];
  assert.ok(Number.isInteger(value) && value > 0, `${label}.${key} must be a positive integer`);
  return value;
}

function devopsInfraGitMirrorManifest(args, deploy) {
  const mirrorSpecs = runtimeLaneMirrorSpecs(deploy, { defaultNodeId: args.nodeId, defaultGitopsRoot: defaultOutDir });
  assert.ok(mirrorSpecs.length > 0, "runtime lane git mirror requires at least one deploy.lanes entry");
  const sourceBranches = uniqueStrings(mirrorSpecs.map((spec) => spec.sourceBranch));
  const gitopsBranches = uniqueStrings(mirrorSpecs.map((spec) => spec.gitopsBranch));
  const mirrorBranches = uniqueStrings([...sourceBranches, ...gitopsBranches]);
  const fetchConfigCommands = mirrorBranches
    .map((branch) => `git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/${branch}:refs/mirror-stage/heads/${branch}'`)
    .join("\n");
  const requiredRefArgs = mirrorBranches.map((branch) => shellSingleQuote(`refs/mirror-stage/heads/${branch}`)).join(" ");
  const sourceBranchArgs = sourceBranches.map((branch) => shellSingleQuote(branch)).join(" ");
  const gitopsBranchArgs = gitopsBranches.map((branch) => shellSingleQuote(branch)).join(" ");
  const mirrorBranchesJson = JSON.stringify(mirrorBranches);
  const sourceBranchesJson = JSON.stringify(sourceBranches);
  const gitopsBranchesJson = JSON.stringify(gitopsBranches);
  const laneConfig = configObject(configObject(deploy.lanes, "deploy.lanes")[args.lane], `deploy.lanes.${args.lane}`);
  const gitMirrorConfig = configObject(laneConfig.gitMirror, `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorProxy = configObject(gitMirrorConfig.egressProxy, `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
  assert.equal(gitMirrorProxy.mode, "node-global", `deploy.lanes.${args.lane}.gitMirror.egressProxy.mode must be node-global`);
  const gitMirrorNamespace = requiredConfigString(gitMirrorConfig, "namespace", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorReadName = requiredConfigString(gitMirrorConfig, "serviceReadName", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorWriteName = requiredConfigString(gitMirrorConfig, "serviceWriteName", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorCachePvcName = requiredConfigString(gitMirrorConfig, "cachePvcName", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorCachePvcStorage = requiredConfigString(gitMirrorConfig, "cachePvcStorage", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorCacheHostPath = optionalConfigString(gitMirrorConfig, "cacheHostPath", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorServicePort = requiredConfigPositiveInteger(gitMirrorConfig, "servicePort", `deploy.lanes.${args.lane}.gitMirror`);
  const gitMirrorConfigMapName = requiredConfigString(gitMirrorConfig, "syncConfigMapName", `deploy.lanes.${args.lane}.gitMirror`);
  const proxyNamespace = requiredConfigString(gitMirrorProxy, "namespace", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
  const proxyServiceName = requiredConfigString(gitMirrorProxy, "serviceName", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
  const proxyPort = requiredConfigPositiveInteger(gitMirrorProxy, "port", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
  const proxyClientName = requiredConfigString(gitMirrorProxy, "clientName", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
  const proxyNoProxy = Array.isArray(gitMirrorProxy.noProxy) ? gitMirrorProxy.noProxy.filter((value) => typeof value === "string" && value.length > 0).join(",") : "";
  const proxyHost = `${proxyServiceName}.${proxyNamespace}.svc.cluster.local`;
  const proxyUrl = `http://${proxyHost}:${proxyPort}`;
  const proxySummary = `git-mirror-egress-proxy client=${proxyClientName} mode=node-global required=true host=${proxyHost} port=${proxyPort} ssh=GIT_SSH-wrapper source=yaml`;
  const proxyCommand = `ProxyCommand=node /tmp/hwlab-github-proxy-connect.mjs ${proxyHost} ${proxyPort} %h %p`;
  const gitMirrorSshPrelude = `printf '%s\\n' ${shellSingleQuote(proxySummary)} >&2
cat > /tmp/hwlab-github-proxy-connect.mjs <<'NODE_PROXY'
#!/usr/bin/env node
import net from "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("hwlab git-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("hwlab git-mirror proxy-connect: " + message);
  process.exit(code);
}
const socket = net.createConnection({ host: proxyHost, port: proxyPort });
let buffer = Buffer.alloc(0);
socket.setTimeout(15000, () => { 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/hwlab-github-proxy-connect.mjs
cat > /tmp/hwlab-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=15 -o ServerAliveInterval=5 -o ServerAliveCountMax=1 -o ${shellSingleQuote(proxyCommand)} "$@"
SH_PROXY
chmod 0700 /tmp/hwlab-git-ssh-proxy.sh
export HTTP_PROXY=${shellSingleQuote(proxyUrl)}
export HTTPS_PROXY=${shellSingleQuote(proxyUrl)}
export ALL_PROXY=${shellSingleQuote(proxyUrl)}
export http_proxy=${shellSingleQuote(proxyUrl)}
export https_proxy=${shellSingleQuote(proxyUrl)}
export all_proxy=${shellSingleQuote(proxyUrl)}
export NO_PROXY=${shellSingleQuote(proxyNoProxy)}
export no_proxy=${shellSingleQuote(proxyNoProxy)}
export GIT_SSH=/tmp/hwlab-git-ssh-proxy.sh
unset GIT_SSH_COMMAND`;
  const cacheVolume = gitMirrorCacheHostPath === null
    ? { name: "cache", persistentVolumeClaim: { claimName: gitMirrorCachePvcName } }
    : { name: "cache", hostPath: { path: gitMirrorCacheHostPath, type: "DirectoryOrCreate" } };
  const labels = {
    "app.kubernetes.io/part-of": "hwlab-node-control-plane",
    "hwlab.pikastech.local/node": args.nodeId,
    "hwlab.pikastech.local/lane": args.lane
  };
  const configLabels = { ...labels, "app.kubernetes.io/name": "git-mirror" };
  const readLabels = { ...labels, "app.kubernetes.io/name": gitMirrorReadName, "hwlab.pikastech.local/git-mirror-mode": "read" };
  const writeLabels = { ...labels, "app.kubernetes.io/name": gitMirrorWriteName, "hwlab.pikastech.local/git-mirror-mode": "write" };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      { apiVersion: "v1", kind: "Namespace", metadata: { name: gitMirrorNamespace } },
      ...(gitMirrorCacheHostPath === null ? [{
        apiVersion: "v1",
        kind: "PersistentVolumeClaim",
        metadata: { name: gitMirrorCachePvcName, namespace: gitMirrorNamespace, labels: configLabels },
        spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: gitMirrorCachePvcStorage } } }
      }] : []),
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: gitMirrorConfigMapName, namespace: gitMirrorNamespace, labels: configLabels },
        data: {
          "sync.sh": `#!/bin/sh
set -eu
repo_url="ssh://git@ssh.github.com:443/pikasTech/HWLAB.git"
repo_path="/cache/pikasTech/HWLAB.git"
lock_dir="/cache/.hwlab-sync.lock"
sync_started_ms=$(node -e 'console.log(Date.now())')
now_ms() { node -e 'console.log(Date.now())'; }
emit_timing() {
  phase="$1"
  status="$2"
  started_ms="$3"
  finished_ms=$(now_ms)
  duration_ms=$((finished_ms - started_ms))
  printf '{"event":"git-mirror-sync-timing","phase":"%s","status":"%s","durationMs":%s,"repository":"pikasTech/HWLAB"}\n' "$phase" "$status" "$duration_ms"
}
mkdir -p /cache/pikasTech /root/.ssh
if ! mkdir "$lock_dir" 2>/dev/null; then
  echo "git mirror sync already running"
  exit 0
fi
trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT INT TERM
cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa
chmod 0400 /root/.ssh/id_rsa
${gitMirrorSshPrelude}
if [ -d "$repo_path/objects" ] && [ -f "$repo_path/HEAD" ]; then
  git -C "$repo_path" remote set-url origin "$repo_url" || git -C "$repo_path" remote add origin "$repo_url"
else
  rm -rf "$repo_path"
  git init --bare "$repo_path"
  git -C "$repo_path" remote add origin "$repo_url"
fi
/script/install-hooks.sh
git -C "$repo_path" config uploadpack.hideRefs refs/mirror-stage
git -C "$repo_path" config uploadpack.allowReachableSHA1InWant true
git -C "$repo_path" config uploadpack.allowAnySHA1InWant true
git -C "$repo_path" config --unset-all remote.origin.fetch 2>/dev/null || true
${fetchConfigCommands}
fetch_started_ms=$(now_ms)
timeout 180 git -C "$repo_path" fetch --quiet --prune origin
emit_timing fetch succeeded "$fetch_started_ms"
git -C "$repo_path" for-each-ref --format='%(objectname) %(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-heads
git -C "$repo_path" for-each-ref --format='%(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-head-refs
git -C "$repo_path" for-each-ref --format='%(objectname) %(refname)' refs/mirror-stage/tags > /tmp/hwlab-stage-tags
git -C "$repo_path" for-each-ref --format='%(refname)' refs/mirror-stage/tags > /tmp/hwlab-stage-tag-refs
if [ ! -s /tmp/hwlab-stage-heads ]; then
  echo "git mirror sync fetched no branch refs" >&2
  exit 41
fi
for required_ref in ${requiredRefArgs}; do
  git -C "$repo_path" show-ref --verify --quiet "$required_ref" || { echo "git mirror sync missing required ref $required_ref" >&2; exit 43; }
done
validate_started_ms=$(now_ms)
while read -r sha ref; do
  [ -n "$sha" ] || continue
  git -C "$repo_path" cat-file -e "$sha^{commit}"
  git -C "$repo_path" cat-file -e "$sha^{tree}"
  if git -C "$repo_path" rev-list --objects --missing=print "$sha" | grep -q '^?'; then
    echo "git mirror sync found missing objects for $ref $sha" >&2
    exit 42
  fi
done < /tmp/hwlab-stage-heads
emit_timing validate succeeded "$validate_started_ms"
publish_started_ms=$(now_ms)
while read -r sha ref; do
  [ -n "$sha" ] || continue
  name=$(printf '%s\n' "$ref" | sed 's#^refs/mirror-stage/heads/##')
  is_gitops_branch=false
  for gitops_branch in ${gitopsBranchArgs}; do
    if [ "$name" = "$gitops_branch" ]; then is_gitops_branch=true; break; fi
  done
  if [ "$is_gitops_branch" = true ]; then
    local_sha=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$name" 2>/dev/null || true)
    if [ -n "$local_sha" ] && [ "$local_sha" != "$sha" ]; then
      if git -C "$repo_path" merge-base --is-ancestor "$sha" "$local_sha"; then
        echo "git mirror sync keeps local $name ahead of GitHub"
        continue
      fi
      if ! git -C "$repo_path" merge-base --is-ancestor "$local_sha" "$sha"; then
        echo "git mirror sync found divergent $name local=$local_sha github=$sha" >&2
        exit 44
      fi
    fi
  fi
  git -C "$repo_path" update-ref "refs/heads/$name" "$sha"
done < /tmp/hwlab-stage-heads
while read -r sha ref; do
  [ -n "$sha" ] || continue
  name=$(printf '%s\n' "$ref" | sed 's#^refs/mirror-stage/tags/##')
  git -C "$repo_path" update-ref "refs/tags/$name" "$sha"
done < /tmp/hwlab-stage-tags
git -C "$repo_path" for-each-ref --format='%(refname)' refs/heads > /tmp/hwlab-public-heads
while read -r ref; do
  [ -n "$ref" ] || continue
  name=$(printf '%s\n' "$ref" | sed 's#^refs/heads/##')
  if ! grep -Fxq "refs/mirror-stage/heads/$name" /tmp/hwlab-stage-head-refs; then
    git -C "$repo_path" update-ref -d "$ref"
  fi
done < /tmp/hwlab-public-heads
git -C "$repo_path" for-each-ref --format='%(refname)' refs/tags > /tmp/hwlab-public-tags
while read -r ref; do
  [ -n "$ref" ] || continue
  name=$(printf '%s\n' "$ref" | sed 's#^refs/tags/##')
  if ! grep -Fxq "refs/mirror-stage/tags/$name" /tmp/hwlab-stage-tag-refs; then
    git -C "$repo_path" update-ref -d "$ref"
  fi
done < /tmp/hwlab-public-tags
emit_timing publish succeeded "$publish_started_ms"
for head_branch in ${sourceBranchArgs}; do
  if git -C "$repo_path" show-ref --verify --quiet "refs/heads/$head_branch"; then
    git -C "$repo_path" symbolic-ref HEAD "refs/heads/$head_branch"
    break
  fi
done
fsck_started_ms=$(now_ms)
git -C "$repo_path" fsck --connectivity-only --no-dangling >/tmp/hwlab-git-fsck.out
emit_timing fsck succeeded "$fsck_started_ms"
git -C "$repo_path" update-server-info
published_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
for source_branch in ${sourceBranchArgs}; do
  git -C "$repo_path" rev-parse "refs/heads/$source_branch" 2>/dev/null | tee "/cache/HWLAB-$source_branch.head" >/dev/null || true
done
printf '%s\n' "$published_at" > /cache/HWLAB.last-sync
export published_at
export mirror_branches_json=${shellSingleQuote(mirrorBranchesJson)}
export source_branches_json=${shellSingleQuote(sourceBranchesJson)}
export gitops_branches_json=${shellSingleQuote(gitopsBranchesJson)}
node - <<'NODE' | tee /cache/HWLAB.last-sync.json
const { execFileSync } = require("node:child_process");
const repo = "/cache/pikasTech/HWLAB.git";
const mirrorBranches = JSON.parse(process.env.mirror_branches_json || "[]");
const sourceBranches = JSON.parse(process.env.source_branches_json || "[]");
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
function rev(ref) {
  try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
}
const refs = {};
for (const branch of mirrorBranches) {
  refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
  refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
}
const sourceInSync = sourceBranches.every((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] === refs["refs/mirror-stage/heads/" + branch]);
const gitopsInSync = gitopsBranches.every((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] === refs["refs/mirror-stage/heads/" + branch]);
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/mirror-stage/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
const payload = {
  event: "git-mirror-sync",
  status: "published",
  repository: "pikasTech/HWLAB",
  publishedAt: process.env.published_at,
  pendingFlush,
  sourceInSync,
  gitopsInSync,
  refs
};
console.log(JSON.stringify(payload));
NODE
emit_timing total succeeded "$sync_started_ms"
`,
          "install-hooks.sh": `#!/bin/sh
set -eu
repo_path="/cache/pikasTech/HWLAB.git"
mkdir -p "$repo_path/hooks"
cat > "$repo_path/hooks/pre-receive" <<'HOOK'
#!/bin/sh
set -eu
zero="0000000000000000000000000000000000000000"
status=0
while read -r old new ref; do
  if [ "$new" = "$zero" ]; then
    echo "git mirror write rejected: deleting $ref is forbidden" >&2
    status=1
    continue
  fi
  git cat-file -e "$new^{commit}" || status=1
  git cat-file -e "$new^{tree}" || status=1
  if git rev-list --objects --missing=print "$new" | grep -q '^?'; then
    echo "git mirror write rejected: missing objects for $new" >&2
    status=1
    continue
  fi
  if [ "$old" != "$zero" ] && ! git merge-base --is-ancestor "$old" "$new"; then
    echo "git mirror write rejected: non-fast-forward $ref" >&2
    status=1
    continue
  fi
done
exit "$status"
HOOK
cat > "$repo_path/hooks/post-receive" <<'HOOK'
#!/bin/sh
set -eu
repo_path=$(git rev-parse --git-dir)
git -C "$repo_path" update-server-info
written_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
export repo_path written_at
export gitops_branches_json=${shellSingleQuote(gitopsBranchesJson)}
node - <<'NODE' > /cache/HWLAB.last-write.json
const { execFileSync } = require("node:child_process");
const repo = process.env.repo_path || "/cache/pikasTech/HWLAB.git";
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
function rev(ref) {
  try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
}
const refs = {};
for (const branch of gitopsBranches) {
  refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
  refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
}
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
console.log(JSON.stringify({
  event: "git-mirror-write",
  status: "received",
  repository: "pikasTech/HWLAB",
  writtenAt: process.env.written_at,
  pendingFlush,
  refs
}));
NODE
HOOK
chmod 0755 "$repo_path/hooks/pre-receive" "$repo_path/hooks/post-receive"
git -C "$repo_path" config http.receivepack true
git -C "$repo_path" config receive.denyDeletes true
git -C "$repo_path" config receive.denyNonFastForwards true
`,
          "flush.sh": `#!/bin/sh
set -eu
repo_url="ssh://git@ssh.github.com:443/pikasTech/HWLAB.git"
repo_path="/cache/pikasTech/HWLAB.git"
lock_dir="/cache/.hwlab-flush.lock"
started_ms=$(node -e 'console.log(Date.now())')
now_ms() { node -e 'console.log(Date.now())'; }
emit_timing() {
  phase="$1"
  status="$2"
  started="$3"
  finished=$(now_ms)
  duration=$((finished - started))
  printf '{"event":"git-mirror-flush-timing","phase":"%s","status":"%s","durationMs":%s,"repository":"pikasTech/HWLAB"}\n' "$phase" "$status" "$duration"
}
if ! mkdir "$lock_dir" 2>/dev/null; then
  echo "git mirror flush already running"
  exit 0
fi
trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT INT TERM
mkdir -p /root/.ssh
cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa
chmod 0400 /root/.ssh/id_rsa
${gitMirrorSshPrelude}
/script/install-hooks.sh
for gitops_branch in ${gitopsBranchArgs}; do
  local_head=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$gitops_branch" 2>/dev/null || true)
  if [ -z "$local_head" ]; then
    echo "git mirror flush skips missing local refs/heads/$gitops_branch"
    continue
  fi
  fetch_started=$(now_ms)
  timeout 90 git -C "$repo_path" fetch --quiet "$repo_url" "refs/heads/$gitops_branch:refs/mirror-stage/heads/$gitops_branch"
  emit_timing "fetch-$gitops_branch" succeeded "$fetch_started"
  github_head=$(git -C "$repo_path" show-ref --verify --hash "refs/mirror-stage/heads/$gitops_branch" 2>/dev/null || true)
  if [ -n "$github_head" ] && [ "$github_head" != "$local_head" ] && ! git -C "$repo_path" merge-base --is-ancestor "$github_head" "$local_head"; then
    echo "git mirror flush rejected divergent $gitops_branch local=$local_head github=$github_head" >&2
    exit 52
  fi
  if [ "$local_head" != "$github_head" ]; then
    push_started=$(now_ms)
    timeout 120 git -C "$repo_path" push "$repo_url" "$local_head:refs/heads/$gitops_branch"
    emit_timing "push-$gitops_branch" succeeded "$push_started"
  else
    echo "git mirror flush $gitops_branch already matches GitHub"
  fi
  git -C "$repo_path" update-ref "refs/mirror-stage/heads/$gitops_branch" "$local_head"
done
git -C "$repo_path" update-server-info
flushed_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
export flushed_at
export gitops_branches_json=${shellSingleQuote(gitopsBranchesJson)}
node - <<'NODE' | tee /cache/HWLAB.last-flush.json
const { execFileSync } = require("node:child_process");
const repo = "/cache/pikasTech/HWLAB.git";
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
function rev(ref) {
  try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
}
const refs = {};
for (const branch of gitopsBranches) {
  refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
  refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
}
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/mirror-stage/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
console.log(JSON.stringify({
  event: "git-mirror-flush",
  status: "flushed",
  repository: "pikasTech/HWLAB",
  flushedAt: process.env.flushed_at,
  pendingFlush,
  refs
}));
NODE
emit_timing total succeeded "$started_ms"
`,
          "http.mjs": `import { createServer } from "node:http";
import { spawn } from "node:child_process";
import { createReadStream, statSync } from "node:fs";
import path from "node:path";
import { createGunzip, createInflate } from "node:zlib";

const cacheRoot = process.env.GIT_MIRROR_CACHE_ROOT || "/cache";
const port = Number(process.env.PORT || 8080);

createServer((req, res) => {
  handle(req, res).catch((error) => {
    if (!res.headersSent) res.writeHead(500, { "content-type": "application/json" });
    res.end(JSON.stringify({ ok: false, error: error.message }));
  });
}).listen(port, "0.0.0.0", () => {
  console.log(JSON.stringify({ event: "git-mirror-smart-http-listening", port, cacheRoot }));
});

async function handle(req, res) {
  const url = new URL(req.url || "/", "http://git-mirror-http");
  const writeHost = isWriteHost(req.headers.host || "");
  if (req.method === "GET" && (url.pathname === "/" || url.pathname === "/health")) {
    res.writeHead(200, { "content-type": "application/json", "cache-control": "no-cache" });
    res.end(JSON.stringify({ ok: true, service: "git-mirror-smart-http", writeHost }));
    return;
  }
  if (req.method === "GET" && url.pathname.endsWith("/info/refs") && url.searchParams.get("service") === "git-upload-pack") {
    await runUploadPackAdvertisement(repoPathFromGitServicePath(url.pathname, "/info/refs"), res);
    return;
  }
  if (req.method === "POST" && url.pathname.endsWith("/git-upload-pack")) {
    await runUploadPackRpc(repoPathFromGitServicePath(url.pathname, "/git-upload-pack"), req, res);
    return;
  }
  if (req.method === "GET" && url.pathname.endsWith("/info/refs") && url.searchParams.get("service") === "git-receive-pack") {
    if (!writeHost) return rejectReadOnly(res);
    await runReceivePackAdvertisement(repoPathFromGitServicePath(url.pathname, "/info/refs"), res);
    return;
  }
  if (req.method === "POST" && url.pathname.endsWith("/git-receive-pack")) {
    if (!writeHost) return rejectReadOnly(res);
    await runReceivePackRpc(repoPathFromGitServicePath(url.pathname, "/git-receive-pack"), req, res);
    return;
  }
  if (req.method === "GET" || req.method === "HEAD") {
    serveStaticFile(url.pathname, req, res);
    return;
  }
  res.writeHead(405, { "content-type": "text/plain" });
  res.end("method not allowed\\n");
}

function isWriteHost(hostHeader) {
  const host = String(hostHeader || "").split(":", 1)[0].toLowerCase();
  return host === "git-mirror-write" || host.startsWith("git-mirror-write.");
}

function rejectReadOnly(res) {
  res.writeHead(403, { "content-type": "application/json", "cache-control": "no-cache" });
  res.end(JSON.stringify({ ok: false, error: "git mirror receive-pack is only available through git-mirror-write" }));
}

function repoPathFromGitServicePath(urlPath, suffix) {
  const repoUrlPath = urlPath.slice(0, -suffix.length);
  if (!repoUrlPath.endsWith(".git")) throw new Error(` + "`" + `unsupported git repo path: \${urlPath}` + "`" + `);
  return safePath(repoUrlPath);
}

function safePath(urlPath) {
  const decoded = decodeURIComponent(urlPath.replace(/^[/]+/u, ""));
  const fullPath = path.resolve(cacheRoot, decoded);
  const normalizedRoot = path.resolve(cacheRoot);
  if (fullPath !== normalizedRoot && !fullPath.startsWith(` + "`" + `\${normalizedRoot}\${path.sep}` + "`" + `)) throw new Error("path escapes cache root");
  return fullPath;
}

function smartHeaders(contentType) {
  return {
    "content-type": contentType,
    "cache-control": "no-cache, max-age=0, must-revalidate",
    expires: "Fri, 01 Jan 1980 00:00:00 GMT",
    pragma: "no-cache"
  };
}

function pktLine(text) {
  const length = Buffer.byteLength(text) + 4;
  return ` + "`" + `\${length.toString(16).padStart(4, "0")}\${text}` + "`" + `;
}

function requestBodyStream(req) {
  const encoding = String(req.headers["content-encoding"] || "identity").toLowerCase();
  if (encoding === "identity" || encoding === "") return req;
  if (encoding === "gzip" || encoding === "x-gzip") return req.pipe(createGunzip());
  if (encoding === "deflate") return req.pipe(createInflate());
  throw new Error(` + "`" + `unsupported git upload-pack content-encoding: \${encoding}` + "`" + `);
}

function runUploadPackAdvertisement(repoPath, res) {
  return new Promise((resolve, reject) => {
    const child = spawn("git-upload-pack", ["--stateless-rpc", "--advertise-refs", repoPath], { stdio: ["ignore", "pipe", "pipe"] });
    let stderr = "";
    child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
    child.on("error", reject);
    child.on("close", (code) => {
      if (code !== 0 && !res.headersSent) reject(new Error(` + "`" + `git-upload-pack advertise failed: \${stderr.trim()}` + "`" + `));
      else resolve();
    });
    res.writeHead(200, smartHeaders("application/x-git-upload-pack-advertisement"));
    res.write(pktLine("# service=git-upload-pack\\n"));
    res.write("0000");
    child.stdout.pipe(res, { end: false });
    child.stdout.on("end", () => res.end());
  });
}

function runUploadPackRpc(repoPath, req, res) {
  return new Promise((resolve, reject) => {
    const child = spawn("git-upload-pack", ["--stateless-rpc", repoPath], { stdio: ["pipe", "pipe", "pipe"] });
    let stderr = "";
    child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
    child.on("error", reject);
    child.on("close", (code) => {
      if (code !== 0 && !res.headersSent) reject(new Error(` + "`" + `git-upload-pack rpc failed: \${stderr.trim()}` + "`" + `));
      else resolve();
    });
    res.writeHead(200, smartHeaders("application/x-git-upload-pack-result"));
    const body = requestBodyStream(req);
    body.on("error", (error) => child.stdin.destroy(error));
    body.pipe(child.stdin);
    child.stdout.pipe(res);
  });
}

function runReceivePackAdvertisement(repoPath, res) {
  return new Promise((resolve, reject) => {
    const child = spawn("git-receive-pack", ["--stateless-rpc", "--advertise-refs", repoPath], { stdio: ["ignore", "pipe", "pipe"] });
    let stderr = "";
    child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
    child.on("error", reject);
    child.on("close", (code) => {
      if (code !== 0 && !res.headersSent) reject(new Error(` + "`" + `git-receive-pack advertise failed: \${stderr.trim()}` + "`" + `));
      else resolve();
    });
    res.writeHead(200, smartHeaders("application/x-git-receive-pack-advertisement"));
    res.write(pktLine("# service=git-receive-pack\\n"));
    res.write("0000");
    child.stdout.pipe(res, { end: false });
    child.stdout.on("end", () => res.end());
  });
}

function runReceivePackRpc(repoPath, req, res) {
  return new Promise((resolve, reject) => {
    const child = spawn("git-receive-pack", ["--stateless-rpc", repoPath], { stdio: ["pipe", "pipe", "pipe"] });
    let stderr = "";
    child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
    child.on("error", reject);
    child.on("close", (code) => {
      if (code !== 0 && !res.headersSent) reject(new Error(` + "`" + `git-receive-pack rpc failed: \${stderr.trim()}` + "`" + `));
      else resolve();
    });
    res.writeHead(200, smartHeaders("application/x-git-receive-pack-result"));
    const body = requestBodyStream(req);
    body.on("error", (error) => child.stdin.destroy(error));
    body.pipe(child.stdin);
    child.stdout.pipe(res);
  });
}

function serveStaticFile(urlPath, req, res) {
  const fullPath = safePath(urlPath);
  let stat;
  try { stat = statSync(fullPath); } catch {
    res.writeHead(404, { "content-type": "text/plain" });
    res.end("not found\\n");
    return;
  }
  if (!stat.isFile()) {
    res.writeHead(404, { "content-type": "text/plain" });
    res.end("not found\\n");
    return;
  }
  res.writeHead(200, { "content-length": stat.size, "content-type": contentType(fullPath), "cache-control": "no-cache" });
  if (req.method === "HEAD") {
    res.end();
    return;
  }
  createReadStream(fullPath).pipe(res);
}

function contentType(filePath) {
  if (filePath.endsWith(".pack")) return "application/x-git-packed-objects";
  if (filePath.endsWith(".idx")) return "application/x-git-packed-objects-toc";
  return "text/plain";
}
`
        }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name: gitMirrorReadName, namespace: gitMirrorNamespace, labels: readLabels },
        spec: {
          replicas: 1,
          selector: { matchLabels: { "app.kubernetes.io/name": gitMirrorReadName } },
          template: {
            metadata: { labels: readLabels },
            spec: {
              containers: [{
                name: "git-mirror",
                image: ciToolsRunnerImage,
                imagePullPolicy: "IfNotPresent",
                command: ["node"],
                args: ["/etc/git-mirror/http.mjs"],
                ports: [{ name: "http", containerPort: 8080 }],
                readinessProbe: { httpGet: { path: "/pikasTech/HWLAB.git/HEAD", port: "http" }, initialDelaySeconds: 5, periodSeconds: 10 },
                livenessProbe: { httpGet: { path: "/", port: "http" }, initialDelaySeconds: 10, periodSeconds: 30 },
                volumeMounts: [
                  { name: "cache", mountPath: "/cache" },
                  { name: "config", mountPath: "/etc/git-mirror", readOnly: true }
                ]
              }],
              volumes: [
                cacheVolume,
                { name: "config", configMap: { name: gitMirrorConfigMapName, defaultMode: 0o555 } }
              ]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name: gitMirrorReadName, namespace: gitMirrorNamespace, labels: readLabels },
        spec: { selector: { "app.kubernetes.io/name": gitMirrorReadName }, ports: [{ name: "http", port: gitMirrorServicePort, targetPort: "http" }] }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name: gitMirrorWriteName, namespace: gitMirrorNamespace, labels: writeLabels },
        spec: { selector: { "app.kubernetes.io/name": gitMirrorReadName }, ports: [{ name: "http", port: gitMirrorServicePort, targetPort: "http" }] }
      }
    ]
  };
}

function argoProject(args = { lane: "node" }) {
  if (isRuntimeLane(args.lane)) {
    const namespace = namespaceNameForProfile(args.lane);
    return {
      apiVersion: "argoproj.io/v1alpha1",
      kind: "AppProject",
      metadata: { name: namespace, namespace: "argocd" },
      spec: {
        description: `HWLAB ${versionNameForRuntimeLane(args.lane)} additive GitOps project on target node; DEV/PROD remain outside this lane.`,
        sourceRepos: [args.gitReadUrl],
        destinations: [{ server: "https://kubernetes.default.svc", namespace }],
        clusterResourceWhitelist: [{ group: "", kind: "Namespace" }],
        namespaceResourceWhitelist: [{ group: "*", kind: "*" }]
      }
    };
  }
  return {
    apiVersion: "argoproj.io/v1alpha1",
    kind: "AppProject",
    metadata: { name: "hwlab-node", namespace: "argocd" },
    spec: {
      description: "HWLAB node GitOps project; D601 remains outside this project.",
      sourceRepos: [defaultSourceRepo],
      destinations: [
        { server: "https://kubernetes.default.svc", namespace: "hwlab-dev" },
        { server: "https://kubernetes.default.svc", namespace: "hwlab-prod" }
      ],
      clusterResourceWhitelist: [{ group: "", kind: "Namespace" }],
      namespaceResourceWhitelist: [{ group: "*", kind: "*" }]
    }
  };
}

function argoApplication(args, profile = "dev") {
  const namespace = namespaceNameForProfile(profile);
  const runtimePath = runtimePathForProfile(profile);
  const gitopsTarget = gitopsTargetForProfile(profile);
  const project = isRuntimeLane(profile) ? namespace : "hwlab-node";
  const repoURL = isRuntimeLane(profile) ? args.gitReadUrl : args.sourceRepo;
  return {
    apiVersion: "argoproj.io/v1alpha1",
    kind: "Application",
    metadata: {
      name: argoApplicationName(profile),
      namespace: "argocd",
      labels: { "app.kubernetes.io/part-of": "hwlab", "hwlab.pikastech.local/gitops-target": gitopsTarget }
    },
    spec: {
      project,
      source: { repoURL, targetRevision: args.gitopsBranch, path: gitopsPathForProfile(args, profile) },
      destination: { server: "https://kubernetes.default.svc", namespace },
      syncPolicy: { automated: { prune: isRuntimeLane(profile), selfHeal: true }, syncOptions: ["CreateNamespace=true", "ApplyOutOfSyncOnly=true"] }
    }
  };
}

function nodeFrpcManifest({ profile = "dev", source = null } = {}) {
  const namespace = namespaceNameForProfile(profile);
  const profileLabel = runtimeLabelForProfile(profile);
  const deploymentName = isRuntimeLane(profile) ? `hwlab-${profile}-frpc` : profile === "prod" ? "hwlab-node-prod-frpc" : "hwlab-node-frpc";
  const configName = `${deploymentName}-config`;
  const proxyPrefix = isRuntimeLane(profile) ? `hwlab-${profile}` : profile === "prod" ? "hwlab-node-prod" : "hwlab-node";
  const webRemotePort = isRuntimeLane(profile) ? defaultPortForRuntimeLane(profile) : profile === "prod" ? 18666 : 17666;
  const edgeRemotePort = isRuntimeLane(profile) ? webRemotePort + 1 : profile === "prod" ? 18667 : 17667;
  const labels = {
    "app.kubernetes.io/name": deploymentName,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/environment": profileLabel,
    "hwlab.pikastech.local/gitops-target": gitopsTargetForProfile(profile),
    "hwlab.pikastech.local/profile": profileLabel
  };
  const sourceCommitLabel = source?.full ? { "hwlab.pikastech.local/source-commit": source.full } : {};
  const renderedLabels = { ...labels, ...sourceCommitLabel };
  const podNetwork = isRuntimeLane(profile) ? {
    hostNetwork: true,
    dnsPolicy: "ClusterFirstWithHostNet"
  } : {};
  const configText = `serverAddr = "74.48.78.17"
serverPort = 7000
loginFailExit = true

[[proxies]]
name = "${proxyPrefix}-cloud-web"
type = "tcp"
localIP = "hwlab-cloud-web.${namespace}.svc.cluster.local"
localPort = 8080
remotePort = ${webRemotePort}

[[proxies]]
name = "${proxyPrefix}-edge-proxy"
type = "tcp"
localIP = "hwlab-edge-proxy.${namespace}.svc.cluster.local"
localPort = 6667
remotePort = ${edgeRemotePort}
`;
  const configSha256 = createHash("sha256").update(configText).digest("hex");
  const templateLabels = { ...labels, "hwlab.pikastech.local/config-sha256": k8sLabelHash(configSha256) };
  const templateAnnotations = { "hwlab.pikastech.local/config-sha256": configSha256 };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: {
          name: configName,
          namespace,
          labels: renderedLabels
        },
        data: {
          "frpc.toml": configText
        }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: {
          name: deploymentName,
          namespace,
          labels: renderedLabels
        },
        spec: {
          replicas: 1,
          selector: { matchLabels: { "app.kubernetes.io/name": deploymentName } },
          template: {
            metadata: { labels: templateLabels, annotations: templateAnnotations },
            spec: {
              ...podNetwork,
              containers: [{
                name: "frpc",
                image: "fatedier/frpc:v0.68.1",
                imagePullPolicy: "IfNotPresent",
                args: ["-c", "/etc/frp/frpc.toml"],
                volumeMounts: [{ name: "config", mountPath: "/etc/frp", readOnly: true }]
              }],
              volumes: [{ name: "config", configMap: { name: configName } }]
            }
          }
        }
      }
    ]
  };
}

function deepSeekProxyManifest({ profile = "dev", source, sourceBranch = defaultBranch, sourceRepo = defaultSourceRepo, gitReadUrl, deploy = null, registryPrefix = defaultRegistryPrefix, catalog = null, useDeployImages = false, metricsSidecarSha256 = null } = {}) {
  const namespace = namespaceNameForProfile(profile);
  const bridgeServiceId = "hwlab-cloud-api";
  const runtimeLane = isRuntimeLane(profile);
  const digestPin = runtimeLane;
  const envReuseServiceIds = runtimeLane ? envReuseServiceIdsForLane(deploy, profile) : null;
  const bridgeImage = runtimeImageForService({ catalog, deploy, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages, digestPin, envReuseServiceIds });
  const bridgeCommit = runtimeCommitForService({ catalog, deploy, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages, digestPin, envReuseServiceIds });
  const bridgeImageTag = runtimeImageTagForService({ catalog, deploy, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages, digestPin, envReuseServiceIds });
  const bridgeBootMetadata = runtimeLane && v02EnvReuseEnabled(catalog, bridgeServiceId, envReuseServiceIds)
    ? bootMetadataForService({ args: { sourceRepo: deploy?.lanes?.[profile]?.sourceRepo || sourceRepo, registryPrefix }, catalog, deployService: deployServiceForBoot(deploy, bridgeServiceId, profile), serviceId: bridgeServiceId, source })
    : null;
  const labels = {
    "app.kubernetes.io/name": "hwlab-deepseek-proxy",
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/environment": runtimeLabelForProfile(profile),
    "hwlab.pikastech.local/gitops-target": gitopsTargetForProfile(profile),
    "hwlab.pikastech.local/service-id": "hwlab-deepseek-proxy",
    "hwlab.pikastech.local/source-commit": source.full
  };
  if (runtimeLane) Object.assign(labels, v02MetricsLabels("hwlab-deepseek-proxy"));
  const templateLabels = {
    ...labels,
    "hwlab.pikastech.local/source-commit": bridgeCommit,
    "hwlab.pikastech.local/bridge-source-commit": bridgeCommit
  };
  const templateAnnotations = {
    "hwlab.pikastech.local/bridge-service-id": bridgeServiceId,
    "hwlab.pikastech.local/source-commit": bridgeCommit,
    "hwlab.pikastech.local/bridge-source-commit": bridgeCommit,
    "hwlab.pikastech.local/bridge-image-tag": bridgeImageTag,
    "hwlab.pikastech.local/bridge-image": bridgeImage,
    ...v02MetricsSidecarAnnotations(runtimeLane ? metricsSidecarSha256 : null)
  };
  const responsesBridgeContainer = {
    name: "responses-bridge",
    image: bridgeImage,
    imagePullPolicy: "IfNotPresent",
    command: ["/usr/local/bin/bun", "run", "/app/cmd/hwlab-deepseek-responses-bridge/main.ts"],
    env: [
      { name: "PORT", value: "4000" },
      { name: "HWLAB_COMMIT_ID", value: bridgeCommit },
      { name: "HWLAB_IMAGE", value: bridgeImage },
      { name: "HWLAB_IMAGE_TAG", value: bridgeImageTag },
      { name: "HWLAB_DEEPSEEK_BRIDGE_UPSTREAM", value: "http://127.0.0.1:4001" },
      { name: "HWLAB_DEEPSEEK_BRIDGE_MODEL", value: deepSeekProfileModel }
    ],
    ports: [{ name: "http", containerPort: 4000 }],
    readinessProbe: { httpGet: { path: "/health/readiness", port: "http" }, initialDelaySeconds: 10, periodSeconds: 10 },
    livenessProbe: { httpGet: { path: "/health/liveliness", port: "http" }, initialDelaySeconds: 20, periodSeconds: 20 }
  };
  if (bridgeBootMetadata) {
    applyEnvReuseBootEnv(responsesBridgeContainer, bridgeBootMetadata, { sourceBranch, gitReadUrl, bootSh: "deploy/runtime/boot/hwlab-deepseek-responses-bridge.sh" });
    Object.assign(templateAnnotations, {
      "hwlab.pikastech.local/bridge-runtime-mode": bridgeBootMetadata.runtimeMode,
      "hwlab.pikastech.local/bridge-boot-repo": bridgeBootMetadata.bootRepo,
      "hwlab.pikastech.local/bridge-boot-commit": bridgeBootMetadata.bootCommit,
      "hwlab.pikastech.local/bridge-boot-sh": "deploy/runtime/boot/hwlab-deepseek-responses-bridge.sh",
      "hwlab.pikastech.local/bridge-environment-digest": bridgeBootMetadata.environmentDigest ?? "not_published"
    });
    Object.assign(templateLabels, {
      "hwlab.pikastech.local/bridge-runtime-mode": bridgeBootMetadata.runtimeMode,
      "hwlab.pikastech.local/bridge-boot-commit": bridgeBootMetadata.bootCommit
    });
  }
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: "hwlab-deepseek-proxy-config", namespace, labels },
        data: {
          "render-config.sh": moonBridgeConfigRenderScript()
        }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name: "hwlab-deepseek-proxy", namespace, labels, annotations: { "hwlab.pikastech.local/moonbridge-source-ref": moonBridgeSourceRef, ...templateAnnotations } },
        spec: {
          replicas: 1,
          selector: { matchLabels: { "app.kubernetes.io/name": "hwlab-deepseek-proxy" } },
          template: {
            metadata: { labels: templateLabels, annotations: templateAnnotations },
            spec: {
              initContainers: [{
                name: "moonbridge-config",
                image: bridgeImage,
                imagePullPolicy: "IfNotPresent",
                command: ["/bin/sh", "-eu", "/scripts/render-config.sh"],
                env: [
                  { name: "DEEPSEEK_API_KEY", valueFrom: { secretKeyRef: { name: secretNameForProfile("hwlab-code-agent-provider", profile), key: "openai-api-key", optional: true } } },
                  { name: "OPENCODE_API_KEY", valueFrom: { secretKeyRef: { name: secretNameForProfile("hwlab-code-agent-provider", profile), key: "opencode-api-key", optional: true } } }
                ],
                volumeMounts: [
                  { name: "moonbridge-scripts", mountPath: "/scripts", readOnly: true },
                  { name: "moonbridge-config", mountPath: "/config" }
                ]
              }],
              containers: [responsesBridgeContainer, {
                name: "moonbridge",
                image: moonBridgeImage,
                imagePullPolicy: "IfNotPresent",
                args: ["-config", "/config/config.yml"],
                ports: [{ name: "moonbridge-http", containerPort: 4001 }],
                readinessProbe: { httpGet: { path: "/v1/models", port: "moonbridge-http" }, initialDelaySeconds: 10, periodSeconds: 10 },
                livenessProbe: { httpGet: { path: "/v1/models", port: "moonbridge-http" }, initialDelaySeconds: 20, periodSeconds: 20 },
                volumeMounts: [
                  { name: "moonbridge-config", mountPath: "/config", readOnly: true },
                  { name: "moonbridge-data", mountPath: "/data" }
                ]
              }, ...(runtimeLane ? [v02MetricsSidecarContainer({ deploy, serviceId: "hwlab-deepseek-proxy", namespace, gitopsTarget: gitopsTargetForProfile(profile) })] : [])],
              volumes: [
                { name: "moonbridge-scripts", configMap: { name: "hwlab-deepseek-proxy-config" } },
                { name: "moonbridge-config", emptyDir: {} },
                { name: "moonbridge-data", emptyDir: {} },
                ...(runtimeLane ? [v02MetricsSidecarVolume(profile)] : [])
              ]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name: "hwlab-deepseek-proxy", namespace, labels },
        spec: { type: "ClusterIP", selector: { "app.kubernetes.io/name": "hwlab-deepseek-proxy" }, ports: [{ name: "http", port: 4000, targetPort: "http" }, ...(runtimeLane ? [{ name: "metrics", port: 9100, targetPort: "metrics" }] : [])] }
      }
    ]
  };
}

function moonBridgeConfigRenderScript() {
  return `#!/bin/sh
if [ -z "\${DEEPSEEK_API_KEY:-}" ] && [ -z "\${OPENCODE_API_KEY:-}" ]; then
  echo "at least one of DEEPSEEK_API_KEY or OPENCODE_API_KEY is required" >&2
  exit 1
fi
cat > /config/config.yml <<EOF
mode: "Transform"
log:
  level: "info"
  format: "text"
server:
  addr: "0.0.0.0:4001"
persistence:
  active_provider: db_sqlite
extensions:
  db_sqlite:
    enabled: true
    config:
      path: /data/moonbridge.db
      wal: true
      busy_timeout_ms: 5000
      max_open_conns: 1
  metrics:
    enabled: true
    config:
      default_limit: 100
      max_limit: 1000
  deepseek_v4:
    config:
      reinforce_instructions: true
      reinforce_prompt: "[System Reminder]: Please pay close attention to the system instructions, AGENTS.md files, and any other context provided. Follow them carefully and completely in your response.\\n[User]:"
cache:
  mode: "explicit"
  ttl: "5m"
  prompt_caching: true
  automatic_prompt_cache: false
  explicit_cache_breakpoints: true
  allow_retention_downgrade: false
  max_breakpoints: 4
  min_cache_tokens: 1024
  expected_reuse: 2
  minimum_value_score: 2048
  min_breakpoint_tokens: 1024
defaults:
  model: "${deepSeekProfileModel}"
  max_tokens: 8192
trace:
  enabled: false
models:
  ${deepSeekProfileModel}:
    context_window: 128000
    max_output_tokens: 8192
    display_name: "${deepSeekProfileModel}"
    description: "DeepSeek via Moon Bridge"
    default_reasoning_level: null
    supported_reasoning_levels: []
    extensions:
      deepseek_v4:
        enabled: true
  deepseek-v4-flash:
    context_window: 1000000
    max_output_tokens: 384000
    display_name: "DeepSeek V4 Flash via OpenCode Zen Go"
    description: "DeepSeek V4 Flash through OpenCode Zen Go Chat Completions via Moon Bridge"
    default_reasoning_level: "xhigh"
    supported_reasoning_levels:
      - effort: "high"
        description: "High reasoning effort"
      - effort: "xhigh"
        description: "Maximum reasoning effort"
    supports_reasoning_summaries: true
    default_reasoning_summary: "auto"
    extensions:
      deepseek_v4:
        enabled: true
providers:
  deepseek:
    base_url: "https://api.deepseek.com/anthropic"
    api_key: "\${DEEPSEEK_API_KEY}"
    version: "2023-06-01"
    user_agent: "moonbridge/1.0"
    offers:
      - model: ${deepSeekProfileModel}
  opencode:
    base_url: "https://opencode.ai/zen/go/v1"
    api_key: "\${OPENCODE_API_KEY:-}"
    protocol: "openai-chat"
    user_agent: "moonbridge-dsflash-go/1.0"
    web_search:
      support: "disabled"
    offers:
      - model: deepseek-v4-flash
routes:
  ${deepSeekProfileModel}:
    model: ${deepSeekProfileModel}
    provider: deepseek
  deepseek-v4-flash:
    model: deepseek-v4-flash
    provider: opencode
EOF
`;
}

function deviceAgent71FreqServerScript() {
  return [
    "import http from \"node:http\";",
    "",
    "const deviceId = process.env.DEVICE_ID || \"71-freq\";",
    "const port = Number(process.env.PORT || 7601);",
    "const cloudApiUrl = (process.env.HWLAB_CLOUD_API_URL || \"http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667\").replace(/\\/+$/u, \"\");",
    "const gatewaySessionId = process.env.HWLAB_GATEWAY_SESSION_ID || \"gws_d601_win_71_freq\";",
    "const resourceId = process.env.HWLAB_GATEWAY_RESOURCE_ID || \"res_d601_windows_host\";",
    "const capabilityId = process.env.HWLAB_GATEWAY_CAPABILITY_ID || \"cap_d601_windows_cmd_exec\";",
    "const workspaceRoot = process.env.DEVICE_WORKSPACE_ROOT || \"F:\\\\Work\\\\ConStart\";",
    "",
    "function sendJson(res, statusCode, payload) {",
    "  const body = JSON.stringify(payload, null, 2);",
    "  res.writeHead(statusCode, { \"content-type\": \"application/json; charset=utf-8\" });",
    "  res.end(body);",
    "}",
    "",
    "function readBody(req) {",
    "  return new Promise((resolve, reject) => {",
    "    let body = \"\";",
    "    req.setEncoding(\"utf8\");",
    "    req.on(\"data\", (chunk) => {",
    "      body += chunk;",
    "      if (body.length > 1024 * 1024) req.destroy(new Error(\"request body too large\"));",
    "    });",
    "    req.on(\"end\", () => resolve(body ? JSON.parse(body) : {}));",
    "    req.on(\"error\", reject);",
    "  });",
    "}",
    "",
    "function postJson(url, payload, timeoutMs) {",
    "  return new Promise((resolve, reject) => {",
    "    const parsed = new URL(url);",
    "    const body = JSON.stringify(payload);",
    "    const request = http.request({",
    "      hostname: parsed.hostname,",
    "      port: parsed.port || 80,",
    "      path: parsed.pathname + parsed.search,",
    "      method: \"POST\",",
    "      headers: { \"content-type\": \"application/json\", \"content-length\": Buffer.byteLength(body) },",
    "      timeout: timeoutMs",
    "    }, (response) => {",
    "      let responseBody = \"\";",
    "      response.setEncoding(\"utf8\");",
    "      response.on(\"data\", (chunk) => { responseBody += chunk; });",
    "      response.on(\"end\", () => {",
    "        try {",
    "          const parsedBody = responseBody ? JSON.parse(responseBody) : null;",
    "          resolve({ statusCode: response.statusCode, body: parsedBody });",
    "        } catch (error) {",
    "          reject(error);",
    "        }",
    "      });",
    "    });",
    "    request.on(\"timeout\", () => request.destroy(new Error(\"request timeout after \" + timeoutMs + \"ms\")));",
    "    request.on(\"error\", reject);",
    "    request.end(body);",
    "  });",
    "}",
    "",
    "function gatewayPayload(input) {",
    "  const traceId = input.traceId || \"trc_device_agent_71_freq_\" + Date.now();",
    "  return {",
    "    jsonrpc: \"2.0\",",
    "    id: input.id || \"req_device_agent_71_freq_\" + Date.now(),",
    "    method: \"hardware.invoke.shell\",",
    "    meta: { serviceId: \"hwlab-cloud-api\", actorId: \"device-agent-71-freq\", environment: \"dev\", traceId, deviceId, workspaceRoot },",
    "    params: {",
    "      gatewaySessionId,",
    "      resourceId,",
    "      capabilityId,",
    "      input: {",
    "        command: input.command,",
    "        cwd: input.cwd || workspaceRoot,",
    "        timeoutMs: input.timeoutMs || 30000",
    "      }",
    "    }",
    "  };",
    "}",
    "",
    "const server = http.createServer(async (req, res) => {",
    "  try {",
    "    const url = new URL(req.url || \"/\", \"http://device-agent-71-freq\");",
    "    if (req.method === \"GET\" && url.pathname === \"/health\") {",
    "      return sendJson(res, 200, { ok: true, deviceId, workspaceRoot, gatewaySessionId, resourceId, capabilityId, cloudApiUrl });",
    "    }",
    "    if (req.method === \"GET\" && url.pathname === \"/skills\") {",
    "      return sendJson(res, 200, { ok: true, deviceId, skills: [{ name: \"cmd\", description: \"Run a bounded Windows cmd command through hwlab-gateway.\" }] });",
    "    }",
    "    if (req.method === \"POST\" && url.pathname === \"/run\") {",
    "      const input = await readBody(req);",
    "      if (!input.command || typeof input.command !== \"string\") return sendJson(res, 400, { ok: false, error: \"command is required\" });",
    "      const timeoutMs = Number(input.timeoutMs || 30000);",
    "      const upstream = await postJson(cloudApiUrl + \"/json-rpc\", gatewayPayload({ ...input, timeoutMs }), timeoutMs + 5000);",
    "      return sendJson(res, upstream.statusCode || 502, { ok: upstream.statusCode >= 200 && upstream.statusCode < 300, deviceId, gatewaySessionId, upstream: upstream.body });",
    "    }",
    "    return sendJson(res, 404, { ok: false, error: \"not found\" });",
    "  } catch (error) {",
    "    return sendJson(res, 500, { ok: false, error: error.message });",
    "  }",
    "});",
    "",
    "server.listen(port, \"0.0.0.0\", () => {",
    "  console.log(JSON.stringify({ ok: true, service: \"device-agent-71-freq\", port, deviceId, workspaceRoot, cloudApiUrl }));",
    "});"
  ].join("\n") + "\n";
}

function deviceAgent71FreqManifest({ profile = "dev", source, registryPrefix, catalog = null, useDeployImages = false }) {
  assert.equal(profile, "dev", "71-freq device-agent is dev-only");
  const namespace = namespaceNameForProfile(profile);
  const name = "device-agent-71-freq";
  const bridgeServiceId = "hwlab-cloud-api";
  const bridgeImage = runtimeImageForService({ catalog, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages });
  const bridgeCommit = runtimeCommitForService({ catalog, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages });
  const bridgeImageTag = runtimeImageTagForService({ catalog, serviceId: bridgeServiceId, source, registryPrefix, useDeployImages });
  const labels = {
    "app.kubernetes.io/name": name,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/component": "device-agent",
    "hwlab.pikastech.local/device-id": "71-freq",
    "hwlab.pikastech.local/environment": runtimeLabelForProfile(profile),
    "hwlab.pikastech.local/gitops-target": "node",
    "hwlab.pikastech.local/profile": runtimeLabelForProfile(profile),
    "hwlab.pikastech.local/service-id": name,
    "hwlab.pikastech.local/source-commit": source.full
  };
  const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
  const selector = { "app.kubernetes.io/name": name };
  const script = deviceAgent71FreqServerScript();
  const scriptSha256 = createHash("sha256").update(script).digest("hex");
  const templateLabels = { ...labels, ...selector, "hwlab.pikastech.local/source-commit": bridgeCommit };
  const templateAnnotations = {
    ...annotations,
    "hwlab.pikastech.local/script-sha256": scriptSha256,
    "hwlab.pikastech.local/bridge-service-id": bridgeServiceId,
    "hwlab.pikastech.local/bridge-source-commit": bridgeCommit,
    "hwlab.pikastech.local/bridge-image-tag": bridgeImageTag,
    "hwlab.pikastech.local/bridge-image": bridgeImage
  };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: `${name}-script`, namespace, labels, annotations: templateAnnotations },
        data: { "server.mjs": script }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name, namespace, labels, annotations },
        spec: {
          replicas: 1,
          selector: { matchLabels: selector },
          template: {
            metadata: { labels: templateLabels, annotations: templateAnnotations },
            spec: {
              containers: [{
                name: "device-agent",
                image: bridgeImage,
                imagePullPolicy: "IfNotPresent",
                command: ["node", "/opt/device-agent/server.mjs"],
                env: [
                  { name: "PORT", value: "7601" },
                  { name: "HWLAB_COMMIT_ID", value: bridgeCommit },
                  { name: "HWLAB_IMAGE", value: bridgeImage },
                  { name: "HWLAB_IMAGE_TAG", value: bridgeImageTag },
                  { name: "DEVICE_ID", value: "71-freq" },
                  { name: "DEVICE_WORKSPACE_ROOT", value: "F:\\Work\\ConStart" },
                  { name: "HWLAB_CLOUD_API_URL", value: `http://hwlab-cloud-api.${namespace}.svc.cluster.local:6667` },
                  { name: "HWLAB_GATEWAY_SESSION_ID", value: "gws_d601_win_71_freq" },
                  { name: "HWLAB_GATEWAY_RESOURCE_ID", value: "res_d601_windows_host" },
                  { name: "HWLAB_GATEWAY_CAPABILITY_ID", value: "cap_d601_windows_cmd_exec" }
                ],
                ports: [{ name: "http", containerPort: 7601 }],
                readinessProbe: { httpGet: { path: "/health", port: "http" }, initialDelaySeconds: 3, periodSeconds: 10 },
                livenessProbe: { httpGet: { path: "/health", port: "http" }, initialDelaySeconds: 10, periodSeconds: 20 },
                resources: { requests: { cpu: "10m", memory: "64Mi" }, limits: { cpu: "200m", memory: "256Mi" } },
                volumeMounts: [
                  { name: "script", mountPath: "/opt/device-agent", readOnly: true },
                  { name: "hwlab-code-agent-workspace", mountPath: "/workspace" }
                ]
              }],
              volumes: [
                { name: "script", configMap: { name: `${name}-script` } },
                { name: "hwlab-code-agent-workspace", persistentVolumeClaim: { claimName: "hwlab-code-agent-workspace" } }
              ]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name, namespace, labels, annotations },
        spec: { type: "ClusterIP", selector, ports: [{ name: "http", port: 7601, targetPort: "http" }] }
      }
    ]
  };
}

function runtimePostgresImageForProfile(deploy, profile) {
  const postgres = runtimeLaneConfig(deploy, profile)?.runtimeStore?.postgres;
  const image = postgres && typeof postgres === "object" && !Array.isArray(postgres) ? postgres.image : null;
  return typeof image === "string" && image.trim().length > 0 ? image.trim() : "postgres:16-alpine";
}

function v02PostgresManifest({ profile = "v02", migrationSql, source, image = "postgres:16-alpine" }) {
  const namespace = namespaceNameForProfile(profile);
  const name = `${namespace}-postgres`;
  const dbName = `hwlab_${profile}`;
  const labels = {
    "app.kubernetes.io/name": name,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/environment": profile,
    "hwlab.pikastech.local/gitops-target": profile,
    "hwlab.pikastech.local/profile": profile,
    "hwlab.pikastech.local/source-commit": source.full
  };
  const migrationSha256 = createHash("sha256").update(migrationSql).digest("hex");
  const templateLabels = {
    "app.kubernetes.io/name": name,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/environment": profile,
    "hwlab.pikastech.local/gitops-target": profile,
    "hwlab.pikastech.local/profile": profile,
    "hwlab.pikastech.local/migration-sha256": k8sLabelHash(migrationSha256)
  };
  const templateAnnotations = { "hwlab.pikastech.local/migration-sha256": migrationSha256 };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: `${name}-init`, namespace, labels },
        data: { "0001_cloud_core_skeleton.sql": migrationSql }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name, namespace, labels },
        spec: { type: "ClusterIP", selector: { "app.kubernetes.io/name": name }, ports: [{ name: "postgres", port: 5432, targetPort: "postgres" }] }
      },
      {
        apiVersion: "apps/v1",
        kind: "StatefulSet",
        metadata: { name, namespace, labels },
        spec: {
          serviceName: name,
          replicas: 1,
          selector: { matchLabels: { "app.kubernetes.io/name": name } },
          template: {
            metadata: { labels: templateLabels, annotations: templateAnnotations },
            spec: {
              containers: [{
                name: "postgres",
                image,
                imagePullPolicy: "IfNotPresent",
                env: [
                  { name: "POSTGRES_DB", value: dbName },
                  { name: "POSTGRES_USER", value: dbName },
                  { name: "POSTGRES_PASSWORD", valueFrom: { secretKeyRef: { name, key: "POSTGRES_PASSWORD" } } }
                ],
                ports: [{ name: "postgres", containerPort: 5432 }],
                readinessProbe: { tcpSocket: { port: "postgres" }, initialDelaySeconds: 5, periodSeconds: 10 },
                livenessProbe: { tcpSocket: { port: "postgres" }, initialDelaySeconds: 30, periodSeconds: 20 },
                volumeMounts: [
                  { name: "data", mountPath: "/var/lib/postgresql/data" },
                  { name: "init", mountPath: "/docker-entrypoint-initdb.d", readOnly: true }
                ]
              }],
              volumes: [{ name: "init", configMap: { name: `${name}-init` } }]
            }
          },
          volumeClaimTemplates: [{
            metadata: { name: "data" },
            spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: "8Gi" } } }
          }]
        }
      }
    ]
  };
}

function externalPostgresConfigForLane(deploy, profile) {
  if (!isRuntimeLane(profile)) return null;
  const config = deploy?.lanes?.[profile]?.externalPostgres;
  if (!config || config.enabled !== true) return null;
  assert.ok(typeof config.serviceName === "string" && config.serviceName.length > 0, `deploy.lanes.${profile}.externalPostgres.serviceName is required`);
  assert.ok(typeof config.endpointAddress === "string" && config.endpointAddress.length > 0, `deploy.lanes.${profile}.externalPostgres.endpointAddress is required`);
  const port = Number(config.port ?? 5432);
  assert.ok(Number.isInteger(port) && port > 0 && port <= 65535, `deploy.lanes.${profile}.externalPostgres.port must be a valid TCP port`);
  return { serviceName: config.serviceName, endpointAddress: config.endpointAddress, port };
}

function externalPostgresManifest({ profile = "v03", config, source }) {
  const namespace = namespaceNameForProfile(profile);
  const labels = {
    "app.kubernetes.io/name": config.serviceName,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/component": "platform-db-bridge",
    "hwlab.pikastech.local/environment": profile,
    "hwlab.pikastech.local/gitops-target": profile,
    "hwlab.pikastech.local/profile": profile,
    "hwlab.pikastech.local/source-commit": source.full
  };
  const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name: config.serviceName, namespace, labels, annotations },
        spec: { type: "ClusterIP", ports: [{ name: "postgres", port: config.port, targetPort: config.port, protocol: "TCP" }] }
      },
      {
        apiVersion: "discovery.k8s.io/v1",
        kind: "EndpointSlice",
        metadata: { name: `${config.serviceName}-host`, namespace, labels: { ...labels, "kubernetes.io/service-name": config.serviceName }, annotations },
        addressType: "IPv4",
        ports: [{ name: "postgres", port: config.port, protocol: "TCP" }],
        endpoints: [{ addresses: [config.endpointAddress], conditions: { ready: true } }]
      }
    ]
  };
}

function v02OpenFgaManifest({ profile = "v02", source }) {
  const namespace = namespaceNameForProfile(profile);
  const name = "hwlab-openfga";
  const image = "127.0.0.1:5000/hwlab/openfga:v1.17.0";
  const labels = {
    "app.kubernetes.io/name": name,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/component": "authorization",
    "hwlab.pikastech.local/environment": profile,
    "hwlab.pikastech.local/gitops-target": profile,
    "hwlab.pikastech.local/profile": profile,
    "hwlab.pikastech.local/service-id": name,
    "hwlab.pikastech.local/source-commit": source.full
  };
  const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
  const selector = { "app.kubernetes.io/name": name };
  const env = [
    { name: "OPENFGA_DATASTORE_ENGINE", value: "postgres" },
    { name: "OPENFGA_DATASTORE_URI", valueFrom: { secretKeyRef: { name: `hwlab-${profile}-openfga`, key: "datastore-uri" } } },
    { name: "OPENFGA_AUTHN_METHOD", value: "preshared" },
    { name: "OPENFGA_AUTHN_PRESHARED_KEYS", valueFrom: { secretKeyRef: { name: `hwlab-${profile}-openfga`, key: "authn-preshared-key" } } },
    { name: "OPENFGA_PLAYGROUND_ENABLED", value: "false" },
    { name: "OPENFGA_HTTP_ADDR", value: "0.0.0.0:8080" },
    { name: "OPENFGA_GRPC_ADDR", value: "0.0.0.0:8081" }
  ];
  const templateLabels = { ...labels, ...selector };
  const runtimeAnnotations = { ...annotations, "argocd.argoproj.io/sync-wave": "2" };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "batch/v1",
        kind: "Job",
        metadata: {
          name: `${name}-migrate`,
          namespace,
          labels,
          annotations: {
            ...annotations,
            "argocd.argoproj.io/hook": "Sync",
            "argocd.argoproj.io/sync-wave": "1",
            "argocd.argoproj.io/hook-delete-policy": "BeforeHookCreation,HookSucceeded"
          }
        },
        spec: {
          backoffLimit: 3,
          template: {
            metadata: { labels: templateLabels, annotations },
            spec: {
              restartPolicy: "OnFailure",
              containers: [{ name: "openfga-migrate", image, imagePullPolicy: "IfNotPresent", args: ["migrate"], env }]
            }
          }
        }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name, namespace, labels, annotations: runtimeAnnotations },
        spec: {
          replicas: 1,
          selector: { matchLabels: selector },
          template: {
            metadata: { labels: templateLabels, annotations },
            spec: {
              containers: [{
                name: "openfga",
                image,
                imagePullPolicy: "IfNotPresent",
                args: ["run"],
                env,
                ports: [{ name: "http", containerPort: 8080 }, { name: "grpc", containerPort: 8081 }],
                readinessProbe: { httpGet: { path: "/healthz", port: "http" }, initialDelaySeconds: 3, periodSeconds: 10 },
                livenessProbe: { httpGet: { path: "/healthz", port: "http" }, initialDelaySeconds: 15, periodSeconds: 20 },
                resources: { requests: { cpu: "50m", memory: "128Mi" }, limits: { cpu: "500m", memory: "512Mi" } }
              }]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name, namespace, labels, annotations: runtimeAnnotations },
        spec: { type: "ClusterIP", selector, ports: [{ name: "http", port: 8080, targetPort: "http" }, { name: "grpc", port: 8081, targetPort: "grpc" }] }
      }
    ]
  };
}

function workbenchRuntimeRedisConf(config) {
  return [
    "save \"\"",
    "appendonly no",
    `maxmemory ${config.memoryPolicy.maxMemory}`,
    `maxmemory-policy ${config.memoryPolicy.eviction}`,
    ""
  ].join("\n");
}

function workbenchRuntimeRedisManifest({ profile = "v03", config, source }) {
  const namespace = config.namespace;
  const name = config.serviceName;
  const port = config.port;
  const selector = { "app.kubernetes.io/name": name };
  const labels = {
    ...selector,
    "app.kubernetes.io/part-of": "hwlab",
    "hwlab.pikastech.local/cache-role": "workbench-derived-read",
    "hwlab.pikastech.local/component": "workbench-runtime-cache",
    "hwlab.pikastech.local/environment": profile,
    "hwlab.pikastech.local/gitops-target": profile,
    "hwlab.pikastech.local/profile": profile,
    "hwlab.pikastech.local/service-id": name,
    "hwlab.pikastech.local/source-commit": source.full
  };
  const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
  const runtimeAnnotations = { ...annotations, "argocd.argoproj.io/sync-wave": "2" };
  const templateLabels = { ...labels, ...selector };
  return {
    apiVersion: "v1",
    kind: "List",
    items: [
      {
        apiVersion: "v1",
        kind: "ConfigMap",
        metadata: { name: `${name}-config`, namespace, labels, annotations: runtimeAnnotations },
        data: { "redis.conf": workbenchRuntimeRedisConf(config) }
      },
      {
        apiVersion: "apps/v1",
        kind: "Deployment",
        metadata: { name, namespace, labels, annotations: runtimeAnnotations },
        spec: {
          replicas: 1,
          selector: { matchLabels: selector },
          template: {
            metadata: { labels: templateLabels, annotations: runtimeAnnotations },
            spec: {
              containers: [{
                name: "redis",
                image: config.image,
                imagePullPolicy: "IfNotPresent",
                args: ["redis-server", "/usr/local/etc/redis/redis.conf"],
                ports: [{ name: "redis", containerPort: port }],
                readinessProbe: { exec: { command: ["redis-cli", "-p", String(port), "ping"] }, initialDelaySeconds: 3, periodSeconds: 10, timeoutSeconds: 2, failureThreshold: 3 },
                livenessProbe: { exec: { command: ["redis-cli", "-p", String(port), "ping"] }, initialDelaySeconds: 15, periodSeconds: 20, timeoutSeconds: 3, failureThreshold: 3 },
                resources: cloneJson(config.resources),
                volumeMounts: [{ name: "config", mountPath: "/usr/local/etc/redis", readOnly: true }]
              }],
              volumes: [{ name: "config", configMap: { name: `${name}-config` } }]
            }
          }
        }
      },
      {
        apiVersion: "v1",
        kind: "Service",
        metadata: { name, namespace, labels, annotations: runtimeAnnotations },
        spec: { type: "ClusterIP", selector, ports: [{ name: "redis", port, targetPort: "redis", protocol: "TCP" }] }
      },
      {
        apiVersion: "networking.k8s.io/v1",
        kind: "NetworkPolicy",
        metadata: { name: `${name}-ingress`, namespace, labels, annotations: runtimeAnnotations },
        spec: {
          podSelector: { matchLabels: selector },
          policyTypes: ["Ingress"],
          ingress: [{
            from: [{ podSelector: { matchLabels: { "app.kubernetes.io/name": "hwlab-workbench-runtime" } } }],
            ports: [{ protocol: "TCP", port }]
          }]
        }
      }
    ]
  };
}

function runtimeKustomization({ profile = "dev", includeDeviceAgent = profile === "dev", externalPostgres = false, workbenchRedis = false } = {}) {
  const resources = ["namespace.yaml", "services.yaml", "health-contract.yaml", "workloads.yaml", "deepseek-proxy.yaml"];
  if (!isRuntimeLane(profile)) resources.splice(1, 0, "code-agent-codex-config.yaml");
  if (isRuntimeLane(profile)) {
    if (externalPostgres) resources.push("external-postgres.yaml");
    else resources.push("postgres.yaml");
    if (workbenchRedis) resources.push("workbench-redis.yaml");
    resources.push("openfga.yaml", "observability.yaml");
  }
  if (includeDeviceAgent) resources.push("device-agent-71-freq.yaml");
  resources.push("node-frpc.yaml");
  return {
    apiVersion: "kustomize.config.k8s.io/v1beta1",
    kind: "Kustomization",
    namespace: namespaceNameForProfile(profile),
    resources
  };
}

function readme({ source, args }) {
  if (args.lane === "v02") {
    return `# HWLAB v0.2 GitOps CI/CD

This directory is generated by \`scripts/gitops-render.mjs --lane v02\` from source branch \`${args.sourceBranch}\`.

- Target: additive node-scoped v0.2 lane only.
- CI: Tekton Pipeline \`hwlab-ci/hwlab-v02-ci-image-publish\`.
- Git mirror/relay: v0.2 CI reads source/catalog from \`${args.gitReadUrl}\` and writes GitOps promotion to \`${args.gitWriteUrl}\`; canonical repo \`${args.sourceRepo}\` remains the source identity and manual flush upstream.
- Artifact contract: runtime images come from \`${args.catalogPath}\`; source branch \`v0.2\` does not track this generated catalog.
- Manual trigger: run \`bun scripts/cli.ts hwlab node control-plane trigger-current --lane v02 --confirm\` from UniDesk to create commit-pinned PipelineRun \`hwlab-v02-ci-poll-<short12>\` for the current \`origin/v0.2\` commit.
- Branch split: source branch \`${args.sourceBranch}\` remains human-authored source; generated desired state is promoted to local mirror branch \`${args.gitopsBranch}\`.
- CD: Argo CD Application \`argocd/hwlab-node-v02\` consumes \`${args.gitReadUrl}:${args.gitopsBranch}:deploy/gitops/node/runtime-v02\` and deploys only to namespace \`hwlab-v02\`.
- Public preview: FRP exposes v0.2 web \`${args.webEndpoint}\` / edge \`${args.runtimeEndpoint}\` through \`hwlab-v02/hwlab-v02-frpc\`.
- node DEV/PROD boundary: this lane does not modify archived DEV/PROD branches, \`hwlab-dev\`, \`hwlab-prod\`, 17666/17667 or 18666/18667.
- CronJob policy: v0.2 does not generate \`hwlab-v02-branch-poller\` or \`hwlab-v02-control-plane-reconciler\`; obsolete live CronJobs should be deleted by the UniDesk control-plane apply command.
- Gate policy: old DEV/D601/main gates do not enter this lane; new checks stay limited to the fixed branch, namespace, catalog, runtime path and Argo boundaries.
`;
  }
  return `# HWLAB node GitOps CI/CD

This directory is generated from built-in Tekton-native CI primitive declarations plus human-authored \`deploy/deploy.yaml\`, CI-authored \`deploy/artifact-catalog.dev.json\`, and \`deploy/k8s/*\` by \`scripts/gitops-render.mjs\`.

- Target: node k3s only.
- CI: Tekton Pipeline \`hwlab-ci/hwlab-node-ci-image-publish\`.
- Artifact contract: runtime images come from \`deploy/artifact-catalog.dev.json\`; \`deploy/deploy.yaml\` only carries human-authored config such as env and topology.
- Branch split: source branch \`${args.sourceBranch}\` remains the watched code branch; generated desired state is promoted to \`${args.gitopsBranch}\`.
- CD: Argo CD Applications \`argocd/hwlab-node-dev\` and \`argocd/hwlab-node-prod\` consume \`${args.gitopsBranch}:deploy/gitops/node/runtime-dev\` and \`runtime-prod\`.
- Public preview: FRP exposes node DEV web \`${args.webEndpoint}\` / edge \`${args.runtimeEndpoint}\` through \`hwlab-dev/hwlab-node-frpc\`, and node PROD web \`${args.prodWebEndpoint}\` / edge \`${args.prodRuntimeEndpoint}\` through \`hwlab-prod/hwlab-node-prod-frpc\`; D601 keeps \`:16666/:16667\`.
- Manual polling: run \`kubectl -n hwlab-ci create job --from=cronjob/hwlab-node-branch-poller hwlab-node-branch-poller-manual-$(date -u +%Y%m%d%H%M%S)\`; this reuses the same poller path and creates a commit-pinned Tekton PipelineRun only when needed.
- Control-plane reconcile: CronJob \`hwlab-ci/hwlab-node-control-plane-reconciler\` polls \`${args.sourceBranch}\`, runs \`scripts/gitops-render.mjs\`, and server-side-applies the generated Tekton RBAC/Pipeline/Poller/Reconciler manifests so CI control-plane changes do not require a manual render/apply step.
- D601 boundary: this path does not target D601, does not use UniDesk Code Queue, and does not change D601 production traffic.
- Concurrency: CI builds are per source commit and do not acquire the legacy DEV CD Lease; Argo CD reconciles the Git desired state.
`;
}

async function plannedFiles(args) {
  const [deploy, namespaceTemplate, config, services, health, workloads] = await Promise.all([
    readJson("deploy/deploy.yaml"),
    readJson("deploy/k8s/base/namespace.yaml"),
    readJson("deploy/k8s/base/code-agent-codex-config.yaml"),
    readJson("deploy/k8s/base/services.yaml"),
    readJson("deploy/k8s/dev/health-contract.yaml"),
    readJson("deploy/k8s/base/workloads.yaml")
  ]);
  args = applyRuntimeLaneDeployConfig(args, deploy, {
    defaultBranch,
    defaultGitopsBranch,
    defaultCatalogPath,
    defaultGitopsRoot: defaultOutDir,
    defaultRuntimeEndpoint,
    defaultWebEndpoint,
    defaultV02RuntimeEndpoint,
    defaultSourceRepo
  });
  const source = await resolveSourceRevision(args.sourceRevision);
  source.imageTag = imageTagForSource(args, source);
  let artifactCatalog = await readJsonIfPresent(args.catalogPath, null);
  if (!artifactCatalog && isRuntimeLane(args.lane)) artifactCatalog = artifactCatalogSkeleton({ args, deploy, source });
  if (!artifactCatalog) artifactCatalog = await readJson(args.catalogPath);
  const settings = ciLaneSettings(args);
  const profiles = laneRuntimeProfiles(args);
  const migrationSql = isRuntimeLane(args.lane)
    ? await readFile(path.join(repoRoot, "internal/db/migrations/0001_cloud_core_skeleton.sql"), "utf8")
    : null;
  const metricsSidecarScript = isRuntimeLane(args.lane)
    ? await readFile(path.join(repoRoot, "internal/dev-entrypoint/metrics-sidecar.mjs"), "utf8")
    : null;
  const metricsSidecarSha256 = metricsSidecarScript ? createHash("sha256").update(metricsSidecarScript).digest("hex") : null;
  const baseLabels = { "hwlab.pikastech.local/gitops-target": settings.gitopsTarget, "hwlab.pikastech.local/source-commit": source.full };
  const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
  const files = new Map();
  const putJson = (relative, value) => files.set(path.join(args.outDir, relative), jsonManifest(value));
  const putText = (relative, value) => files.set(path.join(args.outDir, relative), textFile(value));
  const publicEndpoints = Object.fromEntries(profiles.map((profile) => {
    const endpoints = profileEndpoint(args, profile);
    return [profile, { web: endpoints.webEndpoint, runtime: endpoints.runtimeEndpoint }];
  }));

  const sourceDescriptor = {
    kind: isRuntimeLane(args.lane) ? `hwlab-${args.lane}-gitops-source` : "hwlab-node-gitops-source",
    sourceCommit: source.full,
    sourceShortCommit: source.short,
    sourceImageTag: source.imageTag,
    sourceBranch: args.sourceBranch,
    gitopsBranch: args.gitopsBranch,
    lane: settings.lane,
    sourceRepo: args.sourceRepo,
    gitReadUrl: args.gitReadUrl,
    gitWriteUrl: args.gitWriteUrl,
    registryPrefix: args.registryPrefix,
    runtimePaths: profiles.map((profile) => gitopsPathForProfile(args, profile)),
    publicEndpoints,
    frpDeployments: Object.fromEntries(profiles.map((profile) => [profile, `${namespaceNameForProfile(profile)}/${isRuntimeLane(profile) ? `hwlab-${profile}-frpc` : profile === "prod" ? "hwlab-node-prod-frpc" : "hwlab-node-frpc"}`])),
    tektonPipeline: `hwlab-ci/${settings.pipelineName}`,
    argoApplications: profiles.map((profile) => `argocd/${argoApplicationName(profile)}`)
  };
  if (args.useDeployImages) {
    sourceDescriptor.renderMode = {
      imageSource: args.catalogPath,
      configSource: "deploy/deploy.yaml",
      mixedDesiredState: true
    };
  }
  putJson("source.json", sourceDescriptor);
  putText("README.md", readme({ source, args }));
  putJson("registry/registry.yaml", registryManifest());
  if (isRuntimeLane(args.lane)) putJson("devops-infra/git-mirror.yaml", devopsInfraGitMirrorManifest(args, deploy));
  putJson(`${settings.tektonDir}/rbac.yaml`, tektonRbac(args));
  putJson(`${settings.tektonDir}/pipeline.yaml`, tektonPipeline(args, deploy));
  if (!isRuntimeLane(args.lane)) {
    putJson(`${settings.tektonDir}/poller.yaml`, tektonPollerCronJob(args, deploy));
    putJson(`${settings.tektonDir}/control-plane-reconciler.yaml`, tektonControlPlaneReconcilerCronJob(args));
  }
  putJson(`${settings.tektonDir}/pipelinerun.sample.yaml`, tektonPipelineRunTemplate({ source, args }));
  putJson("argocd/project.yaml", argoProject(args));
  for (const profile of profiles) putJson(`argocd/application-${profile}.yaml`, argoApplication(args, profile));

  for (const profile of profiles) {
    const namespace = namespaceNameForProfile(profile);
    const includeDeviceAgent = profile === "dev";
    const externalPostgres = externalPostgresConfigForLane(deploy, profile);
    const workbenchRedis = workbenchRuntimeRedisConfigForProfile(deploy, profile);
    const profileLabels = { ...baseLabels, "hwlab.pikastech.local/environment": runtimeLabelForProfile(profile), "hwlab.pikastech.local/profile": runtimeLabelForProfile(profile) };
    const runtimeNamespace = cloneJson(namespaceTemplate);
    runtimeNamespace.metadata.name = namespace;
    label(runtimeNamespace.metadata, profileLabels);
    annotate(runtimeNamespace.metadata, annotations);
    const runtimePath = runtimePathForProfile(profile);
    const endpoints = profileEndpoint(args, profile);
    putJson(`${runtimePath}/kustomization.yaml`, runtimeKustomization({ profile, includeDeviceAgent, externalPostgres: Boolean(externalPostgres), workbenchRedis: Boolean(workbenchRedis) }));
    putJson(`${runtimePath}/namespace.yaml`, runtimeNamespace);
    if (!isRuntimeLane(profile)) putJson(`${runtimePath}/code-agent-codex-config.yaml`, transformListNamespace(config, namespace, profileLabels, annotations));
    putJson(`${runtimePath}/services.yaml`, transformServices({ services, namespace, labels: profileLabels, annotations, profile, deploy }));
    putJson(`${runtimePath}/health-contract.yaml`, transformHealthContract(health, namespace, profileLabels, annotations, endpoints.runtimeEndpoint, endpoints.webEndpoint, profile));
    putJson(`${runtimePath}/workloads.yaml`, transformWorkloads({ workloads, deploy, catalog: artifactCatalog, source, sourceBranch: args.sourceBranch, gitReadUrl: args.gitReadUrl, registryPrefix: args.registryPrefix, runtimeEndpoint: endpoints.runtimeEndpoint, webEndpoint: endpoints.webEndpoint, profile, useDeployImages: args.useDeployImages, metricsSidecarSha256 }));
    putJson(`${runtimePath}/deepseek-proxy.yaml`, deepSeekProxyManifest({ profile, source, sourceBranch: args.sourceBranch, sourceRepo: args.sourceRepo, gitReadUrl: args.gitReadUrl, deploy, registryPrefix: args.registryPrefix, catalog: artifactCatalog, useDeployImages: args.useDeployImages, metricsSidecarSha256 }));
    if (isRuntimeLane(profile) && externalPostgres) putJson(`${runtimePath}/external-postgres.yaml`, externalPostgresManifest({ profile, config: externalPostgres, source }));
    if (isRuntimeLane(profile) && !externalPostgres) putJson(`${runtimePath}/postgres.yaml`, v02PostgresManifest({ profile, migrationSql, source, image: runtimePostgresImageForProfile(deploy, profile) }));
    if (workbenchRedis) putJson(`${runtimePath}/workbench-redis.yaml`, workbenchRuntimeRedisManifest({ profile, config: workbenchRedis, source }));
    if (isRuntimeLane(profile)) putJson(`${runtimePath}/openfga.yaml`, v02OpenFgaManifest({ profile, source }));
    if (isRuntimeLane(profile)) putJson(`${runtimePath}/observability.yaml`, observabilityManifest({ deploy, profile, namespace, labels: profileLabels, annotations, metricsSidecarScript }));
    if (includeDeviceAgent) putJson(`${runtimePath}/device-agent-71-freq.yaml`, deviceAgent71FreqManifest({ profile, source, registryPrefix: args.registryPrefix, catalog: artifactCatalog, useDeployImages: args.useDeployImages }));
    putJson(`${runtimePath}/node-frpc.yaml`, nodeFrpcManifest({ profile, source }));
  }
  return { files, source };
}

async function writeFiles(files) {
  for (const [filePath, content] of files) {
    const absolutePath = generatedPath(filePath);
    await mkdir(path.dirname(absolutePath), { recursive: true });
    await writeFile(absolutePath, content);
  }
}

async function cleanStaleGeneratedOutput(args) {
  if (!isRuntimeLane(args.lane)) return;
  for (const relativePath of [`runtime-${args.lane}`, `tekton-${args.lane}`]) {
    await rm(generatedPath(path.join(args.outDir, relativePath)), { recursive: true, force: true });
  }
}

async function checkFiles(files) {
  const mismatches = [];
  for (const [filePath, expected] of files) {
    let actual = null;
    try {
      actual = await readFile(generatedPath(filePath), "utf8");
    } catch (error) {
      if (error?.code !== "ENOENT") throw error;
    }
    if (actual !== expected) mismatches.push(filePath);
  }
  return mismatches;
}

async function main() {
  let args = parseArgs(process.argv.slice(2));
  if (args.help) {
    console.log(usage());
    return;
  }
  ensureObject(args, "args");
  const { files, source } = await plannedFiles(args);
  if (args.check) {
    const mismatches = await checkFiles(files);
    console.log(JSON.stringify({ ok: mismatches.length === 0, sourceCommit: source.full, outDir: args.outDir, checked: files.size, mismatches }, null, 2));
    process.exitCode = mismatches.length === 0 ? 0 : 1;
    return;
  }
  if (args.write) {
    await cleanStaleGeneratedOutput(args);
    await writeFiles(files);
  }
  console.log(JSON.stringify({ ok: true, sourceCommit: source.full, sourceShort: source.short, outDir: args.outDir, files: [...files.keys()] }, null, 2));
}

main().catch((error) => {
  console.error(error.stack || error.message);
  process.exitCode = 1;
});
