feat(workshop): reworked phase flow — agent makeup, sidebar advance, responsive

Rebuild the participant flow around the agent itself:
- Phases: Team registration (+ agent name) -> Meet your agent -> Skills &
  Policies (edit the agent's makeup) -> UnoQ Dashboard (React Flow
  configurator) -> Submit. Swapped/renamed the two module pages
  (Module1/2 -> ModuleDashboard/ModuleMakeup).
- Agent name captured at registration, shown on the dashboard and used in
  the chat greeting (live, not hard-coded), pushed to the board.
- One shared conversation across pages (AgentChatContext); Clawd the crab
  animates the LED matrix and reacts to chat status.
- MAKEUP slide-outs: view, edit (wrench), or AI-refine (wand) the agent's
  personality files and save them back to the board.
- Advance button moved into the sidebar for every phase (ProceedContext).
- Dropped the ADD-doc build + submission gate; Submit just records the entry.
- Responsive pass: sidebar auto-collapses below lg, fluid padding, React
  Flow pan/zoom/fit + Controls, architecture panel becomes a mobile overlay.
- Add @xyflow/react for the configurator.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-27 10:55:34 +02:00
co-authored by Claude Opus 4.8
parent 0797923933
commit 05207ba986
30 changed files with 1690 additions and 687 deletions
+22 -79
View File
@@ -1,11 +1,15 @@
import { useNavigate } from 'react-router-dom'
import { AddLayerForm } from '@/components/AddLayerForm'
import { AddDocument } from '@/components/AddDocument'
import { PanelHeading, ProceedButton } from '@/components/cockpit/PanelChrome'
import { ADD_LAYERS } from '@/lib/addLayers'
import { PanelHeading } from '@/components/cockpit/PanelChrome'
import { useSetProceed } from '@/lib/ProceedContext'
import { useSession } from '@/store/session'
import { makeSubmissionCode } from '@/lib/submission'
/**
* Module 3 · Submit — the finish line. The deliverable is the agent itself (the
* makeup/skills you shaped and shipped to the board), so there's no Agent Design
* Document to assemble or gate on: submitting just records the team's entry for
* judging. The advance control lives in the sidebar.
*/
export function AddBuilder() {
const navigate = useNavigate()
const team = useSession((s) => s.team)
@@ -14,36 +18,30 @@ export function AddBuilder() {
const setSubmission = useSession((s) => s.setSubmission)
const completePhase = useSession((s) => s.completePhase)
const complete = ADD_LAYERS.every(({ key }) => add[key].trim().length > 0)
const submitted = !!submission.code
const onExport = () => window.print()
const onSubmit = () => {
setSubmission({ code: makeSubmissionCode(team, add), submittedAt: new Date().toISOString() })
completePhase('add')
}
useSetProceed(
submitted
? { label: 'Back to start', disabled: false, onClick: () => navigate('/workshop') }
: { label: 'Submit agent', disabled: false, onClick: onSubmit },
)
// ── Submission finale (design panel6) ──
if (submitted) {
return (
<section className="print:hidden">
<section>
<div className="mt-5 rounded-[18px] border border-[var(--green-border-2)] bg-[linear-gradient(180deg,var(--green-bg),var(--surface))] px-12 py-14 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-[var(--green)] text-[32px] text-white">
</div>
<h1 className="mt-6 text-[44px] font-semibold tracking-[-0.02em]">ADD submitted</h1>
<h1 className="mt-6 text-[44px] font-semibold tracking-[-0.02em]">Agent submitted</h1>
<p className="mx-auto mt-3.5 max-w-[460px] text-[18px] leading-[1.5] text-ink-2">
Team <strong className="font-semibold text-ink">{team.name || 'Matrix'}</strong> ·{' '}
{(team.name || 'crimson-node').toLowerCase().replace(/\s+/g, '-')} your Agent Design Document
is in for judging. Your node keeps running the design you just shipped.
Team <strong className="font-semibold text-ink">{team.name || 'your team'}</strong> your agent is
in for judging, running the makeup you shaped on the board.
</p>
<div className="mt-7 inline-flex flex-wrap justify-center gap-2.5 font-mono text-[11px] tracking-[0.1em] text-[var(--green)]">
{ADD_LAYERS.map(({ n, title }) => (
<span key={n} className="rounded-md border border-[var(--green-border)] px-[11px] py-1.5">
L{n} {title.split(' ')[0].toUpperCase()}
</span>
))}
</div>
<div className="mt-8">
<button
type="button"
@@ -60,66 +58,11 @@ export function AddBuilder() {
return (
<section>
<div className="print:hidden">
<PanelHeading
title="Module 3 · Harness, Loops & submit"
intro="Finish Layers 4 and 5 — how your node reasons and how it runs over time — review the assembled Agent Design Document, export a PDF, and submit before the deadline."
size={44}
/>
</div>
<div className="mt-8 grid gap-4 md:grid-cols-2 print:hidden">
<AddLayerForm
layer="L4"
title="ADD · Layer 4 — Harness"
description="Which decisions run on the board, which escalate — and the degradation path, not just the happy path."
placeholder={
'Routine checks: on-board model, no network needed.\n' +
'Ambiguous or high-consequence calls: escalate to the cloud model.\n\n' +
'Degradation path:\n' +
'• cloud slow → fall back on-board, note reduced confidence\n' +
'• no network → keep sensing, logging and safing locally\n' +
'• on-board model down → stop actuating, alert, keep recording'
}
/>
<AddLayerForm
layer="L5"
title="ADD · Layer 5 — Loops"
description="How often it checks, what it reports by exception — and how the loop behaves when a cycle fails."
placeholder={
'Heartbeat every 30 s; sample each minute; report only on exception.\n\n' +
'When a cycle fails:\n' +
'• missed tick → skip, do not back-fill invented data\n' +
'• partial data → report what is missing\n' +
'• N failures → escalate to a human and stop acting'
}
/>
</div>
<div className="mt-5 rounded-[14px] border border-line bg-surface p-[26px_28px]">
<div className="flex items-center justify-between print:hidden">
<div className="text-[19px] font-semibold">Assembled document</div>
<button
type="button"
onClick={onExport}
className="rounded-lg border border-line-2 bg-surface px-4 py-2 text-[14px] text-ink transition-colors hover:border-blue hover:text-blue-ink"
>
Export PDF
</button>
</div>
<div className="mt-[18px] print:mt-0">
<AddDocument />
</div>
</div>
<div className="mt-8 flex items-center justify-between gap-4 print:hidden">
<span className={complete ? 'text-[15px] text-[var(--green)]' : 'text-[15px] text-[var(--muted-2)]'}>
{complete ? 'All five layers complete — ready to submit.' : 'Complete all five layers to submit.'}
</span>
<ProceedButton disabled={!complete} onClick={onSubmit}>
Submit ADD
</ProceedButton>
</div>
<PanelHeading
title="Submit your agent"
intro="You've met your agent, shaped its skills and policies, and wired up its dashboard — submit it for judging from the sidebar when you're ready; your node keeps running the design you shipped."
size={44}
/>
</section>
)
}