import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { test } from "bun:test";

import { createHwpodNodeServer, executeHwpodNodeOpsPlan, resolveHwpodNodeCommand } from "./src/hwpod-node-lib.ts";

test("hwpod-node executes minimal workspace node ops", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-"));
  try {
    await writeFile(path.join(root, "main.c"), "int main(void) { return 0; }\n", "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_test",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [
        { opId: "op_01", op: "node.health", args: { workspacePath: root } },
        { opId: "op_02", op: "workspace.ls", args: { workspacePath: root, path: "." } },
        { opId: "op_03", op: "workspace.cat", args: { workspacePath: root, path: "main.c" } }
      ]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(result.ok, true);
    assert.equal(result.status, "completed");
    assert.equal(result.results[1].output.entries[0].name, "main.c");
    assert.match(result.results[2].output.content, /int main/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node searches workspace text without requiring host rg", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-rg-"));
  try {
    await mkdir(path.join(root, "Middlewares", "Arm-2D"), { recursive: true });
    await mkdir(path.join(root, "Objects"), { recursive: true });
    await writeFile(path.join(root, "Middlewares", "Arm-2D", "arm_2d.c"), "static int before;\nvoid arm_2d_init(void) {\n}\nstatic int after;\n", "utf8");
    await writeFile(path.join(root, "Objects", "ignored.txt"), "arm_2d_init should not be scanned\n", "utf8");

    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_rg",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{ opId: "op_rg", op: "workspace.rg", args: { workspacePath: root, pattern: "arm_2d_init", path: "Middlewares", context: 1 } }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    assert.equal(result.ok, true);
    assert.equal(result.results[0].ok, true);
    assert.equal(result.results[0].output.engine, "node-recursive-search");
    assert.equal(result.results[0].output.matchCount, 1);
    assert.ok(result.results[0].output.stdout.includes("Middlewares/Arm-2D/arm_2d.c-1-static int before"));
    assert.ok(result.results[0].output.stdout.includes("Middlewares/Arm-2D/arm_2d.c:2:void arm_2d_init"));
    assert.ok(result.results[0].output.stdout.includes("Middlewares/Arm-2D/arm_2d.c-3-}"));
    assert.equal(result.results[0].output.matches[0].line, 2);
    assert.equal(result.results[0].output.matches[0].before[0].line, 1);
    assert.equal(result.results[0].output.matches[0].after[0].line, 3);
    assert.equal(result.results[0].output.limits.beforeContext, 1);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node HTTP endpoint accepts hwpod-node-ops plans", async () => {
  const server = createHwpodNodeServer({ now: () => "2026-06-05T00:00:00.000Z", nodeId: "pc-host-1" });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
  try {
    const response = await fetch(`http://127.0.0.1:${server.address().port}/v1/hwpod-node-ops`, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        contractVersion: "hwpod-node-ops-v1",
        planId: "hwpod_plan_http",
        hwpodId: "hwpod-local",
        nodeId: "pc-host-1",
        ops: [{ opId: "op_01", op: "node.version", args: {} }]
      })
    });
    const payload = await response.json();
    assert.equal(response.status, 200);
    assert.equal(payload.ok, true);
    assert.equal(payload.specAuthority, "none");
    assert.equal(payload.results[0].op, "node.version");
  } finally {
    await new Promise((resolve, reject) => server.close((error: Error | undefined) => (error ? reject(error) : resolve(undefined))));
  }
});

