{
  "version": "3.16",
  "name": "CaveZoneScout",
  "description": "Writes a cave-search program into an isolated child space, runs it, and captures the trace/report.",
  "steps": [
    {
      "id": "Tool_010_WriteMap",
      "tool": "WriteFile",
      "input": {
        "file_path": "=\"cave.json\"",
        "content": "=mapJson"
      },
      "next": "Tool_020_WriteSolver"
    },
    {
      "id": "Tool_020_WriteSolver",
      "tool": "WriteFile",
      "input": {
        "file_path": "=\"explore-cave.mjs\"",
        "content": "import fs from 'fs';\n\nconst cavePath = process.argv[2] || 'cave.json';\nconst cave = JSON.parse(fs.readFileSync(cavePath, 'utf8'));\nconst trace = [];\nconst seen = new Map();\nlet best = null;\n\nfunction scoreState(node, energy, crystals, path) {\n  return (node === cave.goal ? 500 : 0) + (crystals * 11) + energy - path.length;\n}\n\nfunction remember(signature, score) {\n  const prev = seen.get(signature) ?? -Infinity;\n  if (prev >= score) return false;\n  seen.set(signature, score);\n  return true;\n}\n\nfunction explore(node, energy, crystals, path, visitedRooms) {\n  const room = cave.rooms[node] || {};\n  const nextVisitedRooms = new Set(visitedRooms);\n  const gained = nextVisitedRooms.has(node) ? 0 : (room.crystals || 0);\n  nextVisitedRooms.add(node);\n  const nextCrystals = crystals + gained;\n  const nextPath = [...path, node];\n  const signature = [node, energy, nextCrystals, [...nextVisitedRooms].sort().join(',')].join('|');\n  const score = scoreState(node, energy, nextCrystals, nextPath);\n  if (!remember(signature, score)) return;\n\n  trace.push(`visit=${node}; energy=${energy}; crystals=${nextCrystals}; path=${nextPath.join('>')}`);\n  if (!best || score > best.score) {\n    best = { node, energy, crystals: nextCrystals, path: nextPath, score };\n  }\n  if (node === cave.goal) return;\n\n  const edges = (cave.tunnels[node] || []).slice().sort((a, b) => {\n    const aReward = (cave.rooms[a.to]?.crystals || 0) - a.cost;\n    const bReward = (cave.rooms[b.to]?.crystals || 0) - b.cost;\n    return bReward - aReward;\n  });\n\n  for (const edge of edges) {\n    if (energy < edge.cost) {\n      trace.push(`skip=${node}->${edge.to}; reason=energy; need=${edge.cost}; have=${energy}`);\n      continue;\n    }\n    const recharge = cave.rooms[edge.to]?.recharge || 0;\n    explore(edge.to, energy - edge.cost + recharge, nextCrystals, nextPath, nextVisitedRooms);\n  }\n}\n\nexplore(cave.start, cave.energy, 0, [], new Set());\n\nconst reportLines = [\n  `zone=${cave.zone}`,\n  `goal=${cave.goal}`,\n  `bestNode=${best?.node || 'unknown'}`,\n  `score=${best?.score ?? 0}`,\n  `energyLeft=${best?.energy ?? 0}`,\n  `crystals=${best?.crystals ?? 0}`,\n  `route=${best?.path?.join('>') || ''}`\n];\n\nfs.writeFileSync('report.txt', reportLines.join('\\n'));\nfs.writeFileSync('trace.txt', trace.join('\\n'));\nconsole.log(`best=${best?.node || 'unknown'}; score=${best?.score ?? 0}; route=${best?.path?.join('>') || ''}; crystals=${best?.crystals ?? 0}`);\n"
      },
      "next": "Tool_030_RunSolver"
    },
    {
      "id": "Tool_030_RunSolver",
      "tool": "Bash",
      "input": {
        "command": "=\"node explore-cave.mjs cave.json\""
      },
      "out": {
        "$solverStdout": "=_result"
      },
      "next": "Tool_040_ReadReport"
    },
    {
      "id": "Tool_040_ReadReport",
      "tool": "ReadFile",
      "input": {
        "file_path": "=\"report.txt\""
      },
      "out": {
        "$reportText": "=_result"
      },
      "next": "Tool_050_ReadTrace"
    },
    {
      "id": "Tool_050_ReadTrace",
      "tool": "ReadFile",
      "input": {
        "file_path": "=\"trace.txt\"",
        "limit": 80
      },
      "out": {
        "$traceText": "=_result"
      },
      "next": "Set_060_Summary"
    },
    {
      "id": "Set_060_Summary",
      "target": "$zoneSummary",
      "value": "=zoneName + \" => \" + $solverStdout",
      "next": "Write_070_Summary"
    },
    {
      "id": "Write_070_Summary",
      "target": "=\"Artifacts/zone-summary.txt\"",
      "value": "=$zoneSummary",
      "mode": "overwrite",
      "next": "Stop_End"
    },
    {
      "id": "Stop_End"
    }
  ]
}