Scaffold CommiTea: yarn workspaces, Electron shell, core label schema, design system

- apps/desktop: electron-vite + React + Tailwind mapped onto design tokens
  (preflight off; tokens/base.css owns the reset); boots to a Reginald
  placeholder proving fonts/tokens/core wiring
- packages/core: pure TS; gitea label schema (est/*, p/*, deadline/hard)
  with pessimistic conflict resolution + 15 unit tests
- docs/design: full design handoff (tokens, 16 component contracts,
  interactive 14-screen prototype, Reginald voice rules)
- docs/PLAN.md: product plan (purity rule, pm-state repo, deterministic
  scheduler + Monte Carlo, directive log)
- Deliberate deviation from novelpad stack: no ElectricSQL/PGlite — local
  store is a rebuildable cache over gitea REST/webhooks (better-sqlite3
  in main process, arriving in P1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Christian LeDoux
2026-07-07 20:42:46 -04:00
commit 7a5cacc54c
268 changed files with 15766 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
// Morning service — focus screen
function FocusScreen({ onOpenIssue }) {
const DS = window.CommiTeaDesignSystem_20e63b;
const { Card, Tag, Badge, Button, IconButton } = DS;
const d = window.CT_DATA;
const FocusRow = ({ slot, issue, jade }) => (
<Card overline={slot} jade={jade}
title={<a href="#" onClick={(e) => { e.preventDefault(); onOpenIssue(issue); }}
style={{ color: 'inherit', border: 'none' }}>{issue.title}</a>}
actions={<IconButton icon="ellipsis" label="More" size="sm" />}
footer={jade ? <>
<Button size="sm">Start</Button>
<Button size="sm" variant="ghost">Defer</Button>
<span style={{ marginLeft: 'auto', font: 'var(--text-caption)', color: 'var(--ink-3)' }}>scheduler pick · critical path</span>
</> : null}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, flexWrap: 'wrap' }}>
<span style={{ font: 'var(--text-data)', color: 'var(--ink-3)' }}>#{issue.id}</span>
{issue.labels.map((l) => <Tag key={l} label={l} />)}
{issue.steeping ? <Badge tone="warn" dot>steeping {issue.steeping}</Badge> : null}
</div>
<p style={{ font: 'var(--text-agent)', color: 'var(--ink-2)', margin: 0 }}>{issue.rationale}</p>
</Card>
);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<header style={{ borderBottom: 'var(--rule-double)', paddingBottom: 14, display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12 }}>
<div>
<h1 style={{ font: 'var(--text-display)', color: 'var(--ink-1)', margin: 0 }}>Morning service</h1>
<p style={{ font: 'var(--text-data)', color: 'var(--ink-3)', margin: '6px 0 0', whiteSpace: 'nowrap' }}>{d.today} · reconcile 3.2s</p>
</div>
<Badge tone="ok" dot>ahead of forecast</Badge>
</header>
<div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr 1fr', gap: 14, alignItems: 'start' }}>
<FocusRow slot="Now" issue={d.focus.now} jade />
<FocusRow slot="Next" issue={d.focus.next} />
<FocusRow slot="Later" issue={d.focus.later} />
</div>
<Card overline="Milestone · Beta" title={<>80% this lands <span style={{ whiteSpace: 'nowrap' }}>Mar 312</span></>}
actions={<IconButton icon="chart-line" label="Open runway" size="sm" />}>
<window.BurnUpCone />
<p style={{ font: 'var(--text-agent)', color: 'var(--ink-2)', margin: '10px 0 0' }}>
The cone has narrowed since Friday. I'm quietly pleased.
</p>
</Card>
</div>
);
}
Object.assign(window, { FocusScreen });