test("hwpod-node executes debug ops only through explicit node-side command bindings", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-debug-"));
  try {
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_debug_bound",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{ opId: "op_build", op: "debug.build", args: { workspacePath: root, command: "printf build-ok > build.ok" } }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    assert.equal(result.ok, true);
    assert.equal(result.results[0].ok, true);
    assert.equal(result.results[0].output.bindingSource, "hwpod-node-ops.command");
    assert.match(await readFile(path.join(root, "build.ok"), "utf8"), /build-ok/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node executes debug commandRuns without shell splitting", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-debug-runs-"));
  try {
    const writer = path.join(root, "writer.js");
    await writeFile(writer, "const { writeFileSync } = require('node:fs'); writeFileSync(process.argv[2], process.argv.slice(3).join('|'));\n", "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_debug_runs",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{ opId: "op_download", op: "debug.download", args: { workspacePath: root, commandRuns: [{ command: process.execPath, argv: [writer, path.join(root, "args.txt"), "CherryUSB MicroLink CMSIS-DAP"] }] } }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    assert.equal(result.ok, true);
    assert.equal(result.results[0].ok, true);
    assert.equal(result.results[0].output.bindingSource, "hwpod-node-ops.commandRuns");
    assert.equal(result.results[0].output.commands[0].command.at(-1), "CherryUSB MicroLink CMSIS-DAP");
    assert.equal(await readFile(path.join(root, "args.txt"), "utf8"), "CherryUSB MicroLink CMSIS-DAP");
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node reports cmd.run non-zero exits as failed results", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-cmd-fail-"));
  try {
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_cmd_fail",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{ opId: "op_cmd", op: "cmd.run", args: { workspacePath: root, command: "sh", argv: ["-c", "echo no >&2; exit 7"] } }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    assert.equal(result.ok, false);
    assert.equal(result.results[0].ok, false);
    assert.equal(result.results[0].status, "failed");
    assert.equal(result.results[0].output.exitCode, 7);
    assert.equal(result.results[0].blocker.code, "hwpod_node_command_failed");
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node refuses plans targeting another node id", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-id-mismatch-"));
  try {
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_node_mismatch",
      hwpodId: "hwpod-local",
      nodeId: "node-d601-f103-v2",
      ops: [{ opId: "op_cmd", op: "cmd.run", args: { workspacePath: root, command: "sh", argv: ["-c", "echo must-not-run"] } }]
    }, { now: () => "2026-06-05T00:00:00.000Z", nodeId: "g14-host-hwpod-node" });

    assert.equal(result.ok, false);
    assert.equal(result.status, "blocked");
    assert.equal(result.localNodeId, "g14-host-hwpod-node");
    assert.equal(result.results[0].blocker.code, "hwpod_node_id_mismatch");
    assert.equal(result.results[0].blocker.details.requestedNodeId, "node-d601-f103-v2");
    assert.equal(result.results[0].blocker.details.localNodeId, "g14-host-hwpod-node");
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node exposes command spawn diagnostics when executable is missing", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-spawn-missing-"));
  try {
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_spawn_missing",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{ opId: "op_cmd", op: "cmd.run", args: { workspacePath: root, command: "hwlab-command-that-does-not-exist-1018", argv: ["--version"] } }]
    }, { now: () => "2026-06-05T00:00:00.000Z", nodeId: "pc-host-1" });

    assert.equal(result.ok, false);
    assert.equal(result.results[0].status, "blocked");
    assert.equal(result.results[0].blocker.code, "hwpod_node_command_spawn_failed");
    assert.equal(result.results[0].blocker.details.output.commandResolution.requested, "hwlab-command-that-does-not-exist-1018");
    assert.equal(result.results[0].blocker.details.output.spawnDiagnostics.platform, process.platform);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node includes structured UART diagnostics when platform blocks serial access", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-uart-"));
  try {
    const fixture = path.join(root, "serial-monitor-idle.mjs");
    await writeFile(fixture, `
const args = process.argv.slice(2).join(" ");
if (args === "monitor status") console.log(JSON.stringify({ action: "monitor_status", success: true, data: { isMonitoring: false, port: null, baudRate: null, lastPort: "COM9", lastBaudRate: 115200 } }));
else if (args === "ports") console.log(JSON.stringify({ action: "list_ports", success: true, data: { ports: [{ path: "COM9" }] } }));
else { console.error("unsupported " + args); process.exit(2); }
`, "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_uart_diag",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_uart",
        op: "io.uart.read",
        args: {
          workspacePath: root,
          port: "uart1",
          serialMonitorDir: root,
          serialMonitorCommand: [process.execPath, fixture],
          ioProbe: { uart: { id: "uart1", port: "COM9", baudrate: 115200 } }
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    if (process.platform === "win32") return;
    assert.equal(result.ok, false);
    assert.equal(result.results[0].status, "blocked");
    assert.equal(result.results[0].blocker.code, "hwpod_uart_monitor_not_active");
    assert.equal(result.results[0].blocker.details.requestedPort, "uart1");
    assert.equal(result.results[0].blocker.details.resolvedPort, "COM9");
    assert.equal(result.results[0].blocker.details.baudRate, 115200);
    assert.equal(result.results[0].blocker.details.serialMonitor.monitorStatus.data.isMonitoring, false);
    assert.match(result.results[0].blocker.details.serialMonitor.startCommand, /monitor start -p COM9 -b 115200/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node reads UART through serial-monitor binding", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-uart-active-"));
  try {
    const fixture = path.join(root, "serial-monitor-fixture.mjs");
    await writeFile(fixture, `
const args = process.argv.slice(2).join(" ");
if (args === "monitor status") console.log(JSON.stringify({ action: "monitor_status", success: true, data: { isMonitoring: true, port: "COM9", baudRate: 115200, startTime: "2026-06-06T10:00:00Z" } }));
else if (args === "ports") console.log(JSON.stringify({ action: "list_ports", success: true, data: { ports: [{ path: "COM9" }] } }));
else if (args.startsWith("fetch")) console.log(JSON.stringify({ action: "fetch_data", success: true, data: [{ timestamp: "2026-06-06T10:00:01Z", port: "COM9", data: "UART OK" }], count: 1, totalCount: 1, hasMore: false, truncated: false, sourceFile: "fixture.jsonl" }));
else { console.error("unsupported " + args); process.exit(2); }
`, "utf8");

    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_uart_read",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_uart",
        op: "io.uart.read",
        args: {
          workspacePath: root,
          port: "uart1",
          maxBytes: 128,
          serialMonitorDir: root,
          serialMonitorCommand: [process.execPath, fixture],
          ioProbe: { uart: { id: "uart1", port: "COM9", baudrate: 115200 } }
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });

    assert.equal(result.ok, true);
    assert.equal(result.results[0].status, "completed");
    assert.equal(result.results[0].output.bindingSource, "serial-monitor-cli");
    assert.equal(result.results[0].output.resolvedPort, "COM9");
    assert.equal(result.results[0].output.text, "UART OK");
    assert.deepEqual(result.results[0].output.command.slice(0, 2), [process.execPath, fixture]);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node resolves Git for Windows when service PATH omits git", async () => {
  const result = await resolveHwpodNodeCommand("git", {
    platform: "win32",
    env: {},
    fileExists: async (candidate: string) => candidate === "C:\\Program Files\\Git\\cmd\\git.exe"
  });

  assert.equal(result.command, "C:\\Program Files\\Git\\cmd\\git.exe");
  assert.equal(result.resolved, true);
  assert.equal(result.source, "windows-well-known-tool");
});

