import React, { useEffect, useState } from 'react'; import { Code2, FlaskConical, History, Lock, Play, RotateCcw, Sliders, Sparkles, Terminal } from 'lucide-react'; import { api, apiData } from '../services/api'; import { useLlmConfig } from '../services/useLlmConfig'; import ModelGate from './ModelGate'; /** * Developer steering console (Dev tab). Honors the two-layer differentiation: * - Layer 1 DISCOVERED (read-only per persona) — shown locked with a badge. * - Layer 1 WRITE via derivation RULESETS — how parameters are computed * (safe formulas), clearly a developer authoring surface. * - Layer 2 AUTHORED overrides — per test-case value overrides. * - Past-job CORRECTIONS — an audited changelog with undo (not an edit field). */ const OVERRIDABLE = [ 'observing.observation_delay_ms', 'observing.scan_pattern', 'observing.fixation_budget', 'thinking.max_steps', 'thinking.options_considered', 'acting.allowed_actions', 'acting.timeout_s', 'acting.frustration_abort_after_failed_steps', ]; const Section: React.FC<{ title: string; icon: any; badge?: string; badgeTone?: string; children: React.ReactNode }> = ({ title, icon: Icon, badge, badgeTone, children, }) => (
{title} {badge && {badge}}
{children}
); const DevSteeringConsole: React.FC = () => { const [hubId, setHubId] = useState(''); const [personaIndex, setPersonaIndex] = useState(0); const [discovered, setDiscovered] = useState(null); const [layer, setLayer] = useState(''); // ruleset (layer-1 write) const [rulePath, setRulePath] = useState('thinking.max_steps'); const [ruleExpr, setRuleExpr] = useState('clamp(digital_literacy * 4, 5, 30)'); const [rulePreview, setRulePreview] = useState(null); // layer-2 override const [ovPath, setOvPath] = useState('acting.frustration_abort_after_failed_steps'); const [ovValue, setOvValue] = useState('1'); const [effective, setEffective] = useState(null); // corrections const [corrFolder, setCorrFolder] = useState('journeys'); const [corrId, setCorrId] = useState(''); const [corrPath, setCorrPath] = useState('steering.thinking.max_steps.value'); const [corrValue, setCorrValue] = useState('99'); const [corrReason, setCorrReason] = useState('reviewer override'); const [corrLog, setCorrLog] = useState([]); const [autofill, setAutofill] = useState(null); const [autofillNote, setAutofillNote] = useState(''); const [err, setErr] = useState(''); const llm = useLlmConfig(); const seedHub = async () => { const env = await api('/api/personas/generate', { body: { company_name: 'Dev', count: 6, seed: 1 } }); setHubId(env.artifact_id!); return env.artifact_id!; }; useEffect(() => { seedHub().catch(() => undefined); }, []); const runDerive = async (rulesetId?: string) => { setErr(''); try { const id = hubId || (await seedHub()); const data = await apiData('/api/steering/derive', { body: { persona_hub_id: id, persona_index: personaIndex, ...(rulesetId ? { ruleset_id: rulesetId } : {}) }, }); setDiscovered(data.steering); setLayer(data.layer); } catch (e: any) { setErr(e.message); } }; const previewRuleset = async () => { setErr(''); try { const created = await api('/api/steering/rulesets', { body: { name: 'dev-preview', rules: { [rulePath]: { type: 'formula', expr: ruleExpr } } }, }); const data = await apiData('/api/steering/rulesets/preview', { body: { persona_hub_id: hubId, persona_index: personaIndex, ruleset_id: created.artifact_id }, }); setRulePreview(data.diff); } catch (e: any) { setErr(e.message); } }; const applyOverride = async () => { setErr(''); try { let parsed: any = ovValue; try { parsed = JSON.parse(ovValue); } catch { /* keep string */ } const data = await apiData('/api/steering/apply', { body: { persona_hub_id: hubId, persona_index: personaIndex, overrides: { [ovPath]: parsed } }, }); setEffective(data.effective_steering); } catch (e: any) { setErr(e.message); } }; const runAutofill = async () => { setAutofillNote(''); try { const data = await apiData('/api/steering/autofill', { body: { persona_hub_id: hubId, persona_index: personaIndex, goal: 'Find and buy a product' } }); setAutofill(data); setAutofillNote(data.provenance?.llm ? `composed by ${data.provenance.llm}` : 'deterministic values (no LLM)'); } catch (e: any) { setAutofillNote(e.message); } }; const injectCorrection = async () => { setErr(''); try { let parsed: any = corrValue; try { parsed = JSON.parse(corrValue); } catch { /* keep string */ } await api('/api/corrections', { body: { folder: corrFolder, artifact_id: corrId, path: corrPath, value: parsed, reason: corrReason }, }); loadCorrections(); } catch (e: any) { setErr(e.message); } }; const loadCorrections = async () => { if (!corrId) return; try { const data = await apiData(`/api/corrections/${corrFolder}/${corrId}`); setCorrLog(data.corrections || []); } catch (e: any) { setErr(e.message); } }; const revert = async () => { try { await api(`/api/corrections/${corrFolder}/${corrId}/revert`, { method: 'POST' }); loadCorrections(); } catch (e: any) { setErr(e.message); } }; return (

Developer Steering Console

layer 1 read · layer 1 write (rulesets) · layer 2 · corrections
{err &&
{err}
}
{/* Layer 1 discovered — read-only */}

A property of the persona — computed, not editable. `POST /api/steering/derive`.

{discovered && ( <>
{layer}
                {JSON.stringify(discovered, null, 1)}
              
)}
{/* Layer 1 WRITE — derivation ruleset */}

Redefine the compute rule via a safe formula over persona features. `POST /api/steering/rulesets`.

setRuleExpr(e.target.value)} className="w-full rounded-lg border border-gray-800 bg-black p-2 font-mono text-[11px] outline-none focus:border-violet-500" />
{rulePreview && (
{Object.entries(rulePreview).map(([p, d]: any) => (
{p} {JSON.stringify(d.default)}{JSON.stringify(d.computed)}
))}
)}
{/* Layer 2 authored override */}

