local fake = require("spec.fake_ext") local progress = require("subagents.progress") local run = require("subagents.run") local luatool = require("subagents.luatool") local toml_workflows = require("subagents.toml_workflows") local workflow = require("subagents.workflow") local uv = require("luv") local function plain(lines) return table.concat(lines, "\n"):gsub("\27%[[%d;]*m", "") end local function has(text, needle) assert(text:find(needle, 1, true), "expected to find " .. needle .. " in:\n" .. text) end local function profile_set() local alpha = { name = "alpha", description = "alpha", body = "ALPHA\n" } local beta = { name = "beta", description = "beta", body = "BETA\n" } return { list = { alpha, beta }, by_name = { alpha = alpha, beta = beta }, warnings = {}, } end local function message(role, text, metadata) return { role = role, text = text, metadata = metadata } end local function tool_use(id, name, input) return { type = "tool_use", id = id, name = name, input = input, } end local function tool_result(id, output, is_error) return { type = "tool_result", tool_use_id = id, is_error = is_error == true, parts = { { text = output } }, } end local function claim(handle, id, tool_name) local component local alive = true progress.claim({ id = id, tool_name = tool_name or "subagents.run", collapsed = true, set_component = function(_, value) component = value return { render = value.render, invalidate = function() end, alive = function() return alive end, set_pinned = function() end, } end, }) assert(component ~= nil, "the production claim path installed a component") return component, function() alive = false end end local function with_host(fn, opts) local handle = fake.install(opts) progress.begin_replay() local ok, err = pcall(fn, handle) progress.reset() handle.restore() if not ok then error(err, 0) end end return { { "replay reconstructs a direct child turn, tools, result, model, and status", function() with_host(function(handle) handle.add_session("child-direct", { message("system", "You are a subagent."), message("system", "Discovered profile.", { subagents = { owner = "0198-primary", agent = "reviewer" }, }), message("user", "inspect the change", { subagents = { tool_call_id = "outer-direct", model = "openai:test", reasoning = "high" }, }), { role = "assistant", blocks = { { type = "text", text = "checking" }, tool_use("tool-1", "std__read", '{"path":"auth.lua"}'), } }, { role = "user", blocks = { tool_result("tool-1", "file contents") } }, { role = "assistant", blocks = { { type = "text", text = "found the issue" } } }, }) local component, kill = claim(handle, "outer-direct") progress.collapse({ collapsed = false }) local text = plain(component:render(120)) has(text, "✔ reviewer child-direct") has(text, "completed") has(text, "↳ openai:test (high)") has(text, "prompt: inspect the change") has(text, "checking") has(text, "std.read [tool-1]") has(text, 'input: {"path":"auth.lua"}') has(text, "result [tool-1]: file contents") has(text, "found the issue") kill() end) end }, { "replay isolates dynamic and fixed workflow cards and only inline manifests show system prompts", function() with_host(function(handle) handle.add_session("child-dynamic", { message("system", "You are a subagent."), message("system", "INLINE-WORKFLOW-SYSTEM", { subagents = { owner = "0198-primary", agent = "inline", inline = true }, }), message("user", "dynamic step", { subagents = { tool_call_id = "outer-dynamic", model = "fixture:one" }, }), message("assistant", "dynamic answer"), }) handle.add_session("child-fixed", { message("system", "You are a subagent."), message("system", "DISCOVERED-SYSTEM", { subagents = { owner = "0198-primary", agent = "alpha" }, }), message("user", "fixed step", { subagents = { tool_call_id = "outer-fixed", model = "fixture:two" }, }), message("assistant", "fixed answer"), }) local dynamic, kill_dynamic = claim(handle, "outer-dynamic", "subagents.lua") local fixed, kill_fixed = claim(handle, "outer-fixed", "subagents.workflow") progress.collapse({ collapsed = false }) local dynamic_text = plain(dynamic:render(120)) local fixed_text = plain(fixed:render(120)) has(dynamic_text, "✔ inline child-dynamic") has(dynamic_text, "system prompt: INLINE-WORKFLOW-SYSTEM") has(dynamic_text, "prompt: dynamic step") has(dynamic_text, "dynamic answer") assert(not dynamic_text:find("fixed answer", 1, true), dynamic_text) has(fixed_text, "✔ alpha child-fixed") has(fixed_text, "prompt: fixed step") has(fixed_text, "fixed answer") assert(not fixed_text:find("system prompt:", 1, true), fixed_text) kill_dynamic() kill_fixed() end) end }, { "one resumed child can contribute separate turns to separate outer calls", function() with_host(function(handle) handle.add_session("child-shared", { message("system", "role"), message("system", "Alpha", { subagents = { owner = "0198-primary", agent = "alpha" } }), message("user", "first turn", { subagents = { tool_call_id = "outer-a", model = "model-a" } }), message("assistant", "first answer"), message("user", "second turn", { subagents = { tool_call_id = "outer-b", model = "model-b" } }), message("assistant", "second answer"), message("user", "third turn", { subagents = { tool_call_id = "outer-a", model = "model-c" } }), message("assistant", "third answer"), }) local a, kill_a = claim(handle, "outer-a") local b, kill_b = claim(handle, "outer-b") progress.collapse({ collapsed = false }) local a_text = plain(a:render(120)) local b_text = plain(b:render(120)) has(a_text, "first answer") has(a_text, "third answer") assert(not a_text:find("second answer", 1, true), a_text) has(b_text, "second answer") assert(not b_text:find("first answer", 1, true), b_text) assert(not b_text:find("third answer", 1, true), b_text) local _, shared_cards = a_text:gsub("child%-shared", "") assert(shared_cards == 2, "both turns owned by outer-a are separate cards:\n" .. a_text) kill_a() kill_b() end) end }, { "replay preserves interleaved spawn order across child sessions", function() with_host(function(handle) handle.add_session("child-a", { message("system", "role"), message("system", "Alpha", { subagents = { owner = "0198-primary", agent = "alpha" } }), message("user", "A1", { subagents = { tool_call_id = "outer-order", sequence = 1, model = "m" } }), message("assistant", "answer A1"), message("user", "A2", { subagents = { tool_call_id = "outer-order", sequence = 3, model = "m" } }), message("assistant", "answer A2"), }) handle.add_session("child-b", { message("system", "role"), message("system", "Beta", { subagents = { owner = "0198-primary", agent = "beta" } }), message("user", "B1", { subagents = { tool_call_id = "outer-order", sequence = 2, model = "m" } }), message("assistant", "answer B1"), }) local component, kill = claim(handle, "outer-order") progress.collapse({ collapsed = false }) local text = plain(component:render(120)) local a1 = assert(text:find("answer A1", 1, true)) local b1 = assert(text:find("answer B1", 1, true)) local a2 = assert(text:find("answer A2", 1, true)) assert(a1 < b1 and b1 < a2, text) kill() end) end }, { "replay keeps cancelled and non-text completed turns terminal", function() with_host(function(handle) handle.add_session("child-cancel", { message("system", "role"), message("system", "Alpha", { subagents = { owner = "0198-primary", agent = "alpha" } }), message("user", "cancelled prompt", { subagents = { tool_call_id = "outer-status", sequence = 1, status = "cancelled", } }), }) handle.add_session("child-thinking", { message("system", "role"), message("system", "Beta", { subagents = { owner = "0198-primary", agent = "beta" } }), message("user", "thinking prompt", { subagents = { tool_call_id = "outer-status", sequence = 2, status = "completed", } }), { role = "assistant", blocks = { { type = "thinking", text = "private reasoning" } } }, }) local component, kill = claim(handle, "outer-status") progress.collapse({ collapsed = false }) local text = plain(component:render(120)) has(text, "⊘ alpha child-cancel") has(text, "✔ beta child-thinking") assert(not text:find("✖", 1, true), text) kill() end) end }, { "replay finds a manifest after long primary system context through the bounded API", function() with_host(function(handle) handle.reject_unbounded_replay = true local messages = {} for index = 1, 80 do messages[#messages + 1] = message("system", "context " .. index) end messages[#messages + 1] = message("system", "INLINE-LONG", { subagents = { owner = "0198-primary", agent = "long", inline = true }, }) messages[#messages + 1] = message("user", "long prompt", { subagents = { tool_call_id = "outer-long", sequence = 1 }, }) messages[#messages + 1] = message("assistant", "long answer") handle.add_session("child-long", messages) local component, kill = claim(handle, "outer-long") progress.collapse({ collapsed = false }) local text = plain(component:render(120)) has(text, "✔ long child-long") has(text, "system prompt: INLINE-LONG") assert(handle.bounded_list_calls == 1, "replay must use the bounded catalog API") assert(handle.bounded_load_calls == 2, "replay must use bounded tail + manifest reads") kill() end) end }, { "durable turns carry the owning outer call and inline manifests are marked", function() with_host(function(handle) local profiles = profile_set() local component, kill = claim(handle, "outer-run") progress.bind({ tool_call_id = "outer-run" }) handle.queue_for("alpha", { output = "done" }) run.handle({ agent = "alpha", prompt = "direct" }, profiles) assert(handle.runs[1].metadata.subagents.tool_call_id == "outer-run", "direct child metadata names its outer tool call") assert(handle.runs[1].metadata.subagents.sequence == 1, "direct child metadata records its card sequence") assert(handle.runs[1].metadata.subagents.status == "completed", "settled status is retained for durable presentation") handle.queue_for("alpha", { output = "fixed done" }) toml_workflows.run(assert(toml_workflows.validate({ name = "fixed", steps = { { id = "step", agent = "alpha", prompt = "run fixed" } }, }, "fixed")), "fixed", profiles) assert(handle.runs[2].metadata.subagents.tool_call_id == "outer-run", "fixed workflow child keeps the same outer owner") assert(handle.runs[2].metadata.subagents.sequence == 2, "fixed workflow child follows spawn order") handle.queue_for("inline", { output = "inline done" }) local source = [[return subagents.workflow(function(ctx) local result = ctx:agent({ name = "inline-work", agent = "inline", prompt = "dynamic" }):await() return result.output end)]] local workflow_id = luatool.handle({ source = source, agents = { { name = "inline", system_prompt = "INLINE" } }, }, profiles, { tool_call_id = "outer-run" }) for _ = 1, 100 do uv.run("nowait") if workflow.workflows[workflow_id].status ~= "running" then break end end assert(workflow.workflows[workflow_id].status == "completed") local child = handle.spawns[3] local manifest = child.system_messages[2].metadata.subagents assert(manifest.inline == true, "inline workflow manifest is explicitly marked") assert(handle.runs[3].metadata.subagents.tool_call_id == "outer-run", "inline workflow child keeps the same outer owner") assert(handle.runs[3].metadata.subagents.sequence == 3, "inline workflow child follows spawn order") assert(handle.runs[3].metadata.subagents.status == "completed", "inline completion is durably annotated") kill() progress.reset() _ = component end) end }, { "missing and malformed child logs degrade to an empty or partial board", function() with_host(function(handle) handle.add_session("malformed", "not a message array") handle.add_session("valid", { message("system", "role"), message("user", "no ownership", { subagents = { model = "model" } }), }) local component, kill = claim(handle, "outer-missing") assert(#component:render(100) == 0, "unowned or malformed logs do not invent cards") kill() end, { sessions = {} }) end }, }