import fs from 'fs/promises'; import os from 'os'; import path from 'path'; const repoRoot = '/Users/ivx/Documents/VLCode-Lite'; const examplesDir = path.join(repoRoot, 'examples', 'workflows'); const emptyWindowWorkflowDir = path.join(os.homedir(), '.vl-code', 'empty-window', '.vl-code', 'workflows'); const solverSource = `import fs from 'fs'; const cavePath = process.argv[2] || 'cave.json'; const cave = JSON.parse(fs.readFileSync(cavePath, 'utf8')); const trace = []; const seen = new Map(); let best = null; function scoreState(node, energy, crystals, path) { return (node === cave.goal ? 500 : 0) + (crystals * 11) + energy - path.length; } function remember(signature, score) { const prev = seen.get(signature) ?? -Infinity; if (prev >= score) return false; seen.set(signature, score); return true; } function explore(node, energy, crystals, path, visitedRooms) { const room = cave.rooms[node] || {}; const nextVisitedRooms = new Set(visitedRooms); const gained = nextVisitedRooms.has(node) ? 0 : (room.crystals || 0); nextVisitedRooms.add(node); const nextCrystals = crystals + gained; const nextPath = [...path, node]; const signature = [node, energy, nextCrystals, [...nextVisitedRooms].sort().join(',')].join('|'); const score = scoreState(node, energy, nextCrystals, nextPath); if (!remember(signature, score)) return; trace.push(\`visit=\${node}; energy=\${energy}; crystals=\${nextCrystals}; path=\${nextPath.join('>')}\`); if (!best || score > best.score) { best = { node, energy, crystals: nextCrystals, path: nextPath, score }; } if (node === cave.goal) return; const edges = (cave.tunnels[node] || []).slice().sort((a, b) => { const aReward = (cave.rooms[a.to]?.crystals || 0) - a.cost; const bReward = (cave.rooms[b.to]?.crystals || 0) - b.cost; return bReward - aReward; }); for (const edge of edges) { if (energy < edge.cost) { trace.push(\`skip=\${node}->\${edge.to}; reason=energy; need=\${edge.cost}; have=\${energy}\`); continue; } const recharge = cave.rooms[edge.to]?.recharge || 0; explore(edge.to, energy - edge.cost + recharge, nextCrystals, nextPath, nextVisitedRooms); } } explore(cave.start, cave.energy, 0, [], new Set()); const reportLines = [ \`zone=\${cave.zone}\`, \`goal=\${cave.goal}\`, \`bestNode=\${best?.node || 'unknown'}\`, \`score=\${best?.score ?? 0}\`, \`energyLeft=\${best?.energy ?? 0}\`, \`crystals=\${best?.crystals ?? 0}\`, \`route=\${best?.path?.join('>') || ''}\` ]; fs.writeFileSync('report.txt', reportLines.join('\\n')); fs.writeFileSync('trace.txt', trace.join('\\n')); console.log(\`best=\${best?.node || 'unknown'}; score=\${best?.score ?? 0}; route=\${best?.path?.join('>') || ''}; crystals=\${best?.crystals ?? 0}\`); `; function makeScoutWorkflow(name = 'CaveZoneScout') { return { version: '3.16', name, 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: solverSource, }, 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' }, ], }; } const northMap = { zone: 'North Rim', start: 'N0', goal: 'N7', energy: 10, rooms: { N0: { crystals: 0 }, N1: { crystals: 2 }, N2: { crystals: 1, recharge: 1 }, N3: { crystals: 3 }, N4: { crystals: 2 }, N5: { crystals: 4, recharge: 2 }, N6: { crystals: 1 }, N7: { crystals: 6 }, }, tunnels: { N0: [{ to: 'N1', cost: 2 }, { to: 'N2', cost: 3 }], N1: [{ to: 'N3', cost: 2 }, { to: 'N4', cost: 3 }], N2: [{ to: 'N4', cost: 2 }, { to: 'N5', cost: 4 }], N3: [{ to: 'N6', cost: 2 }], N4: [{ to: 'N6', cost: 1 }, { to: 'N5', cost: 2 }], N5: [{ to: 'N7', cost: 2 }], N6: [{ to: 'N7', cost: 1 }], }, }; const southMap = { zone: 'South Spiral', start: 'S0', goal: 'S8', energy: 11, rooms: { S0: { crystals: 0 }, S1: { crystals: 1 }, S2: { crystals: 3 }, S3: { crystals: 2, recharge: 1 }, S4: { crystals: 4 }, S5: { crystals: 1 }, S6: { crystals: 5, recharge: 2 }, S7: { crystals: 2 }, S8: { crystals: 7 }, }, tunnels: { S0: [{ to: 'S1', cost: 1 }, { to: 'S2', cost: 3 }], S1: [{ to: 'S3', cost: 2 }, { to: 'S4', cost: 4 }], S2: [{ to: 'S4', cost: 2 }, { to: 'S5', cost: 3 }], S3: [{ to: 'S6', cost: 2 }], S4: [{ to: 'S6', cost: 1 }, { to: 'S7', cost: 2 }], S5: [{ to: 'S7', cost: 2 }], S6: [{ to: 'S8', cost: 2 }], S7: [{ to: 'S8', cost: 1 }], }, }; const anomalyMap = { zone: 'Deep Anomaly', start: 'D0', goal: 'D9', energy: 14, rooms: { D0: { crystals: 0 }, D1: { crystals: 2 }, D2: { crystals: 3 }, D3: { crystals: 1, recharge: 1 }, D4: { crystals: 4 }, D5: { crystals: 2, recharge: 2 }, D6: { crystals: 6 }, D7: { crystals: 3 }, D8: { crystals: 5 }, D9: { crystals: 9 }, }, tunnels: { D0: [{ to: 'D1', cost: 2 }, { to: 'D2', cost: 2 }], D1: [{ to: 'D3', cost: 2 }, { to: 'D4', cost: 4 }], D2: [{ to: 'D4', cost: 2 }, { to: 'D5', cost: 3 }], D3: [{ to: 'D6', cost: 3 }], D4: [{ to: 'D6', cost: 2 }, { to: 'D7', cost: 2 }], D5: [{ to: 'D7', cost: 1 }, { to: 'D8', cost: 3 }], D6: [{ to: 'D9', cost: 2 }], D7: [{ to: 'D9', cost: 2 }], D8: [{ to: 'D9', cost: 1 }], }, }; const scoutWorkflow = makeScoutWorkflow('CaveZoneScout'); const deepScoutWorkflow = makeScoutWorkflow('GeneratedDeepScout'); const supervisorWorkflow = { version: '3.16', name: 'CaveSupervisorDemo', description: 'Supervisor workflow that runs two scout subflows in parallel, pauses for review, then generates a deep-scout child workflow and resumes exploration.', steps: [ { id: 'Set_010_OutputRoot', target: '$outputRoot', value: '=".codex/demo-artifacts/cave-workflow-demo"', next: 'Set_020_DeepFlowFile', }, { id: 'Set_020_DeepFlowFile', target: '$deepFlowFile', value: '=".vl-code/workflows/cave-deep-scout-generated.json"', next: 'Fork_030_InitialScouts', }, { id: 'Fork_030_InitialScouts', children: ['Subflow_040_NorthScout', 'Subflow_050_SouthScout'], next: 'Pause_060_ManagerReview', }, { id: 'Subflow_040_NorthScout', workflow_path: 'cave-zone-scout', mode: 'sync', work_dir: '=$outputRoot + "/north"', params: { zoneName: '="north-rim"', mapJson: JSON.stringify(northMap, null, 2), }, out: { '$northSummary': '=_result.variables["$zoneSummary"]', '$northReport': '=_result.variables["$reportText"]', }, }, { id: 'Subflow_050_SouthScout', workflow_path: 'cave-zone-scout', mode: 'sync', work_dir: '=$outputRoot + "/south"', params: { zoneName: '="south-spiral"', mapJson: JSON.stringify(southMap, null, 2), }, out: { '$southSummary': '=_result.variables["$zoneSummary"]', '$southReport': '=_result.variables["$reportText"]', }, }, { id: 'Pause_060_ManagerReview', reason: 'Manager review: compare north/south scout reports before dispatching a deep anomaly probe.', next: 'Tool_070_WriteDeepScoutWorkflow', }, { id: 'Tool_070_WriteDeepScoutWorkflow', tool: 'WriteFile', input: { file_path: '=$deepFlowFile', content: JSON.stringify(deepScoutWorkflow, null, 2), }, next: 'Subflow_080_DeepScout', }, { id: 'Subflow_080_DeepScout', workflow_path: 'cave-deep-scout-generated', mode: 'sync', work_dir: '=$outputRoot + "/deep-scout"', params: { zoneName: '="deep-anomaly"', mapJson: JSON.stringify(anomalyMap, null, 2), }, out: { '$deepSummary': '=_result.variables["$zoneSummary"]', '$deepReport': '=_result.variables["$reportText"]', }, next: 'Set_090_FinalNarrative', }, { id: 'Set_090_FinalNarrative', target: '$finalNarrative', value: '="North\\n" + $northSummary + "\\n\\nSouth\\n" + $southSummary + "\\n\\nDeep\\n" + $deepSummary', next: 'Write_100_ManagerReport', }, { id: 'Write_100_ManagerReport', target: '=$outputRoot + "/manager-report.txt"', value: '=$finalNarrative', mode: 'overwrite', next: 'Stop_End', }, { id: 'Stop_End' }, ], }; async function writeWorkflow(targetDir, fileName, workflow) { await fs.mkdir(targetDir, { recursive: true }); await fs.writeFile(path.join(targetDir, fileName), JSON.stringify(workflow, null, 2), 'utf8'); } await writeWorkflow(examplesDir, 'cave-zone-scout.json', scoutWorkflow); await writeWorkflow(examplesDir, 'cave-supervisor-demo.json', supervisorWorkflow); await writeWorkflow(emptyWindowWorkflowDir, 'cave-zone-scout.json', scoutWorkflow); await writeWorkflow(emptyWindowWorkflowDir, 'cave-supervisor-demo.json', supervisorWorkflow); console.log(JSON.stringify({ ok: true, examplesDir, emptyWindowWorkflowDir, files: ['cave-zone-scout.json', 'cave-supervisor-demo.json'], }, null, 2));