// SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-20-p2-terminal-outbox-recovery; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0.
// Responsibility: Cloud API AgentRun session/profile continuity regression tests.

import assert from "node:assert/strict";
import { createServer as createHttpServer } from "node:http";
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { test } from "bun:test";

import { createCloudApiServer } from "./server.ts";
import { createCloudRuntimeStore } from "../db/runtime-store.ts";
import { validateCodeAgentChatSchema } from "./code-agent-chat.ts";
import { createCodexStdioSessionManager } from "./codex-stdio-session.ts";
import { createCodeAgentTraceStore } from "./code-agent-trace-store.ts";
import { submitAgentRunChatTurn } from "./code-agent-agentrun-adapter.ts";
import {
  codexStdioChatFixture,
  codexStdioReadyFixture,
  createFakeAppServerClient,
  createFakeCodexCommand,
  createManualAgentSession,
  delay,
  ensureTestAgentAuth,
  pollAgentResult,
  postAgent,
  postAgentRaw,
  prepareFakeCodexHome
} from "./server-test-helpers.ts";

const TEST_AGENT_ACTOR = { id: "usr_agent_owner", username: "agent-owner", displayName: "Agent Owner", role: "user", status: "active" };
const TEST_AUTH_SESSION = { id: "auth_ses_agent_owner" };

function testAgentSessionRecord(input = {}) {
  const sessionId = input.sessionId ?? input.id;
  return {
    id: sessionId,
    sessionId,
    projectId: input.projectId ?? "pikasTech/HWLAB",
    agentId: input.agentId ?? "hwlab-code-agent",
    status: input.status ?? "idle",
    ownerUserId: input.ownerUserId ?? TEST_AGENT_ACTOR.id,
    ownerRole: input.ownerRole ?? TEST_AGENT_ACTOR.role,
    conversationId: input.conversationId ?? null,
    threadId: input.threadId ?? null,
    lastTraceId: input.traceId ?? input.lastTraceId ?? null,
    session: input.session ?? {},
    updatedAt: input.updatedAt ?? "2026-06-03T00:00:00.000Z"
  };
}