Override a final value for this test case. `POST /api/steering/apply`.

setOvValue(e.target.value)} className="w-24 rounded-lg border border-gray-800 bg-black p-2 font-mono text-[11px] outline-none focus:border-teal-500" />
{effective && (
              {JSON.stringify(effective[ovPath.split('.')[0]]?.[ovPath.split('.')[1]], null, 1)}
            
)}
{/* LLM Auto-fill — composes the language rows (think-restyle, goal voice) */}

Numbers stay deterministic; the BYOK text model composes the persona-voiced think-restyle & goal. `POST /api/steering/autofill`.

{!llm.textConfigured ? ( ) : ( )} {autofillNote &&
{autofillNote}
} {autofill && (
              {JSON.stringify(autofill.thinking?.think_restyle_instruction, null, 1)}
            
)}
{/* Corrections — audited changelog with undo */}

Inject a corrected value into a completed artifact. Original kept; every edit logged.

setCorrId(e.target.value)} onBlur={loadCorrections} placeholder="artifact id" className="rounded-lg border border-gray-800 bg-black p-2 font-mono text-[10px] outline-none focus:border-rose-500" /> setCorrPath(e.target.value)} placeholder="dotted.path" className="rounded-lg border border-gray-800 bg-black p-2 font-mono text-[10px] outline-none focus:border-rose-500" /> setCorrValue(e.target.value)} placeholder="new value" className="rounded-lg border border-gray-800 bg-black p-2 font-mono text-[10px] outline-none focus:border-rose-500" />
setCorrReason(e.target.value)} placeholder="reason" className="mt-2 w-full rounded-lg border border-gray-800 bg-black p-2 text-[10px] outline-none focus:border-rose-500" />
{corrLog.length > 0 && (
Changelog
{corrLog.map((c, i) => (
{c.path}: {JSON.stringify(c.from)} → {JSON.stringify(c.to)} · {c.reason}
))}
)}
); }; export default DevSteeringConsole;