Files
Socrates/docs/design-source/socrata/project/editor-shell.jsx
dtoro f1c4566576 Initial commit — design docs + Phase 0 validation harness
Sets up the Socrata project repo with:

docs/ — strategy and design documents
  - idea.md: full product vision
  - implementation-plan.md: Phase 0 + Phase 1 MVP plan
  - phase-0-validation.md: 2-week validation experiment strategy
  - phase-0-plan.md: concrete Phase 0 build plan
  - phase-0-results.md: Phase 0 gate outcome — GO for MVP
  - sysml-modeling.md: metamodel + SE discipline + validation rules
  - socrates.md: agent character, surfaces, modes, prompts, lifecycle
  - sync.md: bidirectional text↔diagram sync engineering
  - design-source/: HTML/CSS/JS handoff bundle from Claude Design

phase-0/ — validated harness (CLI, no UI, no DB)
  - LM Studio (local OpenAI-compatible) generation + detection + judge
  - PlantUML rendering for SysML model visualization
  - 10-seed corpus (8 working + 2 holdouts)
  - 5 corpus runs with iteration history in reports/
  - Final gate: 10/10 pass, mean 4.32/5, holdouts validated

Phase 1 MVP scope and milestones documented in implementation-plan.md.
2026-04-28 22:07:38 +02:00

