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 (