test("cloud api AgentRun adapter keeps AgentRun sessions scoped to HWLAB session across backend profile switches", async () => {
  const calls = [];
  const hwlabSessionId = "ses_server-test-profile-switch";
  const minimaxSessionId = "ses_agentrun_server_test_profile_switch";
  const ownerSessions = new Map([[hwlabSessionId, testAgentSessionRecord({
    sessionId: hwlabSessionId,
    conversationId: "cnv_server-test-profile-switch",
    threadId: "019e8078-db67-7750-a5d9-1a99f3abd445",
    traceId: "trc_existing_deepseek",
    status: "active",
    session: {
      agentRun: {
        adapter: "agentrun-v01",
        backendProfile: "deepseek",
        runId: "run_existing_deepseek",
        commandId: "cmd_existing_deepseek",
        jobName: "agentrun-v01-runner-existing-deepseek",
        namespace: "agentrun-v01",
        sessionId: "ses_agentrun_server_test_profile_switch",
        reuseEligible: true,
        managerUrl: "http://127.0.0.1:1",
        status: "runner-job-created"
      }
    }
  })]]);

  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    const chunks = [];
    for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
    const body = chunks.length ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : null;
    calls.push({ method: request.method, path: url.pathname, body });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_profile_switch" })}\n`);
    };
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_existing_deepseek") {
      response.writeHead(500, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: false, failureKind: "unexpected-reuse", message: "deepseek run must not be reused for minimax-m3" })}\n`);
      return;
    }
    if (request.method === "POST" && url.pathname === "/api/v1/runs") {
      assert.equal(body.backendProfile, "minimax-m3");
      assert.equal(body.sessionRef.sessionId, minimaxSessionId);
      assert.equal(body.sessionRef.threadId, undefined);
      assert.equal(body.sessionRef.metadata.hwlabSessionId, hwlabSessionId);
      assert.equal(body.sessionRef.metadata.agentRunSessionProfile, "minimax-m3");
      return send({ id: "run_hwlab_profile_switch_m3", status: "pending", backendProfile: "minimax-m3", sessionRef: body.sessionRef, resourceBundleRef: body.resourceBundleRef });
    }
    if (request.method === "POST" && url.pathname === "/api/v1/runs/run_hwlab_profile_switch_m3/commands") {
      assert.equal(body.payload.providerProfile, "minimax-m3");
      assert.equal(body.payload.sessionId, minimaxSessionId);
      assert.equal(body.payload.hwlabSessionId, hwlabSessionId);
      assert.equal(body.payload.threadId, null);
      assert.equal(body.dispatch?.kind, "kubernetes-job");
      assert.equal(body.dispatch?.input?.commandId, undefined);
      return send({
        id: "cmd_hwlab_profile_switch_m3",
        runId: "run_hwlab_profile_switch_m3",
        state: "pending",
        type: "turn",
        seq: 1,
        dispatchIntent: {
          id: "dispatch_hwlab_profile_switch_m3",
          state: "pending",
          runnerJobId: "rjob_hwlab_profile_switch_m3",
          attemptCount: 0,
          durable: true
        }
      });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_switch_m3/commands") {
      return send({ items: [
        { id: "cmd_hwlab_profile_switch_m3", runId: "run_hwlab_profile_switch_m3", state: "completed", type: "turn", seq: 1, idempotencyKey: "trc_server-test-agentrun-profile-switch", payload: { traceId: "trc_server-test-agentrun-profile-switch", conversationId: "cnv_server-test-profile-switch", hwlabSessionId, threadId: "019e8078-db67-7750-a5d9-1a99f3abd445", providerProfile: "minimax-m3" } }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_switch_m3/events") {
      return send({ items: [
        { id: "evt_profile_switch_1", runId: "run_hwlab_profile_switch_m3", seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: "cmd_hwlab_profile_switch_m3", attemptId: "attempt_hwlab_profile_switch_m3", jobName: "agentrun-v01-runner-profile-switch-m3", namespace: "agentrun-v01" }, createdAt: "2026-06-02T00:00:00.000Z" },
        { id: "evt_profile_switch_2", runId: "run_hwlab_profile_switch_m3", seq: 2, type: "assistant_message", payload: { commandId: "cmd_hwlab_profile_switch_m3", text: "AGENTRUN_HWLAB_MINIMAX_M3_OK" }, createdAt: "2026-06-02T00:00:01.000Z" },
        { id: "evt_profile_switch_3", runId: "run_hwlab_profile_switch_m3", seq: 3, type: "terminal_status", payload: { commandId: "cmd_hwlab_profile_switch_m3", terminalStatus: "completed" }, createdAt: "2026-06-02T00:00:02.000Z" }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_switch_m3/commands/cmd_hwlab_profile_switch_m3/result") {
      return send({
        runId: "run_hwlab_profile_switch_m3",
        commandId: "cmd_hwlab_profile_switch_m3",
        attemptId: "attempt_hwlab_profile_switch_m3",
        runnerId: "runner_hwlab_profile_switch_m3",
        jobName: "agentrun-v01-runner-profile-switch-m3",
        namespace: "agentrun-v01",
        status: "completed",
        runStatus: "completed",
        commandState: "completed",
        terminalStatus: "completed",
        completed: true,
        messageId: "msg_profile_switch_m3",
        reply: "AGENTRUN_HWLAB_MINIMAX_M3_OK",
        lastSeq: 3,
        eventCount: 3,
        sessionRef: { sessionId: minimaxSessionId, conversationId: "cnv_server-test-profile-switch", threadId: "019e8078-db67-7750-a5d9-1a99f3abd445" }
      });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, failureKind: "schema-invalid", message: `unexpected ${request.method} ${url.pathname}`, traceId: "trc_fake_profile_switch" })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  const server = createCloudApiServer({
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567",
      HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "deepseek",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async recordAgentSessionOwner(input) {
        const record = testAgentSessionRecord(input);
        ownerSessions.set(record.id, record);
        return record;
      },
      async getAgentSession(sessionId) {
        return ownerSessions.get(sessionId) ?? null;
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const traceId = "trc_server-test-agentrun-profile-switch";
    const submit = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
      method: "POST",
      headers: { "content-type": "application/json", "x-trace-id": traceId, cookie: "hwlab_session=test-stub-session" },
      body: JSON.stringify({
        conversationId: "cnv_server-test-profile-switch",
        sessionId: hwlabSessionId,
        ownerUserId: "usr_agent_owner",
        ownerRole: "user",
        threadId: "019e8078-db67-7750-a5d9-1a99f3abd445",
        providerProfile: "minimax-m3",
        message: "Switch this HWLAB session to MiniMax-M3 through AgentRun"
      })
    });
    assert.equal(submit.status, 202);

    const payload = await pollAgentResult(port, traceId);
    assert.equal(payload.status, "completed");
    assert.equal(payload.sessionId, hwlabSessionId);
    assert.equal(payload.agentRun.backendProfile, "minimax-m3");
    assert.equal(payload.agentRun.runId, "run_hwlab_profile_switch_m3");
    assert.equal(payload.agentRun.sessionId, minimaxSessionId);
    assert.equal(calls.some((call) => call.method === "GET" && call.path === "/api/v1/runs/run_existing_deepseek"), false);
    assert.equal(calls.filter((call) => call.method === "POST" && call.path === "/api/v1/runs").length, 1);
    const stored = ownerSessions.get(hwlabSessionId);
    assert.equal(stored.session.providerProfile, "minimax-m3");
    assert.equal(stored.session.agentRun.backendProfile, "minimax-m3");
    assert.equal(stored.session.agentRun.sessionId, minimaxSessionId);
    assert.equal(calls.some((call) => call.path.endsWith("/runner-jobs")), false);
  } finally {
    await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
    await new Promise((resolve, reject) => agentRunServer.close((error) => (error ? reject(error) : resolve())));
  }
});

test("cloud api AgentRun adapter starts a fresh AgentRun session after a failed stale continuation when provider changes", async () => {
  const calls = [];
  const hwlabSessionId = "ses_server-test-stale-continuation-switch";
  const conversationId = "cnv_server-test-stale-continuation-switch";
  const staleThreadId = "thread_stale_bad_model";
  const ownerSessions = new Map([[hwlabSessionId, testAgentSessionRecord({
    sessionId: hwlabSessionId,
    conversationId,
    threadId: staleThreadId,
    traceId: "trc_stale_bad_model",
    status: "thread-resume-failed",
    session: {
      providerProfile: "codex-api",
      codeAgentProviderProfile: "codex-api",
      continuation: {
        requiresFreshSession: true,
        reasonCode: "provider-stream-disconnected",
        staleThreadId,
        traceId: "trc_stale_bad_model",
        valuesRedacted: true
      },
      agentRun: {
        adapter: "agentrun-v01",
        backendProfile: "codex-api",
        runId: "run_stale_bad_model",
        commandId: "cmd_stale_bad_model",
        sessionId: "ses_agentrun_stale_bad_model",
        threadId: staleThreadId,
        terminalStatus: "failed",
        reuseEligible: false
      }
    }
  })]]);

  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    const chunks = [];
    for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
    const body = chunks.length ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : null;
    calls.push({ method: request.method, path: url.pathname, body });
    const send = (data, status = 200) => {
      response.writeHead(status, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: status < 400, data, traceId: "trc_fake_stale_continuation_switch" })}\n`);
    };
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_stale_bad_model") {
      return send({ message: "stale run must not be reused after provider switch" }, 500);
    }
    if (request.method === "POST" && url.pathname === "/api/v1/sessions") {
      assert.match(body.sessionId, /-reset-/u);
      assert.equal(body.backendProfile, "dsflash-go");
      return send({ sessionId: body.sessionId, backendProfile: body.backendProfile });
    }
    if (request.method === "POST" && url.pathname === "/api/v1/runs") {
      assert.equal(body.backendProfile, "dsflash-go");
      assert.match(body.sessionRef?.sessionId, /-reset-/u);
      assert.equal(body.sessionRef?.threadId, undefined);
      assert.equal(body.sessionRef?.metadata?.hwlabSessionId, hwlabSessionId);
      assert.equal(body.sessionRef?.metadata?.agentRunSessionProfile, "dsflash-go");
      return send({ id: "run_stale_recovery_dsflash", status: "pending", backendProfile: "dsflash-go", sessionRef: body.sessionRef, resourceBundleRef: body.resourceBundleRef });
    }
    if (request.method === "POST" && url.pathname === "/api/v1/runs/run_stale_recovery_dsflash/commands") {
      assert.equal(body.payload.providerProfile, "dsflash-go");
      assert.match(body.payload.sessionId, /-reset-/u);
      assert.equal(body.payload.hwlabSessionId, hwlabSessionId);
      assert.equal(body.payload.threadId, null);
      assert.equal(body.dispatch?.kind, "kubernetes-job");
      assert.equal(body.dispatch?.input?.commandId, undefined);
      return send({
        id: "cmd_stale_recovery_dsflash",
        runId: "run_stale_recovery_dsflash",
        state: "pending",
        type: "turn",
        seq: 1,
        dispatchIntent: {
          id: "dispatch_stale_recovery_dsflash",
          state: "pending",
          runnerJobId: "rjob_stale_recovery_dsflash",
          attemptCount: 0,
          durable: true
        }
      });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_stale_recovery_dsflash/commands") {
      return send({ items: [
        { id: "cmd_stale_recovery_dsflash", runId: "run_stale_recovery_dsflash", state: "completed", type: "turn", seq: 1, idempotencyKey: "trc_server-test-stale-continuation-switch", payload: { traceId: "trc_server-test-stale-continuation-switch", conversationId, hwlabSessionId, threadId: "thread_recovered_dsflash", providerProfile: "dsflash-go" } }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_stale_recovery_dsflash/events") {
      return send({ items: [
        { id: "evt_stale_recovery_1", runId: "run_stale_recovery_dsflash", seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: "cmd_stale_recovery_dsflash" }, createdAt: "2026-06-30T00:00:00.000Z" },
        { id: "evt_stale_recovery_2", runId: "run_stale_recovery_dsflash", seq: 2, type: "assistant_message", payload: { commandId: "cmd_stale_recovery_dsflash", text: "AGENTRUN_STALE_RECOVERY_OK", final: true, replyAuthority: true }, createdAt: "2026-06-30T00:00:01.000Z" },
        { id: "evt_stale_recovery_3", runId: "run_stale_recovery_dsflash", seq: 3, type: "terminal_status", payload: { commandId: "cmd_stale_recovery_dsflash", terminalStatus: "completed" }, createdAt: "2026-06-30T00:00:02.000Z" }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_stale_recovery_dsflash/commands/cmd_stale_recovery_dsflash/result") {
      return send({
        runId: "run_stale_recovery_dsflash",
        commandId: "cmd_stale_recovery_dsflash",
        attemptId: "attempt_stale_recovery_dsflash",
        runnerId: "runner_stale_recovery_dsflash",
        jobName: "agentrun-v01-runner-stale-recovery-dsflash",
        namespace: "agentrun-v01",
        status: "completed",
        runStatus: "completed",
        commandState: "completed",
        terminalStatus: "completed",
        completed: true,
        reply: "AGENTRUN_STALE_RECOVERY_OK",
        lastSeq: 3,
        eventCount: 3,
        sessionRef: { sessionId: calls.find((call) => call.method === "POST" && call.path === "/api/v1/runs")?.body?.sessionRef?.sessionId, conversationId, threadId: "thread_recovered_dsflash" }
      });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, failureKind: "schema-invalid", message: `unexpected ${request.method} ${url.pathname}`, traceId: "trc_fake_stale_continuation_switch" })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  const server = createCloudApiServer({
    traceStore: createCodeAgentTraceStore(),
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "JD01",
      HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567",
      HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "codex-api",
      HWLAB_ENVIRONMENT: "v03",
      HWLAB_GITOPS_PROFILE: "v03"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async recordAgentSessionOwner(input) {
        const previous = ownerSessions.get(input.sessionId) ?? null;
        const record = testAgentSessionRecord({
          ...(previous ?? {}),
          ...input,
          threadId: input.threadId ?? previous?.threadId ?? null,
          session: { ...(previous?.session ?? {}), ...(input.session ?? {}) }
        });
        ownerSessions.set(record.id, record);
        return record;
      },
      async getAgentSession(sessionId) {
        return ownerSessions.get(sessionId) ?? null;
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const traceId = "trc_server-test-stale-continuation-switch";
    const submit = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
      method: "POST",
      headers: { "content-type": "application/json", "x-trace-id": traceId, cookie: "hwlab_session=test-stub-session" },
      body: JSON.stringify({
        conversationId,
        sessionId: hwlabSessionId,
        ownerUserId: "usr_agent_owner",
        ownerRole: "user",
        threadId: staleThreadId,
        providerProfile: "dsflash-go",
        message: "Continue after the first model failed"
      })
    });
    assert.equal(submit.status, 202);

    const payload = await pollAgentResult(port, traceId);
    assert.equal(payload.status, "completed");
    assert.equal(payload.finalResponse?.text ?? payload.reply?.content, "AGENTRUN_STALE_RECOVERY_OK");
    assert.equal(payload.agentRun.backendProfile, "dsflash-go");
    assert.match(payload.agentRun.sessionId, /-reset-/u);
    assert.equal(calls.some((call) => call.method === "GET" && call.path === "/api/v1/runs/run_stale_bad_model"), false);
    assert.equal(calls.filter((call) => call.method === "POST" && call.path === "/api/v1/runs").length, 1);
    const commandCall = calls.find((call) => call.method === "POST" && call.path === "/api/v1/runs/run_stale_recovery_dsflash/commands");
    assert.equal(commandCall.body.payload.threadId, null);
    const stored = ownerSessions.get(hwlabSessionId);
    assert.equal(stored.status, "completed");
    assert.equal(stored.threadId, "thread_recovered_dsflash");
    assert.equal(stored.session.providerProfile, "dsflash-go");
    assert.equal(stored.session.continuation.requiresFreshSession, false);
    assert.equal(calls.some((call) => call.path.endsWith("/runner-jobs")), false);
  } finally {
    await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
    await new Promise((resolve, reject) => agentRunServer.close((error) => (error ? reject(error) : resolve())));
  }
});

test("cloud api AgentRun adapter inherits session provider profile when a recovered Workbench page omits it", async () => {
  const calls = [];
  const hwlabSessionId = "ses_server-test-profile-inherit";
  const agentRunSessionId = "ses_agentrun_server_test_profile_inherit";
  const conversationId = "cnv_server-test-profile-inherit";
  const threadId = "019e8078-db67-7750-a5d9-1a99f3abd446";
  const ownerSessions = new Map([[hwlabSessionId, testAgentSessionRecord({
    sessionId: hwlabSessionId,
    conversationId,
    threadId,
    traceId: "trc_existing_dsflash_go",
    status: "active",
    session: {
      providerProfile: "dsflash-go",
      codeAgentProviderProfile: "dsflash-go",
      agentRun: {
        adapter: "agentrun-v01",
        backendProfile: "dsflash-go",
        runId: "run_existing_dsflash_go",
        commandId: "cmd_existing_dsflash_go",
        sessionId: agentRunSessionId,
        terminalStatus: "completed",
        reuseEligible: false
      }
    }
  })]]);

  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    const chunks = [];
    for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
    const body = chunks.length ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : null;
    calls.push({ method: request.method, path: url.pathname, body });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_profile_inherit" })}\n`);
    };
    if (request.method === "POST" && url.pathname === "/api/v1/runs") {
      assert.equal(body.backendProfile, "dsflash-go");
      assert.equal(body.sessionRef.sessionId, agentRunSessionId);
      assert.equal(body.sessionRef.metadata.hwlabSessionId, hwlabSessionId);
      assert.equal(body.sessionRef.metadata.agentRunSessionProfile, "dsflash-go");
      return send({ id: "run_hwlab_profile_inherit", status: "pending", backendProfile: "dsflash-go", sessionRef: body.sessionRef, resourceBundleRef: body.resourceBundleRef });
    }
    if (request.method === "POST" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands") {
      assert.equal(body.payload.providerProfile, "dsflash-go");
      assert.equal(body.payload.sessionId, agentRunSessionId);
      assert.equal(body.payload.hwlabSessionId, hwlabSessionId);
      assert.equal(body.payload.threadId, null);
      assert.equal(body.dispatch?.kind, "kubernetes-job");
      assert.equal(body.dispatch?.input?.commandId, undefined);
      return send({
        id: "cmd_hwlab_profile_inherit",
        runId: "run_hwlab_profile_inherit",
        state: "pending",
        type: "turn",
        seq: 1,
        dispatchIntent: {
          id: "dispatch_hwlab_profile_inherit",
          state: "pending",
          runnerJobId: "rjob_hwlab_profile_inherit",
          attemptCount: 0,
          durable: true
        }
      });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands") {
      return send({ items: [
        { id: "cmd_hwlab_profile_inherit", runId: "run_hwlab_profile_inherit", state: "completed", type: "turn", seq: 1, idempotencyKey: "trc_server-test-agentrun-profile-inherit", payload: { traceId: "trc_server-test-agentrun-profile-inherit", conversationId, hwlabSessionId, threadId, providerProfile: "dsflash-go" } }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/events") {
      return send({ items: [
        { id: "evt_profile_inherit_1", runId: "run_hwlab_profile_inherit", seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: "cmd_hwlab_profile_inherit", attemptId: "attempt_hwlab_profile_inherit", jobName: "agentrun-v01-runner-profile-inherit", namespace: "agentrun-v01" }, createdAt: "2026-06-02T00:00:00.000Z" },
        { id: "evt_profile_inherit_2", runId: "run_hwlab_profile_inherit", seq: 2, type: "assistant_message", payload: { commandId: "cmd_hwlab_profile_inherit", text: "AGENTRUN_DSFLASH_GO_OK" }, createdAt: "2026-06-02T00:00:01.000Z" },
        { id: "evt_profile_inherit_3", runId: "run_hwlab_profile_inherit", seq: 3, type: "terminal_status", payload: { commandId: "cmd_hwlab_profile_inherit", terminalStatus: "completed" }, createdAt: "2026-06-02T00:00:02.000Z" }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands/cmd_hwlab_profile_inherit/result") {
      return send({
        runId: "run_hwlab_profile_inherit",
        commandId: "cmd_hwlab_profile_inherit",
        attemptId: "attempt_hwlab_profile_inherit",
        runnerId: "runner_hwlab_profile_inherit",
        jobName: "agentrun-v01-runner-profile-inherit",
        namespace: "agentrun-v01",
        status: "completed",
        runStatus: "completed",
        commandState: "completed",
        terminalStatus: "completed",
        completed: true,
        messageId: "msg_profile_inherit",
        reply: "AGENTRUN_DSFLASH_GO_OK",
        lastSeq: 3,
        eventCount: 3,
        sessionRef: { sessionId: agentRunSessionId, conversationId, threadId }
      });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, failureKind: "schema-invalid", message: `unexpected ${request.method} ${url.pathname}`, traceId: "trc_fake_profile_inherit" })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  const server = createCloudApiServer({
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567",
      HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "codex",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async recordAgentSessionOwner(input) {
        const previous = ownerSessions.get(input.sessionId)?.session ?? {};
        const record = testAgentSessionRecord({ ...input, session: { ...previous, ...(input.session ?? {}) } });
        ownerSessions.set(record.id, record);
        return record;
      },
      async getAgentSession(sessionId) {
        return ownerSessions.get(sessionId) ?? null;
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const traceId = "trc_server-test-agentrun-profile-inherit";
    const submit = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
      method: "POST",
      headers: { "content-type": "application/json", "x-trace-id": traceId, cookie: "hwlab_session=test-stub-session" },
      body: JSON.stringify({
        conversationId,
        sessionId: hwlabSessionId,
        ownerUserId: "usr_agent_owner",
        ownerRole: "user",
        message: "Continue with the Workbench session provider profile"
      })
    });
    assert.equal(submit.status, 202);

    const payload = await pollAgentResult(port, traceId);
    assert.equal(payload.status, "completed");
    assert.equal(payload.agentRun.backendProfile, "dsflash-go");
    assert.equal(calls.filter((call) => call.method === "POST" && call.path === "/api/v1/runs").length, 1);
    const stored = ownerSessions.get(hwlabSessionId);
    assert.equal(stored.session.providerProfile, "dsflash-go");
    assert.equal(stored.session.agentRun.backendProfile, "dsflash-go");
    assert.equal(calls.some((call) => call.path.endsWith("/runner-jobs")), false);
  } finally {
    await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
    await new Promise((resolve, reject) => agentRunServer.close((error) => (error ? reject(error) : resolve())));
  }
});

test("cloud api AgentRun adapter rejects non-internal manager URLs by default", async () => {
  const server = createCloudApiServer({
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      AGENTRUN_MGR_URL: "http://74.48.78.17:8080"
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const manualSession = await createManualAgentSession(port, {
      conversationId: "cnv_server-test-agentrun-public-url"
    });
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
      method: "POST",
      headers: { "content-type": "application/json", "x-trace-id": "trc_server-test-agentrun-public-url", cookie: manualSession.cookie },
      body: JSON.stringify({ conversationId: manualSession.conversationId, sessionId: manualSession.sessionId, message: "must reject public manager url" })
    });
    assert.equal(response.status, 202);
    const body = await response.json();
    assert.equal(body.accepted, true);
    const result = await pollAgentResult(port, "trc_server-test-agentrun-public-url");
    assert.equal(result.status, "failed");
    assert.match(JSON.stringify(result), /internal k3s Service DNS/u);
  } finally {
    await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
  }
});

test("cloud api /v1/agent/chat records authenticated owner on agent session", async () => {
  const workspace = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-owner-"));
  const codexHome = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-owner-codex-home-"));
  const ownerRecords = [];
  const ownerSessions = new Map([["ses_server-test-owner", testAgentSessionRecord({
    sessionId: "ses_server-test-owner",
    conversationId: "cnv_server-test-owner",
    status: "idle"
  })]]);
  const server = createCloudApiServer({
    env: {
      PATH: process.env.PATH,
      CODEX_HOME: codexHome,
      HWLAB_CODE_AGENT_CODEX_WORKSPACE: workspace,
      HWLAB_CODE_AGENT_CODEX_SANDBOX: "danger-full-access",
      HWLAB_CODE_AGENT_PROVIDER: "codex-stdio",
      HWLAB_CODE_AGENT_MODEL: "gpt-test",
      OPENAI_API_KEY: "test-openai-key-material",
      HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://127.0.0.1:65535/v1/responses"
    },
    accessController: {
      required: true,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async recordAgentSessionOwner(input) {
        const record = testAgentSessionRecord(input);
        ownerRecords.push(input);
        ownerSessions.set(record.id, record);
        return record;
      },
      async getAgentSession(sessionId) {
        return ownerSessions.get(sessionId) ?? null;
      }
    },
    codexStdioManager: {
      describe() { return { ...codexStdioReadyFixture({ workspace, codexHome }), sandbox: "danger-full-access" }; },
      async probe() { return { ...codexStdioReadyFixture({ workspace, codexHome }), sandbox: "danger-full-access" }; },
      async chat(params = {}) {
        return {
          ...codexStdioChatFixture({ workspace, codexHome, params }),
          sandbox: "danger-full-access"
        };
      },
      cancel() {},
      reapIdle() {}
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const payload = await postAgent(port, {
      conversationId: "cnv_server-test-owner",
      sessionId: "ses_server-test-owner",
      traceId: "trc_server-test-owner",
      message: "owner binding smoke"
    });
    validateCodeAgentChatSchema(payload);
    assert.equal(payload.ownerUserId, "usr_agent_owner");
    assert.equal(ownerRecords.length, 2);
    assert.equal(ownerRecords[0].status, "running");
    const terminalOwnerRecord = ownerRecords.at(-1);
    assert.equal(terminalOwnerRecord.ownerUserId, "usr_agent_owner");
    assert.equal(terminalOwnerRecord.sessionId, "ses_server_stdio_pwd");
    assert.equal(terminalOwnerRecord.conversationId, "cnv_server-test-owner");
    assert.equal(terminalOwnerRecord.traceId, "trc_server-test-owner");
    assert.equal(terminalOwnerRecord.status, "completed");
    assert.equal(terminalOwnerRecord.session.messageCount, 2);
    assert.equal(terminalOwnerRecord.session.messages.length, 2);
    assert.equal(terminalOwnerRecord.session.messages[0].role, "user");
    assert.equal(terminalOwnerRecord.session.messages[0].text, "owner binding smoke");
    assert.equal(terminalOwnerRecord.session.messages[0].status, "sent");
    assert.equal(terminalOwnerRecord.session.messages[1].role, "agent");
    assert.equal(terminalOwnerRecord.session.messages[1].status, "completed");
    assert.equal(terminalOwnerRecord.session.messages[1].traceId, "trc_server-test-owner");
    assert.equal(terminalOwnerRecord.session.firstUserMessagePreview, "owner binding smoke");
    assert.equal(terminalOwnerRecord.session.valuesRedacted, true);
    assert.equal(JSON.stringify(ownerRecords).includes("test-openai-key-material"), false);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await rm(workspace, { recursive: true, force: true });
    await rm(codexHome, { recursive: true, force: true });
  }
});

test("cloud api /v1/agent/chat/inspect maps conversation session and thread details to trace evidence", async () => {
  const workspace = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-inspect-"));
  const codexHome = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-inspect-codex-home-"));
  const server = createCloudApiServer({
    env: {
      PATH: process.env.PATH,
      CODEX_HOME: codexHome,
      HWLAB_CODE_AGENT_CODEX_WORKSPACE: workspace,
      HWLAB_CODE_AGENT_CODEX_SANDBOX: "danger-full-access",
      HWLAB_CODE_AGENT_PROVIDER: "codex-stdio",
      HWLAB_CODE_AGENT_MODEL: "gpt-test",
      OPENAI_API_KEY: "test-openai-key-material",
      HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://127.0.0.1:65535/v1/responses"
    },
    codexStdioManager: {
      describe() {
        return {
          ...codexStdioReadyFixture({ workspace, codexHome }),
          sandbox: "danger-full-access",
          recentSessions: [{
            sessionId: "ses_server_stdio_pwd",
            conversationId: "cnv_server-test-inspect",
            threadId: "019e6c72-2373-75e3-9856-eff286db7163",
            status: "idle",
            currentTraceId: null,
            lastTraceId: "trc_server-test-inspect",
            workspace,
            sandbox: "danger-full-access",
            secretMaterialStored: false,
            valuesRedacted: true
          }]
        };
      },
      async probe() {
        return {
          ...codexStdioReadyFixture({ workspace, codexHome }),
          sandbox: "danger-full-access"
        };
      },
      async chat(params = {}) {
        const base = codexStdioChatFixture({ workspace, codexHome, params });
        return {
          ...base,
          sandbox: "danger-full-access",
          session: {
            ...base.session,
            threadId: "019e6c72-2373-75e3-9856-eff286db7163",
            sandbox: "danger-full-access"
          },
          sessionReuse: {
            ...base.sessionReuse,
            threadId: "019e6c72-2373-75e3-9856-eff286db7163"
          }
        };
      },
      get(sessionId) {
        if (sessionId !== "ses_server_stdio_pwd") return null;
        return {
          sessionId,
          conversationId: "cnv_server-test-inspect",
          threadId: "019e6c72-2373-75e3-9856-eff286db7163",
          status: "idle",
          lastTraceId: "trc_server-test-inspect",
          workspace,
          sandbox: "danger-full-access",
          secretMaterialStored: false,
          valuesRedacted: true
        };
      },
      cancel() {},
      reapIdle() {}
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const traceId = "trc_server-test-inspect";
    const manualSession = await createManualAgentSession(port, {
      conversationId: "cnv_server-test-inspect"
    });
    const submit = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
      method: "POST",
      headers: {
        "content-type": "application/json",
        cookie: manualSession.cookie,
        "x-trace-id": traceId,
        "prefer": "respond-async",
        "x-hwlab-short-connection": "1"
      },
      body: JSON.stringify({
        conversationId: manualSession.conversationId,
        sessionId: manualSession.sessionId,
        message: "inspect mapping smoke"
      })
    });
    assert.equal(submit.status, 202);
    const payload = await pollAgentResult(port, traceId);
    assert.equal(payload.status, "completed");

    const inspect = await fetch(`http://127.0.0.1:${port}/v1/agent/chat/inspect?conversationId=cnv_server-test-inspect&sessionId=${manualSession.sessionId}&threadId=019e6c72-2373-75e3-9856-eff286db7163`);
    assert.equal(inspect.status, 200);
    const body = await inspect.json();
    assert.equal(body.ok, true);
    assert.equal(body.status, "found");
    assert.equal(body.latestTraceId, traceId);
    assert.equal(body.traceUrl, `/v1/agent/traces/${traceId}`);
    assert.equal(body.resultUrl, `/v1/agent/chat/result/${traceId}`);
    assert.equal(body.query.sessionId, manualSession.sessionId);
    assert.equal(body.query.threadId, "019e6c72-2373-75e3-9856-eff286db7163");
    assert.equal(body.session.sessionId, "ses_server_stdio_pwd");
    assert.equal(body.session.threadId, "019e6c72-2373-75e3-9856-eff286db7163");
    assert.equal(body.conversationFacts.conversationId, "cnv_server-test-inspect");
    assert.equal(body.runnerTrace.traceId, traceId);
    assert.equal(body.valuesRedacted, true);
    assert.equal(body.secretMaterialStored, false);
    assert.equal(JSON.stringify(body).includes("test-openai-key-material"), false);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await rm(workspace, { recursive: true, force: true });
    await rm(codexHome, { recursive: true, force: true });
  }
});

test("cloud api /v1/agent/chat/inspect returns not_found for empty conversation facts", async () => {
  const server = createCloudApiServer();
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat/inspect?conversationId=cnv_server-test-inspect-missing&sessionId=ses_server_test_missing&threadId=019e6c72-2373-75e3-9856-eff286db7163&traceId=trc_server_test_missing`);
    assert.equal(response.status, 404);
    const body = await response.json();
    assert.equal(body.ok, false);
    assert.equal(body.status, "not_found");
    assert.equal(body.latestTraceId, null);
    assert.deepEqual(body.traceIds, []);
    assert.equal(body.traceUrl, null);
    assert.equal(body.resultUrl, null);
    assert.equal(body.conversationFacts.turnCount, 0);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
  }
});

test("cloud api trace reports expired projection without AgentRun read-through when live trace store has expired (#1519)", async () => {
  const ownerSessions = new Map();
  const agentRunCalls = [];
  const commandFinalText = "历史 trace 已过期，但 final response 来自 AgentRun command result。";
  ownerSessions.set("ses_issue842_expired", testAgentSessionRecord({
    sessionId: "ses_issue842_expired",
    projectId: "prj_v02_code_agent",
    conversationId: "cnv_issue842_expired",
    threadId: "thread-issue-842-expired",
    traceId: "trc_issue842_expired",
    status: "active",
    session: {
      finalResponse: {
        text: "旧 session snapshot final 不应作为历史 trace 权威。",
        textChars: 30,
        role: "assistant",
        status: "completed",
        traceId: "trc_issue842_expired",
        source: "code-agent-result",
        valuesPrinted: false
      },
      traceSummary: {
        traceId: "trc_issue842_expired",
        source: "stale-derived-session-evidence",
        sourceEventCount: 26,
        terminalStatus: "completed",
        noiseEventCount: 4,
        omittedNoiseCount: 4,
        valuesPrinted: false
      },
      agentRun: {
        adapter: "agentrun-v01",
        runId: "run_issue842_expired",
        commandId: "cmd_issue842_expired",
        runnerId: "runner_issue842_expired",
        jobName: "agentrun-v01-runner-issue842-expired",
        namespace: "agentrun-v01",
        terminalStatus: "completed",
        valuesPrinted: false
      },
      valuesRedacted: true
    }
  }));
  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    agentRunCalls.push({ method: request.method, path: url.pathname, search: url.search });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_issue842_expired" })}\n`);
    };
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_issue842_expired/commands") {
      return send({ items: [
        { id: "cmd_issue842_expired", runId: "run_issue842_expired", state: "completed", type: "turn", seq: 1, idempotencyKey: "trc_issue842_expired", payload: { traceId: "trc_issue842_expired", conversationId: "cnv_issue842_expired", hwlabSessionId: "ses_issue842_expired", threadId: "thread-issue-842-expired", providerProfile: "deepseek" } }
      ] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_issue842_expired/events") {
      return send({ items: [] });
    }
    if (request.method === "GET" && url.pathname === "/api/v1/runs/run_issue842_expired/commands/cmd_issue842_expired/result") {
      return send({
        runId: "run_issue842_expired",
        commandId: "cmd_issue842_expired",
        attemptId: "attempt_issue842_expired",
        runnerId: "runner_issue842_expired",
        jobName: "agentrun-v01-runner-issue842-expired",
        namespace: "agentrun-v01",
        status: "completed",
        runStatus: "completed",
        commandState: "completed",
        terminalStatus: "completed",
        completed: true,
        reply: commandFinalText,
        lastSeq: 26,
        eventCount: 26,
        sessionRef: { sessionId: "ses_agentrun_issue842_expired", conversationId: "cnv_issue842_expired", threadId: "thread-issue-842-expired" }
      });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, message: `unexpected ${request.method} ${url.pathname}` })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  const traceStore = createCodeAgentTraceStore();
  const server = createCloudApiServer({
    traceStore,
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async getAgentSessionByTraceId(traceId) {
        return [...ownerSessions.values()].find((session) => session.lastTraceId === traceId) ?? null;
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/traces/trc_issue842_expired`, {
      headers: { cookie: "hwlab_session=test-stub-session" }
    });
    assert.equal(response.status, 200);
    const body = await response.json();
    assert.equal(body.ok, false);
    assert.equal(body.status, "missing");
    assert.equal(body.traceStatus, "missing");
    assert.equal(body.eventCount, 0);
    assert.equal(body.projectionStatus, "unknown");
    assert.equal(body.retention.liveTraceStore, "missing");
    assert.equal(JSON.stringify(body).includes("旧 session snapshot final"), false);
    assert.deepEqual(agentRunCalls, []);
    assert.equal(JSON.stringify(body).includes("password"), false);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await new Promise((resolve, reject) => {
      agentRunServer.close((error) => (error ? reject(error) : resolve()));
    });
  }
});

test("cloud api trace does not replay an earlier AgentRun command from GET after same-run lastSeq advances (#1519)", async () => {
  const calls = [];
  const firstTraceId = "trc_issue955_first_trace";
  const codeAgentChatResults = new Map();
  const runId = "run_issue955_replay";
  const firstCommandId = "cmd_issue955_first";
  const secondCommandId = "cmd_issue955_second";
  const firstFinalText = "目前只有一个 HWPOD 可用：\n\n- d601-f103-v2 (board: D601-F103-V2 / STM32F103)\n\nAPI 返回 count=1, availableCount=1。";
  const firstEvents = [
    { id: "evt_issue955_first_setup", runId, seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: firstCommandId, jobName: "agentrun-v01-runner-issue955-first", namespace: "agentrun-v01" }, createdAt: "2026-06-06T01:43:25.000Z" },
    { id: "evt_issue955_first_tool", runId, seq: 18, type: "tool_call", payload: { method: "item/completed", type: "commandExecution", toolName: "commandExecution", itemId: "call_issue955_hwpod_list", command: "/bin/sh -lc 'hwpod list --available'", status: "completed", exitCode: 0, outputSummary: '{"count":1,"availableCount":1,"ids":["d601-f103-v2"]}', commandId: firstCommandId }, createdAt: "2026-06-06T01:43:42.000Z" },
    { id: "evt_issue955_first_assistant", runId, seq: 27, type: "assistant_message", payload: { commandId: firstCommandId, itemId: "msg_item_0", text: firstFinalText }, createdAt: "2026-06-06T01:43:55.000Z" },
    { id: "evt_issue955_first_terminal", runId, seq: 35, type: "terminal_status", payload: { commandId: firstCommandId, terminalStatus: "completed" }, createdAt: "2026-06-06T01:43:56.000Z" }
  ];
  const secondEvents = [
    { id: "evt_issue955_second_setup", runId, seq: 47, type: "backend_status", payload: { phase: "runner-claim-waiting-for-stale-lease" }, createdAt: "2026-06-06T01:45:56.000Z" },
    { id: "evt_issue955_second_assistant", runId, seq: 58, type: "assistant_message", payload: { commandId: secondCommandId, itemId: "msg_item_0", text: "编译成功！来总结一下结果。" }, createdAt: "2026-06-06T01:46:24.000Z" },
    { id: "evt_issue955_second_terminal", runId, seq: 66, type: "terminal_status", payload: { commandId: secondCommandId, terminalStatus: "completed" }, createdAt: "2026-06-06T01:46:28.000Z" }
  ];
  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    calls.push({ method: request.method, path: url.pathname, afterSeq: url.searchParams.get("afterSeq") });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_issue955_replay" })}\n`);
    };
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/commands`) {
      return send({ items: [
        { id: firstCommandId, runId, state: "completed", idempotencyKey: firstTraceId, createdAt: "2026-06-06T01:43:30.040Z", updatedAt: "2026-06-06T01:43:56.000Z", payload: { traceId: firstTraceId, conversationId: "cnv_issue955_replay", hwlabSessionId: "ses_issue955_replay", threadId: "thread-issue955-replay", providerProfile: "deepseek" } },
        { id: secondCommandId, runId, state: "completed", idempotencyKey: "trc_issue955_second_trace", createdAt: "2026-06-06T01:46:11.000Z", updatedAt: "2026-06-06T01:46:28.000Z", payload: { traceId: "trc_issue955_second_trace", conversationId: "cnv_issue955_replay", hwlabSessionId: "ses_issue955_replay", threadId: "thread-issue955-replay", providerProfile: "deepseek" } }
      ] });
    }
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/commands/${firstCommandId}/result`) {
      return send({ runId, commandId: firstCommandId, status: "completed", runStatus: "completed", commandState: "completed", terminalStatus: "completed", completed: true, reply: firstFinalText, lastSeq: 35, eventCount: 35, sessionRef: { sessionId: "ses_agentrun_deepseek_issue955_replay", conversationId: "cnv_issue955_replay", threadId: "thread-issue955-replay" } });
    }
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/events`) {
      return send({ items: [...firstEvents, ...secondEvents] });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, message: `unexpected ${request.method} ${url.pathname}` })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  codeAgentChatResults.set(firstTraceId, {
    accepted: true,
    status: "completed",
    shortConnection: true,
    traceId: firstTraceId,
    conversationId: "cnv_issue955_replay",
    sessionId: "ses_issue955_replay",
    threadId: "thread-issue955-replay",
    ownerUserId: TEST_AGENT_ACTOR.id,
    ownerRole: TEST_AGENT_ACTOR.role,
    reply: { role: "assistant", content: firstFinalText },
    finalResponse: { text: firstFinalText, textChars: firstFinalText.length, role: "assistant", status: "completed", traceId: firstTraceId, valuesPrinted: false },
    traceSummary: { traceId: firstTraceId, source: "code-agent-derived-session-evidence", sourceEventCount: 41, terminalStatus: "completed", agentRun: { runId, commandId: firstCommandId, lastSeq: 35, valuesPrinted: false }, valuesPrinted: false },
    agentRun: { adapter: "agentrun-v01", managerUrl: `http://127.0.0.1:${agentRunPort}`, runId, commandId: firstCommandId, lastSeq: 66, terminalStatus: "completed", valuesPrinted: false },
    valuesPrinted: false
  });
  const traceStore = createCodeAgentTraceStore();
  const server = createCloudApiServer({
    traceStore,
    codeAgentChatResults,
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/traces/${firstTraceId}`, {
      headers: { cookie: "hwlab_session=test-stub-session" }
    });
    assert.equal(response.status, 200);
    const body = await response.json();
    const text = JSON.stringify(body);
    assert.equal(body.traceId, firstTraceId);
    assert.equal(body.status, "expired");
    assert.equal(body.projectionStatus, "caught-up");
    assert.deepEqual(calls, []);
    assert.equal(body.eventCount, 0);
    assert.deepEqual(body.events, []);
    assert.equal(body.finalResponse.text, firstFinalText);
    assert.match(text, /d601-f103-v2/u);
    assert.doesNotMatch(text, /编译成功/u);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await new Promise((resolve, reject) => {
      agentRunServer.close((error) => (error ? reject(error) : resolve()));
    });
  }
});

test("cloud api running trace reports current projection without AgentRun event refresh (#1519)", async () => {
  const calls = [];
  const traceId = "trc_issue1000_running_trace";
  const runId = "run_issue1000_running_trace";
  const commandId = "cmd_issue1000_running_trace";
  const codeAgentChatResults = new Map();
  const events = [
    { id: "evt_issue1000_created", runId, seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId, jobName: "agentrun-v01-runner-issue1000", namespace: "agentrun-v01" }, createdAt: "2026-06-06T08:34:30.000Z" },
    { id: "evt_issue1000_turn", runId, seq: 2, type: "backend_status", payload: { phase: "turn/started", commandId }, createdAt: "2026-06-06T08:34:31.000Z" },
    { id: "evt_issue1000_tool", runId, seq: 3, type: "tool_call", payload: { method: "item/completed", type: "commandExecution", toolName: "commandExecution", itemId: "call_issue1000_hwpod", command: "hwpod list --available", status: "completed", exitCode: 0, outputSummary: "available=1", commandId }, createdAt: "2026-06-06T08:34:32.000Z" },
    { id: "evt_issue1000_output", runId, seq: 4, type: "assistant_message", payload: { commandId, itemId: "msg_issue1000_running", text: "正在查看 HWPOD。" }, createdAt: "2026-06-06T08:34:33.000Z" }
  ];
  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    calls.push({ method: request.method, path: url.pathname, search: url.search });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_issue1000_running" })}\n`);
    };
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/events`) return send({ items: events });
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/commands/${commandId}/result`) {
      return send({ runId, commandId, status: "running", runStatus: "running", commandState: "running", terminalStatus: null, completed: false, reply: null, lastSeq: 3, eventCount: 3 });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, message: `unexpected ${request.method} ${url.pathname}` })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  codeAgentChatResults.set(traceId, {
    accepted: true,
    status: "running",
    shortConnection: true,
    traceId,
    conversationId: "cnv_issue1000_running_trace",
    sessionId: "ses_issue1000_running_trace",
    threadId: "thread-issue1000-running-trace",
    ownerUserId: TEST_AGENT_ACTOR.id,
    ownerRole: TEST_AGENT_ACTOR.role,
    agentRun: { adapter: "agentrun-v01", managerUrl: `http://127.0.0.1:${agentRunPort}`, runId, commandId, traceId, providerTrace: { traceId }, lastSeq: 0, status: "running", commandState: "running", valuesPrinted: false },
    valuesPrinted: false
  });
  const server = createCloudApiServer({
    traceStore: createCodeAgentTraceStore(),
    codeAgentChatResults,
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/traces/${traceId}`, {
      headers: { cookie: "hwlab_session=test-stub-session" }
    });
    assert.equal(response.status, 200);
    const body = await response.json();
    assert.equal(body.status, "missing");
    assert.equal(body.projectionStatus, "projecting");
    assert.equal(body.eventCount, 0);
    assert.deepEqual(body.events, []);
    assert.deepEqual(calls, []);
    assert.equal(calls.some((call) => call.path === `/api/v1/runs/${runId}/commands/${commandId}/result`), false);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await new Promise((resolve, reject) => {
      agentRunServer.close((error) => (error ? reject(error) : resolve()));
    });
  }
});

test("cloud api turn status does not backfill terminal AgentRun projection on GET (#1585)", async () => {
  const calls = [];
  const traceId = "trc_issue1422_turn_status_fast_path";
  const runId = "run_issue1422_turn_status_fast_path";
  const commandId = "cmd_issue1422_turn_status_fast_path";
  const events = [
    { id: "evt_issue1422_created", runId, seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId }, createdAt: "2026-06-18T04:30:00.000Z" },
    { id: "evt_issue1422_terminal", runId, seq: 2, type: "terminal_status", payload: { commandId, terminalStatus: "completed" }, createdAt: "2026-06-18T04:30:01.000Z" }
  ];
  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    calls.push({ method: request.method, path: url.pathname, search: url.search });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_issue1422_turn" })}\n`);
    };
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/events`) return send({ items: events });
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/commands/${commandId}/result`) return send({
      runId,
      commandId,
      status: "completed",
      runStatus: "claimed",
      commandState: "completed",
      terminalStatus: "completed",
      completed: true,
      reply: { content: "issue 1555 read-side backfill completed" },
      lastSeq: 2,
      eventCount: 2
    });
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, message: `unexpected ${request.method} ${url.pathname}` })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  const codeAgentChatResults = new Map([[traceId, {
    accepted: true,
    status: "running",
    shortConnection: true,
    traceId,
    conversationId: "cnv_issue1422_turn_status",
    sessionId: "ses_issue1422_turn_status",
    threadId: "thread-issue1422-turn-status",
    ownerUserId: TEST_AGENT_ACTOR.id,
    ownerRole: TEST_AGENT_ACTOR.role,
    agentRun: { adapter: "agentrun-v01", managerUrl: `http://127.0.0.1:${agentRunPort}`, runId, commandId, traceId, providerTrace: { traceId }, lastSeq: 0, status: "running", commandState: "running", valuesPrinted: false },
    valuesPrinted: false
  }]]);
  const server = createCloudApiServer({
    traceStore: createCodeAgentTraceStore(),
    codeAgentChatResults,
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/turns/${traceId}`, {
      headers: { cookie: "hwlab_session=test-stub-session" }
    });
    assert.equal(response.status, 200);
    const body = await response.json();
    assert.equal(body.status, "running");
    assert.equal(body.terminal, false);
    assert.equal(body.projectionStatus, "projecting");
    assert.equal(body.agentRun.commandState, "running");
    assert.equal(body.agentRun.terminalStatus ?? null, null);
    assert.equal(body.finalResponse, null);
    assert.deepEqual(calls, []);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await new Promise((resolve, reject) => {
      agentRunServer.close((error) => (error ? reject(error) : resolve()));
    });
  }
});

test("cloud api turn status reuses request session lookup without loading persisted AgentRun result (#1519)", async () => {
  const calls = [];
  const traceId = "trc_issue1422_turn_status_session_cache";
  const runId = "run_issue1422_turn_status_session_cache";
  const commandId = "cmd_issue1422_turn_status_session_cache";
  const agentRunServer = createHttpServer(async (request, response) => {
    const url = new URL(request.url || "/", "http://127.0.0.1");
    calls.push({ method: request.method, path: url.pathname, search: url.search });
    const send = (data) => {
      response.writeHead(200, { "content-type": "application/json" });
      response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_issue1422_session_cache" })}\n`);
    };
    if (request.method === "GET" && url.pathname === `/api/v1/runs/${runId}/events`) {
      return send({ items: [
        { id: "evt_issue1422_session_cache_running", runId, seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId }, createdAt: "2026-06-18T05:20:00.000Z" }
      ] });
    }
    response.writeHead(404, { "content-type": "application/json" });
    response.end(`${JSON.stringify({ ok: false, message: `unexpected ${request.method} ${url.pathname}` })}\n`);
  });
  await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));

  const agentRunPort = agentRunServer.address().port;
  let sessionLookupCount = 0;
  const session = testAgentSessionRecord({
    sessionId: "ses_issue1422_turn_status_session_cache",
    projectId: "prj_hwpod_workbench",
    conversationId: "cnv_issue1422_turn_status_session_cache",
    threadId: "thread-issue1422-turn-status-session-cache",
    lastTraceId: traceId,
    status: "running",
    session: {
      agentRun: {
        adapter: "agentrun-v01",
        managerUrl: `http://127.0.0.1:${agentRunPort}`,
        runId,
        commandId,
        traceId,
        providerTrace: { traceId, valuesPrinted: false },
        lastSeq: 0,
        status: "running",
        commandState: "running",
        backendProfile: "deepseek",
        valuesPrinted: false
      },
      valuesRedacted: true
    }
  });
  const server = createCloudApiServer({
    traceStore: createCodeAgentTraceStore(),
    codeAgentChatResults: new Map(),
    env: {
      HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
      AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
      HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
      HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
      HWLAB_ENVIRONMENT: "v02",
      HWLAB_GITOPS_PROFILE: "v02"
    },
    accessController: {
      required: false,
      async authenticate() {
        return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
      },
      async getAgentSessionByTraceId(requestTraceId) {
        sessionLookupCount += 1;
        return requestTraceId === traceId ? session : null;
      }
    }
  });
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));

  try {
    const { port } = server.address();
    const response = await fetch(`http://127.0.0.1:${port}/v1/agent/turns/${traceId}?projectId=prj_hwpod_workbench`, {
      headers: { cookie: "hwlab_session=test-stub-session" }
    });
    assert.equal(response.status, 404);
    const body = await response.json();
    assert.equal(body.status, "unknown");
    assert.equal(body.projectionStatus, "unknown");
    assert.equal(sessionLookupCount, 1);
    assert.equal(calls.filter((call) => call.path === `/api/v1/runs/${runId}/events`).length, 0);
  } finally {
    await new Promise((resolve, reject) => {
      server.close((error) => (error ? reject(error) : resolve()));
    });
    await new Promise((resolve, reject) => {
      agentRunServer.close((error) => (error ? reject(error) : resolve()));
    });
  }
});
