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]>
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import { useEffect } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { AddLayerForm } from '@/components/AddLayerForm'
|
|
import { PanelHeading, ProceedButton } from '@/components/cockpit/PanelChrome'
|
|
import { useSession } from '@/store/session'
|
|
|
|
const L2_PREFILL =
|
|
'i2c_scan to enumerate both ADXL355Z; matrix_text and matrix_count for on-board readouts; adxl355_stream for live vibration.'
|
|
const L3_PREFILL =
|
|
'Report only on exception; escalate ambiguous or high-consequence calls to the cloud model; never suppress a stale-sensor alarm.'
|
|
|
|
export function Module2() {
|
|
const navigate = useNavigate()
|
|
const l2 = useSession((s) => s.add.L2)
|
|
const l3 = useSession((s) => s.add.L3)
|
|
const tried = useSession((s) => s.tried)
|
|
const setAddLayer = useSession((s) => s.setAddLayer)
|
|
const completePhase = useSession((s) => s.completePhase)
|
|
|
|
const ready = l2.trim().length > 0 && l3.trim().length > 0
|
|
|
|
// 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 (tried < 3) return
|
|
if (!useSession.getState().add.L2.trim()) setAddLayer('L2', L2_PREFILL)
|
|
if (!useSession.getState().add.L3.trim()) setAddLayer('L3', L3_PREFILL)
|
|
}, [tried, setAddLayer])
|
|
|
|
const onProceed = () => {
|
|
completePhase('m2')
|
|
navigate('/workshop/add')
|
|
}
|
|
|
|
return (
|
|
<section>
|
|
<PanelHeading
|
|
eyebrow="PHASE 4 OF 5 · ~90 MIN"
|
|
title="Module 2 · Skills & policies"
|
|
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 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>
|
|
|
|
<div className="mt-6 flex justify-end">
|
|
<ProceedButton disabled={!ready} onClick={onProceed}>
|
|
Proceed to Module 3 →
|
|
</ProceedButton>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|