211 lines
8.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// EditorShell — the dual-canvas workspace, themed by the wrapping artboard.
function TopBar({ data, presence }) {
return (
<header className="topbar">
<div className="topbar-left">
<div className="brand">
<span className="brand-name">Socrata</span>
</div>
<div className="breadcrumbs">
<span className="bc-sep">/</span>
<span className="bc-item">{data.project.scope}</span>
<span className="bc-sep">/</span>
<span className="bc-item bc-active">{data.project.name}</span>
<span className="bc-branch">
<span className="bc-branch-glyph"></span> {data.project.branch}
</span>
</div>
</div>
<div className="topbar-right">
<div className="sync-pill">
<span className="sync-dot" /> model in sync · {data.project.lastSync}
</div>
<div className="topbar-divider" />
<div className="avatar">MC</div>
</div>
</header>
);
}
function LeftRail({ data, focusBlockId, setFocusBlockId, density }) {
const [collapsed, setCollapsed] = React.useState(false);
const [open, setOpen] = React.useState({ outline: true, model: true, requirements: true });
const toggle = (k) => setOpen((s) => ({ ...s, [k]: !s[k] }));
if (collapsed) {
return (
<nav className="leftrail leftrail-collapsed">
<button className="rail-collapse-btn" onClick={() => setCollapsed(false)} title="Expand rail"></button>
<div className="rail-collapsed-stack">
<span className="rail-collapsed-tag" title="Outline">OUT</span>
<span className="rail-collapsed-tag" title="Model · 6 blocks">MOD</span>
<span className="rail-collapsed-tag" title="Requirements">REQ</span>
</div>
</nav>
);
}
return (
<nav className="leftrail">
<div className="rail-section">
<button className="rail-section-head" onClick={() => toggle("outline")}>
<span className={`rail-caret ${open.outline ? "rail-caret-open" : ""}`}></span>
<span className="rail-label">Outline</span>
</button>
{open.outline && (
<ul className="rail-list">
<li className="rail-item rail-item-active">
<span className="rail-item-text">Problem framing</span>
</li>
<li className="rail-item">
<span className="rail-item-text">Constraints</span>
<span className="rail-count rail-count-req">3</span>
</li>
<li className="rail-item">
<span className="rail-item-text">Why now</span>
</li>
<li className="rail-item rail-item-muted">
<span className="rail-item-text">Hypotheses</span>
<span className="rail-count rail-count-asm">3</span>
</li>
<li className="rail-item rail-item-muted">
<span className="rail-item-text">Open questions</span>
<span className="rail-count rail-count-q">5</span>
</li>
<li className="rail-item rail-item-muted">
<span className="rail-item-text">Risks</span>
<span className="rail-count rail-count-risk">2</span>
</li>
</ul>
)}
</div>
<div className="rail-section">
<button className="rail-section-head" onClick={() => toggle("model")}>
<span className={`rail-caret ${open.model ? "rail-caret-open" : ""}`}></span>
<span className="rail-label">Model</span>
</button>
{open.model && (
<ul className="rail-list rail-blocks">
{data.blocks.map((b) => (
<li
key={b.id}
className={`rail-block rail-${b.kind} ${focusBlockId === b.id ? "rail-block-active" : ""}`}
onMouseEnter={() => setFocusBlockId(b.id)}
onMouseLeave={() => setFocusBlockId(null)}
>
<span className="rail-block-glyph">
{b.kind === "constraint" ? "{}" : b.kind === "actor" ? "◐" : "▢"}
</span>
<span className="rail-block-label">{b.label}</span>
<span
className="rail-block-count"
title={`${b.properties.length} ${b.properties.length === 1 ? "property" : "properties"}`}
>
<span className="rail-block-count-glyph">·</span>
{b.properties.length}
</span>
</li>
))}
</ul>
)}
</div>
<div className="rail-section">
<button className="rail-section-head" onClick={() => toggle("requirements")}>
<span className={`rail-caret ${open.requirements ? "rail-caret-open" : ""}`}></span>
<span className="rail-label">Requirements</span>
</button>
{open.requirements && (
<ul className="rail-list">
<li className="rail-req"><span className="req-tag">REQ-001</span><span className="req-status req-traced" /></li>
<li className="rail-req"><span className="req-tag">REQ-002</span><span className="req-status req-traced" /></li>
<li className="rail-req"><span className="req-tag">REQ-003</span><span className="req-status req-untraced" /></li>
</ul>
)}
</div>
<button className="rail-collapse-btn rail-collapse-btn-bottom" onClick={() => setCollapsed(true)} title="Collapse rail"></button>
</nav>
);
}
function CanvasHeader({ title, subtitle, right }) {
return (
<div className="canvas-header">
<div>
<div className="canvas-title">{title}</div>
<div className="canvas-sub">{subtitle}</div>
</div>
<div className="canvas-header-right">{right}</div>
</div>
);
}
function EditorShell({ data, density, markupStyle, diagramStyle, presence }) {
const [focusBlockId, setFocusBlockId] = React.useState(null);
return (
<div className={`shell shell-density-${density} shell-presence-${presence}`}>
<TopBar data={data} presence={presence} />
<div className="shell-body">
<SocratesDock data={data} presence={presence} density={density} />
<LeftRail data={data} focusBlockId={focusBlockId} setFocusBlockId={setFocusBlockId} density={density} />
<main className="canvases">
<section className="canvas canvas-text">
<CanvasHeader
title="Narrative"
subtitle="Markup-augmented prose · synced to model"
right={null}
/>
<div className="canvas-scroll">
<TextCanvas
data={data}
density={density}
markupStyle={markupStyle}
focusBlockId={focusBlockId}
setFocusBlockId={setFocusBlockId}
/>
</div>
</section>
<div className="canvas-divider" />
<section className="canvas canvas-diagram">
<CanvasHeader
title="Model"
subtitle="SysML · 6 blocks · 6 associations · 1 constraint"
right={
<div className="canvas-actions">
<span className="canvas-mode-pill">Fit</span>
<span className="canvas-mode-pill canvas-mode-active">100%</span>
<span className="canvas-mode-pill">Layout</span>
</div>
}
/>
<div className="canvas-scroll canvas-scroll-diagram">
<DiagramCanvas data={data} density={density} variant={diagramStyle} focusBlockId={focusBlockId} onSelect={setFocusBlockId} />
<div className="diagram-legend">
<span><span className="legend-sw legend-block" /> block</span>
<span><span className="legend-sw legend-actor" /> actor</span>
<span><span className="legend-sw legend-constraint" /> constraint</span>
</div>
</div>
</section>
</main>
</div>
<footer className="statusbar">
<span>Socrata · v0.4 · Phase 1</span>
<span className="status-spacer" />
<span>3 assumptions open · 2 risks tracked · 1 proposal pending</span>
<span className="status-spacer" />
<span>{data.project.owner}</span>
</footer>
</div>
);
}
window.EditorShell = EditorShell;