test("hwpod-node keeps explicit executable paths unchanged", async () => {
  const result = await resolveHwpodNodeCommand("C:\\Tools\\Git\\cmd\\git.exe", {
    platform: "win32",
    env: {},
    fileExists: async () => true
  });

  assert.equal(result.command, "C:\\Tools\\Git\\cmd\\git.exe");
  assert.equal(result.resolved, false);
  assert.equal(result.source, "explicit-path");
});

test("hwpod-node applies workspace patches through the stable node op", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-patch-"));
  try {
    await writeFile(path.join(root, "main.c"), "int value = 1;\n", "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_patch",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_patch",
        op: "workspace.apply-patch",
        args: {
          workspacePath: root,
          patch: [
            "*** Begin Patch",
            "*** Update File: main.c",
            "@@",
            "-int value = 1;",
            "+int value = 2;",
            "*** End Patch",
            ""
          ].join("\n")
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(result.ok, true);
    assert.equal(result.results[0].ok, true);
    assert.match(await readFile(path.join(root, "main.c"), "utf8"), /value = 2/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node preserves CRLF when applying workspace patches", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-patch-crlf-"));
  try {
    await writeFile(path.join(root, "main.c"), "int main(void) {\r\n  while (1) {\r\n  }\r\n}\r\n", "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_patch_crlf",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_patch",
        op: "workspace.apply-patch",
        args: {
          workspacePath: root,
          patch: [
            "*** Begin Patch",
            "*** Update File: main.c",
            "@@",
            "   while (1) {",
            "+    /* MARKER_OK */",
            "   }",
            "*** End Patch",
            ""
          ].join("\n")
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    const content = await readFile(path.join(root, "main.c"), "utf8");
    assert.equal(result.ok, true);
    assert.match(content, /\r\n  while \(1\) \{\r\n    \/\* MARKER_OK \*\/\r\n  \}\r\n/u);
    assert.doesNotMatch(content, /[^\r]\n/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node apply-patch accepts UniDesk v2 compatible unified headers and unprefixed context", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-patch-v2-"));
  try {
    await writeFile(path.join(root, "main.c"), [
      "#include <stdio.h>",
      "int main(void) {",
      "  printf(\"OLD\\r\\n\");",
      "  return 0;",
      "}",
      ""
    ].join("\n"), "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_patch_v2",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_patch",
        op: "workspace.apply-patch",
        args: {
          workspacePath: root,
          patch: [
            "*** Begin Patch",
            "*** Update File: main.c",
            "@@ -1,5 +1,6 @@",
            "#include <stdio.h>",
            "int main(void) {",
            "-  printf(\"OLD\\r\\n\");",
            "+  printf(\"NEW\\r\\n\");",
            "+  printf(\"TRACE\\r\\n\");",
            "  return 0;",
            "}",
            "*** End Patch",
            ""
          ].join("\n")
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    const content = await readFile(path.join(root, "main.c"), "utf8");
    assert.equal(result.ok, true);
    assert.equal(result.results[0].output.engine, "codex-apply-patch-v2-compatible");
    assert.match(result.results[0].output.hints.join("\n"), /unified-diff hunk header/u);
    assert.match(result.results[0].output.hints.join("\n"), /unprefixed Update File context line/u);
    assert.match(content, /printf\("NEW\\r\\n"\);/u);
    assert.match(content, /printf\("TRACE\\r\\n"\);/u);
    assert.doesNotMatch(content, /printf\("NEW\r\n"\);/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node apply-patch rejects raw unified diff with a precise format blocker", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-patch-raw-diff-"));
  try {
    await writeFile(path.join(root, "main.c"), "int value = 1;\n", "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_patch_raw_diff",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_patch",
        op: "workspace.apply-patch",
        args: {
          workspacePath: root,
          patch: [
            "--- a/main.c",
            "+++ b/main.c",
            "@@ -1 +1 @@",
            "-int value = 1;",
            "+int value = 2;",
            ""
          ].join("\n")
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(result.ok, false);
    assert.equal(result.results[0].blocker.code, "unsupported_apply_patch_format");
    assert.equal(result.results[0].blocker.details.engine, "codex-apply-patch-v2-compatible");
    assert.equal(result.results[0].blocker.details.format, "unified-diff");
    assert.match(result.results[0].blocker.summary, /Codex\/UniDesk apply_patch v2 envelope/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node returns apply-patch diagnostics when context is missing", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-patch-diagnostics-"));
  try {
    const original = "int main(void) {\r\n  while (1) {\r\n  }\r\n}\r\n";
    await writeFile(path.join(root, "main.c"), original, "utf8");
    const result = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_patch_diag",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_patch",
        op: "workspace.apply-patch",
        args: {
          workspacePath: root,
          patch: [
            "*** Begin Patch",
            "*** Update File: main.c",
            "@@",
            "-  while (2) {",
            "+  while (3) {",
            "*** End Patch",
            ""
          ].join("\n")
        }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(result.ok, false);
    assert.equal(result.results[0].blocker.code, "apply_patch_context_not_found");
    assert.equal(result.results[0].blocker.details.fileSha256, sha256(original));
    assert.equal(result.results[0].blocker.details.lineEnding, "\r\n");
    assert.equal(result.results[0].blocker.details.lineEndingCounts.crlf, 4);
    assert.equal(result.results[0].blocker.details.normalized, true);
    assert.match(result.results[0].blocker.details.nodeVersion, /thin-node-ops/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node edits CRLF workspaces with insert-after replace and write ops", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-text-edit-"));
  try {
    const filePath = path.join(root, "projects", "01_baseline", "User", "main.c");
    await mkdir(path.dirname(filePath), { recursive: true });
    await writeFile(filePath, "int main(void) {\r\n  while (1) {\r\n  }\r\n}\r\n", "utf8");
    const before = await readFile(filePath, "utf8");
    const insert = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_insert",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_insert",
        op: "workspace.insert-after",
        args: { workspacePath: root, path: "projects/01_baseline/User/main.c", anchor: "  while (1) {", line: "    /* MARKER_OK */", expectedSha: sha256(before) }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(insert.ok, true);
    assert.equal(insert.results[0].output.before.sha256, sha256(before));
    assert.equal(insert.results[0].output.after.lineEnding, "\r\n");
    assert.equal(insert.results[0].output.anchorMatch, "line-sequence");
    assert.deepEqual(insert.results[0].output.diff.preview, ["+    /* MARKER_OK */"]);
    const inserted = await readFile(filePath, "utf8");
    assert.match(inserted, /\r\n    \/\* MARKER_OK \*\/\r\n/u);
    assert.doesNotMatch(inserted, /[^\r]\n/u);

    const replace = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_replace",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_replace",
        op: "workspace.replace",
        args: { workspacePath: root, path: "projects/01_baseline/User/main.c", find: "    /* MARKER_OK */", replace: "    /* MARKER_REPLACED */", expectedSha: sha256(inserted) }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(replace.ok, true);
    assert.equal(replace.results[0].output.occurrences, 1);
    assert.match(await readFile(filePath, "utf8"), /MARKER_REPLACED/u);

    const dryRun = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_write_dry",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_write",
        op: "workspace.write",
        args: { workspacePath: root, path: "new.txt", content: "alpha\nbeta", lineEnding: "crlf", finalNewline: true, dryRun: true }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(dryRun.ok, true);
    assert.equal(dryRun.results[0].output.dryRun, true);
    assert.equal(dryRun.results[0].output.after.lineEnding, "\r\n");
    await assert.rejects(() => readFile(path.join(root, "new.txt"), "utf8"), /ENOENT/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node insert-after accepts a unique in-line source fragment anchor", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-fragment-anchor-"));
  try {
    const filePath = path.join(root, "projects", "01_baseline", "User", "main.c");
    await mkdir(path.dirname(filePath), { recursive: true });
    await writeFile(filePath, "void boot(void) {\r\n  printf(\"\\r\\n[D601-F103] device-pod LCD bring-up\\r\\n\");\r\n  lcd_init();\r\n}\r\n", "utf8");
    const before = await readFile(filePath, "utf8");
    const insert = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_insert_fragment",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_insert",
        op: "workspace.insert-after",
        args: { workspacePath: root, path: "projects/01_baseline/User/main.c", anchor: "device-pod LCD bring-up", line: "  printf(\"[D601-F103] marker\\r\\n\");", expectedSha: sha256(before) }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(insert.ok, true);
    assert.equal(insert.results[0].output.anchorLine, 2);
    assert.equal(insert.results[0].output.anchorMatch, "line-fragment");
    const inserted = await readFile(filePath, "utf8");
    assert.match(inserted, /device-pod LCD bring-up\\r\\n"\);\r\n  printf\("\[D601-F103\] marker\\r\\n"\);\r\n  lcd_init/u);
    assert.doesNotMatch(inserted, /[^\r]\n/u);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node insert-after keeps fragment anchors safe when ambiguous", async () => {
  const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-hwpod-node-fragment-ambiguous-"));
  try {
    const filePath = path.join(root, "main.c");
    await writeFile(filePath, "printf(\"device-pod LCD bring-up\");\nprintf(\"device-pod LCD bring-up again\");\n", "utf8");
    const before = await readFile(filePath, "utf8");
    const insert = await executeHwpodNodeOpsPlan({
      contractVersion: "hwpod-node-ops-v1",
      planId: "hwpod_plan_insert_ambiguous_fragment",
      hwpodId: "hwpod-local",
      nodeId: "pc-host-1",
      ops: [{
        opId: "op_insert",
        op: "workspace.insert-after",
        args: { workspacePath: root, path: "main.c", anchor: "device-pod LCD bring-up", line: "printf(\"marker\");", expectedSha: sha256(before) }
      }]
    }, { now: () => "2026-06-05T00:00:00.000Z" });
    assert.equal(insert.ok, false);
    assert.equal(insert.results[0].blocker.code, "workspace_insert_anchor_ambiguous");
    assert.equal(insert.results[0].blocker.details.anchorMatch, "line-fragment");
  } finally {
    await rm(root, { recursive: true, force: true });
  }
});

test("hwpod-node preserves Windows absolute workspace paths for PC-host nodes", async () => {
  const result = await executeHwpodNodeOpsPlan({
    contractVersion: "hwpod-node-ops-v1",
    planId: "hwpod_plan_windows_path",
    hwpodId: "d601-f103-v2",
    nodeId: "node-d601-f103-v2",
    ops: [{ opId: "op_01", op: "workspace.ls", args: { workspacePath: "F:\\Work\\D601-HWLAB", path: "." } }]
  }, { now: () => "2026-06-05T00:00:00.000Z" });

  assert.equal(result.ok, false);
  assert.equal(result.results[0].blocker.code, "ENOENT");
  assert.match(result.results[0].blocker.summary, /scandir 'F:\\Work\\D601-HWLAB'/u);
  assert.doesNotMatch(result.results[0].blocker.summary, /\/root\//u);
});

function sha256(content: string) {
  return createHash("sha256").update(content, "utf8").digest("hex");
}
