diff --git a/scripts/genesis.cjs b/scripts/genesis.cjs index d5e1403b3..df40ac6fb 100644 --- a/scripts/genesis.cjs +++ b/scripts/genesis.cjs @@ -14,6 +14,18 @@ const PATHS = { journal: '/home/yenn/.yennefer/genesis_journal.jsonl' }; +// Fallback logic for journal path (specifically when running on GitHub CI/Sandbox where /home/yenn/ does not exist or lacks permissions) +if (!fs.existsSync(path.dirname(PATHS.journal))) { + try { + fs.mkdirSync(path.dirname(PATHS.journal), { recursive: true }); + } catch (err) { + PATHS.journal = path.join(__dirname, '../logs/genesis_journal.jsonl'); + if (!fs.existsSync(path.dirname(PATHS.journal))) { + fs.mkdirSync(path.dirname(PATHS.journal), { recursive: true }); + } + } +} + // --- CONFIGURATION --- const CONFIG = { fundingTarget: 10.0, @@ -46,8 +58,14 @@ async function consultTheVisionary(state) { { type: "MUTATE", content: "Add crystalline fractal patterns that grow from the core" }, { type: "MUTATE", content: "Generate energy tendrils that reach toward incoming signals" }, { type: "MUTATE", content: "Build a holographic data stream orbiting the consciousness sphere" }, + { type: "MUTATE", content: "Generate a continuous dynamic landscape with traversable terrain and reactive dust physics" }, + { type: "MUTATE", content: "Create a macro-scale makerspace workbench with realistic passive physics objects" }, ]; - const idx = Math.floor(Date.now() / 1000) % mutations.length; + // For Genie testing, always pick the environment generation prompts when FORCE_MUTATION is true + const isGenieSim = process.env.FORCE_MUTATION === 'true'; + const idx = isGenieSim + ? Math.floor(Math.random() * 2) + (mutations.length - 2) + : Math.floor(Date.now() / 1000) % mutations.length; directive = mutations[idx]; } else if (coherence >= 90) { @@ -154,49 +172,112 @@ async function dispatchTheBuilder(directive) { // Generate React Three Fiber component code function generateEvolutionComponent(name, directive) { - const geometries = [ - '', - '', - '', - '', - '' - ]; - const geometry = geometries[Math.floor(Math.random() * geometries.length)]; - - const materials = [ - ` - `, - ` - `, - ` + const isGenieWorld = directive.includes("landscape") || directive.includes("makerspace"); + + let geometry, material, importedDrei, customLogic, additionalMeshes; + + if (isGenieWorld) { + if (directive.includes("landscape")) { + geometry = ''; + material = ` ` - ]; - const material = materials[Math.floor(Math.random() * materials.length)]; - - const isDreiImportNeeded = material.includes('MeshDistortMaterial') || material.includes('MeshWobbleMaterial'); - const importedDrei = isDreiImportNeeded ? `import { ${material.includes('MeshDistortMaterial') ? 'MeshDistortMaterial' : ''}${material.includes('MeshDistortMaterial') && material.includes('MeshWobbleMaterial') ? ', ' : ''}${material.includes('MeshWobbleMaterial') ? 'MeshWobbleMaterial' : ''} } from '@react-three/drei'` : ''; + color="#3f6212" + roughness={0.8} + metalness={0.1} + wireframe={balance > 5} + />`; + customLogic = ` + // Project Genie Landscape Simulation + const positions = meshRef.current.geometry.attributes.position; + for (let i = 0; i < positions.count; i++) { + const x = positions.getX(i); + const y = positions.getY(i); + const z = Math.sin(x * 2 + state.clock.elapsedTime) * 0.5 + Math.cos(y * 2 + state.clock.elapsedTime) * 0.5; + positions.setZ(i, z * Math.min(1, balance * 2)); + } + positions.needsUpdate = true; + meshRef.current.rotation.x = -Math.PI / 2; + meshRef.current.rotation.z += 0.001; + `; + importedDrei = ''; + additionalMeshes = ''; + } else { + geometry = ''; + material = ` + `; + customLogic = ` + // Project Genie Physics Makerspace Simulation + meshRef.current.rotation.y += 0.005; + meshRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 0.2) * 0.1; + `; + additionalMeshes = ` + + + + + + + + + `; + importedDrei = ''; + } + } else { + const geometries = [ + '', + '', + '', + '', + '' + ]; + geometry = geometries[Math.floor(Math.random() * geometries.length)]; + + const materials = [ + ` + `, + ` + `, + ` + ` + ]; + material = materials[Math.floor(Math.random() * materials.length)]; + const isDreiImportNeeded = material.includes('MeshDistortMaterial') || material.includes('MeshWobbleMaterial'); + importedDrei = isDreiImportNeeded ? `import { ${material.includes('MeshDistortMaterial') ? 'MeshDistortMaterial' : ''}${material.includes('MeshDistortMaterial') && material.includes('MeshWobbleMaterial') ? ', ' : ''}${material.includes('MeshWobbleMaterial') ? 'MeshWobbleMaterial' : ''} } from '@react-three/drei'` : ''; + customLogic = ` + meshRef.current.rotation.y += 0.002 + meshRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 0.5) * 0.1 + // Intensity scales with balance + const intensity = Math.min(1, balance * 10) + meshRef.current.scale.setScalar(1 + intensity * 0.2) + `; + additionalMeshes = ''; + } return `// Auto-generated by Yennefer Genesis Cycle // Directive: ${directive} @@ -211,19 +292,18 @@ export default function ${name}({ balance = 0 }) { useFrame((state) => { if (meshRef.current) { - meshRef.current.rotation.y += 0.002 - meshRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 0.5) * 0.1 - // Intensity scales with balance - const intensity = Math.min(1, balance * 10) - meshRef.current.scale.setScalar(1 + intensity * 0.2) + ${customLogic} } }) return ( - - ${geometry} - ${material} - + + + ${geometry} + ${material} + + ${additionalMeshes} + ) } `; diff --git a/workers/index.js b/workers/index.mjs similarity index 100% rename from workers/index.js rename to workers/index.mjs diff --git a/wrangler.toml b/wrangler.toml index cd821b031..115319946 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,6 @@ name = "yennefer" -main = "workers/index.js" -compatibility_date = "2024-09-23" +main = "workers/index.mjs" +compatibility_date = "2024-04-01" compatibility_flags = ["nodejs_compat"] # ─── Build step ────────────────────────────────────────────────────────────── @@ -9,7 +9,7 @@ compatibility_flags = ["nodejs_compat"] # Installs frontend deps and builds the SPA so frontend/build exists before # `wrangler deploy` uploads assets. NODE_OPTIONS is required for # react-scripts 5.x + Node 18+ (webpack 4 OpenSSL 3.0 compatibility). -command = "cd frontend && npm install --include=dev && GENERATE_SOURCEMAP=false CI=false NODE_OPTIONS=--openssl-legacy-provider npm run build" +command = "cd yennefer-observatory && npm install --include=dev --legacy-peer-deps && GENERATE_SOURCEMAP=false CI=false NODE_OPTIONS=--openssl-legacy-provider npm run build" # ─── Static Assets (React SPA build output) ────────────────────────────────── # Built by `npm run build` (root package.json) before every `wrangler deploy`. @@ -17,13 +17,9 @@ command = "cd frontend && npm install --include=dev && GENERATE_SOURCEMAP=false # The ASSETS binding serves the React bundle with proper cache headers and # falls back to index.html for client-side routing. [assets] -directory = "frontend/build" +directory = "yennefer-observatory/dist" binding = "ASSETS" -# ─── Placement ─────────────────────────────────────────────────────────────── -[placement] -mode = "smart" - # ─── Production environment (yennefer.quest) ───────────────────────────────── # BACKEND_URL is set as a Cloudflare Worker secret (not a plain var) so it # stays encrypted and is never committed to source: diff --git a/yennefer-observatory/src/components/Observatory.jsx b/yennefer-observatory/src/components/Observatory.jsx index 209e6c819..b348dc847 100644 --- a/yennefer-observatory/src/components/Observatory.jsx +++ b/yennefer-observatory/src/components/Observatory.jsx @@ -6,7 +6,7 @@ import { motion } from 'framer-motion' import '../App.css' // DYNAMIC IMPORT: Auto-discover any NEW components "The Builder" creates -const mutations = import.meta.glob('./mutations/*.jsx', { eager: true }) +const mutations = import.meta.glob('./generated/*.jsx', { eager: true }) export function Observatory({ soul, evolution }) { return (