refactor(web): reorganize phases + fix Open-your-node URL

Move sections to where they read better:
- Phase 1 (Team registration): drop the "Your Agent" block.
- Phase 2 (Meet your agent): host the "Your Agent" section (say-hi / Telegram /
  voice) AND the agent chat under it; remove "Pick your domain".
- Module 1 (Domain & events): "Pick your domain" moves here (no more read-only
  carry) alongside the ADD Layer 1 card.
- Module 2 (Skills & policies): the chat is gone; the L2/L3 ADD cards show
  directly (still auto-prefilled if the three prompts ran in Meet your agent).

Also: OpenYourNode opens the browser-reachable board URL. In self-host/USB mode
the stored url is container-facing (host.docker.internal) which the browser
can't resolve — derive the current host on :8080 instead. Tests updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-23 12:52:50 -07:00
co-authored by Claude Opus 4.8
parent 48b88b0f0d
commit 4dd3681eef
10 changed files with 131 additions and 191 deletions
+25 -50
View File
@@ -1,8 +1,7 @@
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { AgentChat } from '@/components/AgentChat'
import { AddLayerForm } from '@/components/AddLayerForm'
import { PanelHeading, PanelCard, ProceedButton } from '@/components/cockpit/PanelChrome'
import { PanelHeading, ProceedButton } from '@/components/cockpit/PanelChrome'
import { useSession } from '@/store/session'
const L2_PREFILL =
@@ -15,19 +14,18 @@ export function Module2() {
const l2 = useSession((s) => s.add.L2)
const l3 = useSession((s) => s.add.L3)
const tried = useSession((s) => s.tried)
const setTried = useSession((s) => s.setTried)
const setAddLayer = useSession((s) => s.setAddLayer)
const completePhase = useSession((s) => s.completePhase)
const allTried = tried >= 3
const ready = allTried && l2.trim().length > 0 && l3.trim().length > 0
const ready = l2.trim().length > 0 && l3.trim().length > 0
// On reaching 3/3, seed Layers 2 & 3 with a starting draft (only if untouched).
// If the team ran the three agent prompts in "Meet your agent", seed Layers 2 & 3
// with a starting draft (only if untouched).
useEffect(() => {
if (!allTried) return
if (tried < 3) return
if (!useSession.getState().add.L2.trim()) setAddLayer('L2', L2_PREFILL)
if (!useSession.getState().add.L3.trim()) setAddLayer('L3', L3_PREFILL)
}, [allTried, setAddLayer])
}, [tried, setAddLayer])
const onProceed = () => {
completePhase('m2')
@@ -39,53 +37,30 @@ export function Module2() {
<PanelHeading
eyebrow="PHASE 4 OF 5 · ~90 MIN"
title="Module 2 · Skills & policies"
intro="Talk to your agent and watch it run real tools on your board. Each prompt makes it use a built-in skill — then capture your domain's skills and the policy that governs them."
intro="Capture what your agent can do and the policy that governs it — Layers 2 and 3 of your Agent Design Document."
size={46}
/>
<div className="mt-9">
<AgentChat onProgress={(done) => setTried(done)} />
<div className="mt-9 space-y-5">
<AddLayerForm
layer="L2"
title="ADD · Layer 2 — Skills"
description="What skills can the agent invoke to act on its domain?"
placeholder="Flash a sketch to the MCU; scroll a message; drive the damper; sample the IMU."
/>
<AddLayerForm
layer="L3"
title="ADD · Layer 3 — Policies & failure"
description="The actuation gate — and what happens when things break. A fail-safe must never quietly report 'normal'."
placeholder="Report only on exception; escalate ambiguous calls to the cloud; never suppress a stale-sensor alarm."
/>
</div>
{allTried ? (
<div className="mt-8 space-y-5" data-testid="whats-next">
<div>
<h2 className="text-[22px] font-semibold tracking-[-0.01em]">What&rsquo;s next</h2>
<p className="mt-1 max-w-[560px] text-[15px] text-ink-2">
You just watched the agent enumerate the bus and drive the matrix with its built-in
skills. Now capture <span className="font-medium text-ink">your domain&rsquo;s</span> skills and
the policy that governs them — Layers 2 and 3, drafted below.
</p>
</div>
<AddLayerForm
layer="L2"
title="ADD · Layer 2 — Skills"
description="What skills can the agent invoke to act on its domain?"
placeholder="Flash a sketch to the MCU; scroll a message; drive the damper; sample the IMU."
/>
<AddLayerForm
layer="L3"
title="ADD · Layer 3 — Policies & failure"
description="The actuation gate — and what happens when things break. A fail-safe must never quietly report 'normal'."
placeholder="Report only on exception; escalate ambiguous calls to the cloud; never suppress a stale-sensor alarm."
/>
<div className="flex justify-end">
<ProceedButton disabled={!ready} onClick={onProceed}>
Proceed to Module 3 →
</ProceedButton>
</div>
</div>
) : (
<PanelCard className="mt-6">
<div className="text-[15px] font-semibold text-ink-2">What&rsquo;s next</div>
<p className="mt-2 text-[14px] leading-[1.5] text-ink-3">
Try all three prompts above. Once your agent has run each one successfully, we&rsquo;ll
capture your domain&rsquo;s skills and policies here.
</p>
</PanelCard>
)}
<div className="mt-6 flex justify-end">
<ProceedButton disabled={!ready} onClick={onProceed}>
Proceed to Module 3 →
</ProceedButton>
</div>
</section>
)
}