From 4183fdc7d3667fb4c2af72ff0098c15168c9e950 Mon Sep 17 00:00:00 2001 From: t Date: Thu, 20 Aug 2026 15:30:59 -0600 Subject: Expose a json codec to the subagents.lua sandbox Model-authored workflow Lua could reach string, table, math, and utf8 but had no way to parse an agent's report, so any fan-out over discovered work had to invent an ad-hoc line format and hand-roll string.gmatch. Hand the guest panto.ext.json instead. decode returns nil plus a message rather than raising: the sandbox deliberately has no pcall, so a raising decoder would let one malformed agent line kill an entire workflow. Teach the pattern in the injected guidance too: deterministic Lua owns the loops, counts, ordering, and gates, agents supply discovery and judgment, and a worker that feeds Lua ends its report with one parseable line. The existing static-graph example stays; a discover-then-fan-out example joins it. --- spec/test_luatool.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'spec/test_luatool.lua') diff --git a/spec/test_luatool.lua b/spec/test_luatool.lua index d002bca..62f9283 100644 --- a/spec/test_luatool.lua +++ b/spec/test_luatool.lua @@ -57,6 +57,19 @@ return { assert(env.print() == nil) end }, + { "the guest json codec round-trips and reports bad input instead of raising", function() + local env = luatool.build_env() + local encoded = env.json.encode({ prs = { 124, 125 } }) + has(encoded, "124") + local decoded = env.json.decode(encoded) + assert(type(decoded) == "table" and decoded.prs[2] == 125) + -- The sandbox has no pcall, so a raising decoder would kill a workflow + -- over one malformed agent line. + local value, message = env.json.decode("RESULT=not json") + assert(value == nil and type(message) == "string") + assert(env.json.decode(nil) == nil) + end }, + { "the string metatable stays reachable and harmless", function() local env = luatool.build_env() assert(type(("").dump) == "function") -- cgit v1.3