- 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>
6693 lines
205 KiB
JavaScript
6693 lines
205 KiB
JavaScript
/* @ds-bundle: {"format":4,"namespace":"CommiTeaDesignSystem_20e63b","components":[{"name":"Badge","sourcePath":"components/core/Badge.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Card","sourcePath":"components/core/Card.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Tabs","sourcePath":"components/core/Tabs.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"Dialog","sourcePath":"components/feedback/Dialog.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Tooltip","sourcePath":"components/feedback/Tooltip.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"Input","sourcePath":"components/forms/Input.jsx"},{"name":"Radio","sourcePath":"components/forms/Radio.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"}],"sourceHashes":{"components/core/Badge.jsx":"13c23a483d6d","components/core/Button.jsx":"ffc4f2a60c23","components/core/Card.jsx":"e4f4f0a376af","components/core/Icon.jsx":"1787a3656dc6","components/core/IconButton.jsx":"170d08e66f39","components/core/Tabs.jsx":"0f8158ee544f","components/core/Tag.jsx":"302fa43de0bd","components/feedback/Dialog.jsx":"73351848bd2e","components/feedback/Toast.jsx":"f9a033ad288d","components/feedback/Tooltip.jsx":"56a0f8711a27","components/forms/Checkbox.jsx":"4cb2969560f3","components/forms/Input.jsx":"094796149aa2","components/forms/Radio.jsx":"91f9c6b050f9","components/forms/Select.jsx":"9ff161748dde","components/forms/Switch.jsx":"f06333a8ce87","ui_kits/app/BoardScreen.jsx":"dbc1bd0a53b7","ui_kits/app/CalibrationScreen.jsx":"c91b96dc9bf5","ui_kits/app/CaptureScreen.jsx":"73340a249734","ui_kits/app/Chart.jsx":"15c1e3215058","ui_kits/app/ChatPanel.jsx":"339468410bb2","ui_kits/app/DepsGraph.jsx":"939049a86dda","ui_kits/app/DirectivesScreen.jsx":"e2b00e10749b","ui_kits/app/FocusScreen.jsx":"299cda1464ad","ui_kits/app/GanttView.jsx":"1f80d0b66429","ui_kits/app/InboxScreen.jsx":"e6cb39fc8ffe","ui_kits/app/IssueScreen.jsx":"4a796332482d","ui_kits/app/MilestoneScreen.jsx":"c2079e4d6380","ui_kits/app/OnboardingScreen.jsx":"640268f5031f","ui_kits/app/RunwayScreen.jsx":"038c4bfad5fe","ui_kits/app/SettingsScreen.jsx":"310bf0c6283b","ui_kits/app/Shell.jsx":"9135061e542a","ui_kits/app/StandupScreen.jsx":"70abb71f7c43","ui_kits/app/StatesGallery.jsx":"324b05e164e9","ui_kits/app/data.js":"df66d90a9521"},"inlinedExternals":[],"unexposedExports":[]} */
|
||
|
||
(() => {
|
||
|
||
const __ds_ns = (window.CommiTeaDesignSystem_20e63b = window.CommiTeaDesignSystem_20e63b || {});
|
||
|
||
const __ds_scope = {};
|
||
|
||
(__ds_ns.__errors = __ds_ns.__errors || []);
|
||
|
||
// components/core/Badge.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-badge {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
font: 500 12px/1 var(--font-sans);
|
||
padding: 4px 9px;
|
||
border-radius: var(--radius-round);
|
||
}
|
||
.ct-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
||
.ct-badge--ok { background: var(--ok-tint); color: var(--ok); }
|
||
.ct-badge--warn { background: var(--warn-tint); color: var(--warn); }
|
||
.ct-badge--danger { background: var(--danger-tint); color: var(--danger); }
|
||
.ct-badge--info { background: var(--info-tint); color: var(--info); }
|
||
.ct-badge--neutral { background: var(--paper-2); color: var(--ink-2); }
|
||
.ct-badge--jade { background: var(--jade-tint); color: var(--jade-7); }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-badge-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-badge-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Badge({
|
||
tone = 'neutral',
|
||
dot = false,
|
||
children,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("span", _extends({
|
||
className: `ct-badge ct-badge--${tone}`,
|
||
style: style
|
||
}, rest), dot ? /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-badge__dot"
|
||
}) : null, children);
|
||
}
|
||
Object.assign(__ds_scope, { Badge });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Badge.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/Card.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-card {
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: var(--radius-3);
|
||
box-shadow: var(--shadow-1);
|
||
}
|
||
.ct-card--jade { box-shadow: var(--shadow-jade-line), var(--shadow-1); }
|
||
.ct-card__header {
|
||
display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
|
||
padding: 16px 20px 0;
|
||
}
|
||
.ct-card__title {
|
||
font: var(--text-title);
|
||
color: var(--ink-1);
|
||
margin: 0;
|
||
}
|
||
.ct-card__overline {
|
||
font: var(--text-overline);
|
||
letter-spacing: var(--letter-spacing-wide);
|
||
text-transform: uppercase;
|
||
color: var(--ink-3);
|
||
margin: 0 0 6px;
|
||
}
|
||
.ct-card__body { padding: 14px 20px 18px; }
|
||
.ct-card__body--flush { padding: 0; }
|
||
.ct-card__footer {
|
||
display: flex; align-items: center; gap: 8px;
|
||
padding: 12px 20px;
|
||
border-top: 1px solid var(--border-hairline);
|
||
}
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-card-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-card-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Card({
|
||
title,
|
||
overline,
|
||
actions,
|
||
footer,
|
||
jade = false,
|
||
flush = false,
|
||
children,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("section", _extends({
|
||
className: `ct-card${jade ? ' ct-card--jade' : ''}`,
|
||
style: style
|
||
}, rest), title || overline || actions ? /*#__PURE__*/React.createElement("header", {
|
||
className: "ct-card__header"
|
||
}, /*#__PURE__*/React.createElement("div", null, overline ? /*#__PURE__*/React.createElement("p", {
|
||
className: "ct-card__overline"
|
||
}, overline) : null, title ? /*#__PURE__*/React.createElement("h2", {
|
||
className: "ct-card__title"
|
||
}, title) : null), actions ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: '4px',
|
||
flexShrink: 0
|
||
}
|
||
}, actions) : null) : null, /*#__PURE__*/React.createElement("div", {
|
||
className: `ct-card__body${flush ? ' ct-card__body--flush' : ''}`
|
||
}, children), footer ? /*#__PURE__*/React.createElement("footer", {
|
||
className: "ct-card__footer"
|
||
}, footer) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Card });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Card.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/Icon.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
/* Generated from assets/icons/*.svg (lucide-static v0.462.0, ISC). Do not edit paths by hand. */
|
||
const ICONS = {
|
||
"activity": "<path d=\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\"></path>",
|
||
"arrow-left": "<path d=\"m12 19-7-7 7-7\"></path>\n <path d=\"M19 12H5\"></path>",
|
||
"arrow-right": "<path d=\"M5 12h14\"></path>\n <path d=\"m12 5 7 7-7 7\"></path>",
|
||
"arrow-up-right": "<path d=\"M7 7h10v10\"></path>\n <path d=\"M7 17 17 7\"></path>",
|
||
"bell": "<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"></path>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"></path>",
|
||
"calendar": "<path d=\"M8 2v4\"></path>\n <path d=\"M16 2v4\"></path>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"></rect>\n <path d=\"M3 10h18\"></path>",
|
||
"chart-line": "<path d=\"M3 3v16a2 2 0 0 0 2 2h16\"></path>\n <path d=\"m19 9-5 5-4-4-3 3\"></path>",
|
||
"chart-no-axes-gantt": "<path d=\"M8 6h10\"></path>\n <path d=\"M6 12h9\"></path>\n <path d=\"M11 18h7\"></path>",
|
||
"check": "<path d=\"M20 6 9 17l-5-5\"></path>",
|
||
"chevron-down": "<path d=\"m6 9 6 6 6-6\"></path>",
|
||
"chevron-left": "<path d=\"m15 18-6-6 6-6\"></path>",
|
||
"chevron-right": "<path d=\"m9 18 6-6-6-6\"></path>",
|
||
"chevron-up": "<path d=\"m18 15-6-6-6 6\"></path>",
|
||
"circle-alert": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\"></line>\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\"></line>",
|
||
"circle-check": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <path d=\"m9 12 2 2 4-4\"></path>",
|
||
"circle-dashed": "<path d=\"M10.1 2.182a10 10 0 0 1 3.8 0\"></path>\n <path d=\"M13.9 21.818a10 10 0 0 1-3.8 0\"></path>\n <path d=\"M17.609 3.721a10 10 0 0 1 2.69 2.7\"></path>\n <path d=\"M2.182 13.9a10 10 0 0 1 0-3.8\"></path>\n <path d=\"M20.279 17.609a10 10 0 0 1-2.7 2.69\"></path>\n <path d=\"M21.818 10.1a10 10 0 0 1 0 3.8\"></path>\n <path d=\"M3.721 6.391a10 10 0 0 1 2.7-2.69\"></path>\n <path d=\"M6.391 20.279a10 10 0 0 1-2.69-2.7\"></path>",
|
||
"circle-dot": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"1\"></circle>",
|
||
"circle": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>",
|
||
"clock-3": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <polyline points=\"12 6 12 12 16.5 12\"></polyline>",
|
||
"clock": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <polyline points=\"12 6 12 12 16 14\"></polyline>",
|
||
"coffee": "<path d=\"M10 2v2\"></path>\n <path d=\"M14 2v2\"></path>\n <path d=\"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1\"></path>\n <path d=\"M6 2v2\"></path>",
|
||
"copy": "<rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"></rect>\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"></path>",
|
||
"ellipsis": "<circle cx=\"12\" cy=\"12\" r=\"1\"></circle>\n <circle cx=\"19\" cy=\"12\" r=\"1\"></circle>\n <circle cx=\"5\" cy=\"12\" r=\"1\"></circle>",
|
||
"external-link": "<path d=\"M15 3h6v6\"></path>\n <path d=\"M10 14 21 3\"></path>\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path>",
|
||
"eye": "<path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\"></path>\n <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>",
|
||
"filter": "<polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"></polygon>",
|
||
"flag": "<path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\"></path>\n <line x1=\"4\" x2=\"4\" y1=\"22\" y2=\"15\"></line>",
|
||
"gauge": "<path d=\"m12 14 4-4\"></path>\n <path d=\"M3.34 19a10 10 0 1 1 17.32 0\"></path>",
|
||
"git-branch": "<line x1=\"6\" x2=\"6\" y1=\"3\" y2=\"15\"></line>\n <circle cx=\"18\" cy=\"6\" r=\"3\"></circle>\n <circle cx=\"6\" cy=\"18\" r=\"3\"></circle>\n <path d=\"M18 9a9 9 0 0 1-9 9\"></path>",
|
||
"git-commit-horizontal": "<circle cx=\"12\" cy=\"12\" r=\"3\"></circle>\n <line x1=\"3\" x2=\"9\" y1=\"12\" y2=\"12\"></line>\n <line x1=\"15\" x2=\"21\" y1=\"12\" y2=\"12\"></line>",
|
||
"git-merge": "<circle cx=\"18\" cy=\"18\" r=\"3\"></circle>\n <circle cx=\"6\" cy=\"6\" r=\"3\"></circle>\n <path d=\"M6 21V9a9 9 0 0 0 9 9\"></path>",
|
||
"git-pull-request": "<circle cx=\"18\" cy=\"18\" r=\"3\"></circle>\n <circle cx=\"6\" cy=\"6\" r=\"3\"></circle>\n <path d=\"M13 6h3a2 2 0 0 1 2 2v7\"></path>\n <line x1=\"6\" x2=\"6\" y1=\"9\" y2=\"21\"></line>",
|
||
"history": "<path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"></path>\n <path d=\"M3 3v5h5\"></path>\n <path d=\"M12 7v5l4 2\"></path>",
|
||
"inbox": "<polyline points=\"22 12 16 12 14 15 10 15 8 12 2 12\"></polyline>\n <path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\"></path>",
|
||
"info": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <path d=\"M12 16v-4\"></path>\n <path d=\"M12 8h.01\"></path>",
|
||
"keyboard": "<path d=\"M10 8h.01\"></path>\n <path d=\"M12 12h.01\"></path>\n <path d=\"M14 8h.01\"></path>\n <path d=\"M16 12h.01\"></path>\n <path d=\"M18 8h.01\"></path>\n <path d=\"M6 8h.01\"></path>\n <path d=\"M7 16h10\"></path>\n <path d=\"M8 12h.01\"></path>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"></rect>",
|
||
"layers": "<path d=\"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z\"></path>\n <path d=\"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65\"></path>\n <path d=\"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65\"></path>",
|
||
"leaf": "<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"></path>\n <path d=\"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12\"></path>",
|
||
"link": "<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"></path>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"></path>",
|
||
"list-filter": "<path d=\"M3 6h18\"></path>\n <path d=\"M7 12h10\"></path>\n <path d=\"M10 18h4\"></path>",
|
||
"list": "<path d=\"M3 12h.01\"></path>\n <path d=\"M3 18h.01\"></path>\n <path d=\"M3 6h.01\"></path>\n <path d=\"M8 12h13\"></path>\n <path d=\"M8 18h13\"></path>\n <path d=\"M8 6h13\"></path>",
|
||
"loader-circle": "<path d=\"M21 12a9 9 0 1 1-6.219-8.56\"></path>",
|
||
"message-square": "<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>",
|
||
"milestone": "<path d=\"M12 13v8\"></path>\n <path d=\"M12 3v3\"></path>\n <path d=\"M4 6a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h13a2 2 0 0 0 1.152-.365l3.424-2.317a1 1 0 0 0 0-1.635l-3.424-2.318A2 2 0 0 0 17 6z\"></path>",
|
||
"minus": "<path d=\"M5 12h14\"></path>",
|
||
"moon": "<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"></path>",
|
||
"network": "<rect x=\"16\" y=\"16\" width=\"6\" height=\"6\" rx=\"1\"></rect>\n <rect x=\"2\" y=\"16\" width=\"6\" height=\"6\" rx=\"1\"></rect>\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"6\" rx=\"1\"></rect>\n <path d=\"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3\"></path>\n <path d=\"M12 12V8\"></path>",
|
||
"panel-left": "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"></rect>\n <path d=\"M9 3v18\"></path>",
|
||
"pause": "<rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"></rect>\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"></rect>",
|
||
"pencil": "<path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\"></path>\n <path d=\"m15 5 4 4\"></path>",
|
||
"play": "<polygon points=\"6 3 20 12 6 21 6 3\"></polygon>",
|
||
"plus": "<path d=\"M5 12h14\"></path>\n <path d=\"M12 5v14\"></path>",
|
||
"refresh-cw": "<path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"></path>\n <path d=\"M21 3v5h-5\"></path>\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\"></path>\n <path d=\"M8 16H3v5\"></path>",
|
||
"search": "<circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <path d=\"m21 21-4.3-4.3\"></path>",
|
||
"send": "<path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\"></path>\n <path d=\"m21.854 2.147-10.94 10.939\"></path>",
|
||
"settings-2": "<path d=\"M20 7h-9\"></path>\n <path d=\"M14 17H5\"></path>\n <circle cx=\"17\" cy=\"17\" r=\"3\"></circle>\n <circle cx=\"7\" cy=\"7\" r=\"3\"></circle>",
|
||
"settings": "<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"></path>\n <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>",
|
||
"sparkles": "<path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\"></path>\n <path d=\"M20 3v4\"></path>\n <path d=\"M22 5h-4\"></path>\n <path d=\"M4 17v2\"></path>\n <path d=\"M5 18H3\"></path>",
|
||
"square-kanban": "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"></rect>\n <path d=\"M8 7v7\"></path>\n <path d=\"M12 7v4\"></path>\n <path d=\"M16 7v9\"></path>",
|
||
"sun": "<circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\n <path d=\"M12 2v2\"></path>\n <path d=\"M12 20v2\"></path>\n <path d=\"m4.93 4.93 1.41 1.41\"></path>\n <path d=\"m17.66 17.66 1.41 1.41\"></path>\n <path d=\"M2 12h2\"></path>\n <path d=\"M20 12h2\"></path>\n <path d=\"m6.34 17.66-1.41 1.41\"></path>\n <path d=\"m19.07 4.93-1.41 1.41\"></path>",
|
||
"tag": "<path d=\"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\"></path>\n <circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"></circle>",
|
||
"target": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"6\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"2\"></circle>",
|
||
"trash-2": "<path d=\"M3 6h18\"></path>\n <path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"></path>\n <path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"></path>\n <line x1=\"10\" x2=\"10\" y1=\"11\" y2=\"17\"></line>\n <line x1=\"14\" x2=\"14\" y1=\"11\" y2=\"17\"></line>",
|
||
"trending-up": "<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"></polyline>\n <polyline points=\"16 7 22 7 22 13\"></polyline>",
|
||
"triangle-alert": "<path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"></path>\n <path d=\"M12 9v4\"></path>\n <path d=\"M12 17h.01\"></path>",
|
||
"user": "<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"></path>\n <circle cx=\"12\" cy=\"7\" r=\"4\"></circle>",
|
||
"users": "<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"></path>\n <circle cx=\"9\" cy=\"7\" r=\"4\"></circle>\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"></path>\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\"></path>",
|
||
"x": "<path d=\"M18 6 6 18\"></path>\n <path d=\"m6 6 12 12\"></path>",
|
||
"zap": "<path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\"></path>"
|
||
};
|
||
function Icon({
|
||
name,
|
||
size = 16,
|
||
strokeWidth = 1.5,
|
||
title,
|
||
style,
|
||
...rest
|
||
}) {
|
||
const inner = ICONS[name];
|
||
if (!inner) {
|
||
console.warn('[CommiTea Icon] unknown icon: ' + name);
|
||
return null;
|
||
}
|
||
return /*#__PURE__*/React.createElement("svg", _extends({
|
||
width: size,
|
||
height: size,
|
||
viewBox: "0 0 24 24",
|
||
fill: "none",
|
||
stroke: "currentColor",
|
||
strokeWidth: strokeWidth,
|
||
strokeLinecap: "round",
|
||
strokeLinejoin: "round",
|
||
"aria-hidden": title ? undefined : true,
|
||
role: title ? 'img' : undefined,
|
||
"aria-label": title,
|
||
style: {
|
||
flexShrink: 0,
|
||
...style
|
||
},
|
||
dangerouslySetInnerHTML: {
|
||
__html: inner
|
||
}
|
||
}, rest));
|
||
}
|
||
const ICON_NAMES = Object.keys(ICONS);
|
||
Object.assign(__ds_scope, { Icon, ICON_NAMES });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Icon.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/Button.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-btn {
|
||
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
||
font: 600 14px/1 var(--font-sans);
|
||
border-radius: var(--radius-2);
|
||
border: 1px solid transparent;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
transition: background var(--duration-fast) var(--ease-out),
|
||
border-color var(--duration-fast) var(--ease-out),
|
||
color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||
.ct-btn--md { height: 34px; padding: 0 14px; }
|
||
.ct-btn--sm { height: 28px; padding: 0 10px; font-size: 13px; }
|
||
.ct-btn--primary { background: var(--accent); color: var(--text-on-accent); }
|
||
.ct-btn--primary:hover:not(:disabled) { background: var(--accent-hover); }
|
||
.ct-btn--primary:active:not(:disabled) { background: var(--accent-pressed); }
|
||
.ct-btn--secondary { background: var(--surface-card); border-color: var(--line-2); color: var(--ink-1); }
|
||
.ct-btn--secondary:hover:not(:disabled) { background: var(--paper-2); }
|
||
.ct-btn--secondary:active:not(:disabled) { background: var(--paper-3); }
|
||
.ct-btn--ghost { background: transparent; color: var(--ink-2); }
|
||
.ct-btn--ghost:hover:not(:disabled) { background: var(--paper-2); color: var(--ink-1); }
|
||
.ct-btn--ghost:active:not(:disabled) { background: var(--paper-3); }
|
||
.ct-btn--danger { background: var(--danger); color: var(--ink-inverse); }
|
||
.ct-btn--danger:hover:not(:disabled) { filter: brightness(0.92); }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-button-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-button-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Button({
|
||
variant = 'primary',
|
||
size = 'md',
|
||
icon,
|
||
iconRight,
|
||
disabled = false,
|
||
children,
|
||
style,
|
||
...rest
|
||
}) {
|
||
const iconSize = size === 'sm' ? 15 : 17;
|
||
return /*#__PURE__*/React.createElement("button", _extends({
|
||
type: "button",
|
||
className: `ct-btn ct-btn--${size} ct-btn--${variant}`,
|
||
disabled: disabled,
|
||
style: style
|
||
}, rest), icon ? /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: icon,
|
||
size: iconSize
|
||
}) : null, children, iconRight ? /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: iconRight,
|
||
size: iconSize
|
||
}) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Button });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Button.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/IconButton.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-iconbtn {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
border-radius: var(--radius-2);
|
||
border: 1px solid transparent;
|
||
background: transparent;
|
||
color: var(--ink-2);
|
||
cursor: pointer;
|
||
transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-iconbtn:hover:not(:disabled) { background: var(--paper-2); color: var(--ink-1); }
|
||
.ct-iconbtn:active:not(:disabled) { background: var(--paper-3); }
|
||
.ct-iconbtn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||
.ct-iconbtn--md { width: 34px; height: 34px; }
|
||
.ct-iconbtn--sm { width: 28px; height: 28px; }
|
||
.ct-iconbtn--outline { border-color: var(--line-2); background: var(--surface-card); }
|
||
.ct-iconbtn--outline:hover:not(:disabled) { background: var(--paper-2); }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-iconbtn-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-iconbtn-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function IconButton({
|
||
icon,
|
||
label,
|
||
variant = 'ghost',
|
||
size = 'md',
|
||
disabled = false,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("button", _extends({
|
||
type: "button",
|
||
className: `ct-iconbtn ct-iconbtn--${size}${variant === 'outline' ? ' ct-iconbtn--outline' : ''}`,
|
||
"aria-label": label,
|
||
title: label,
|
||
disabled: disabled,
|
||
style: style
|
||
}, rest), /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: icon,
|
||
size: size === 'sm' ? 15 : 17
|
||
}));
|
||
}
|
||
Object.assign(__ds_scope, { IconButton });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/IconButton.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/Tabs.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-tabs {
|
||
display: flex; gap: 2px;
|
||
border-bottom: 1px solid var(--border-hairline);
|
||
}
|
||
.ct-tab {
|
||
display: inline-flex; align-items: center; gap: 7px;
|
||
font: 500 13.5px/1 var(--font-sans);
|
||
color: var(--ink-2);
|
||
background: none; border: none;
|
||
padding: 10px 12px;
|
||
margin-bottom: -1px;
|
||
border-bottom: 2px solid transparent;
|
||
cursor: pointer;
|
||
transition: color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-tab:hover { color: var(--ink-1); }
|
||
.ct-tab--active {
|
||
color: var(--ink-1);
|
||
font-weight: 600;
|
||
border-bottom-color: var(--accent);
|
||
}
|
||
.ct-tab__count { font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-tabs-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-tabs-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Tabs({
|
||
items,
|
||
active,
|
||
onChange,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("div", _extends({
|
||
className: "ct-tabs",
|
||
role: "tablist",
|
||
style: style
|
||
}, rest), items.map(item => /*#__PURE__*/React.createElement("button", {
|
||
key: item.id,
|
||
type: "button",
|
||
role: "tab",
|
||
"aria-selected": item.id === active,
|
||
className: `ct-tab${item.id === active ? ' ct-tab--active' : ''}`,
|
||
onClick: () => onChange && onChange(item.id)
|
||
}, item.icon ? /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: item.icon,
|
||
size: 15
|
||
}) : null, item.label, item.count != null ? /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-tab__count"
|
||
}, item.count) : null)));
|
||
}
|
||
Object.assign(__ds_scope, { Tabs });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Tabs.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/Tag.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-tag {
|
||
display: inline-flex; align-items: center; gap: 5px;
|
||
font: 500 11.5px/1 var(--font-mono);
|
||
letter-spacing: var(--letter-spacing-label);
|
||
padding: 4px 9px;
|
||
border-radius: var(--radius-round);
|
||
white-space: nowrap;
|
||
}
|
||
.ct-tag--est { background: var(--label-est-bg); color: var(--label-est-text); }
|
||
.ct-tag--p1 { background: var(--danger-tint); color: var(--label-p1); }
|
||
.ct-tag--p2 { background: var(--warn-tint); color: var(--label-p2); }
|
||
.ct-tag--p3 { background: var(--info-tint); color: var(--label-p3); }
|
||
.ct-tag--p4 { background: var(--paper-2); color: var(--label-p4); }
|
||
.ct-tag--hard { background: var(--label-hard); color: var(--ink-inverse); }
|
||
.ct-tag--plain { background: var(--paper-2); color: var(--ink-2); }
|
||
.ct-tag__x {
|
||
display: inline-flex; padding: 0; margin: 0 -3px 0 0;
|
||
background: none; border: none; color: inherit; cursor: pointer; opacity: 0.6;
|
||
}
|
||
.ct-tag__x:hover { opacity: 1; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-tag-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-tag-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function toneFor(label) {
|
||
if (label.startsWith('est/')) return 'est';
|
||
if (label === 'p/1') return 'p1';
|
||
if (label === 'p/2') return 'p2';
|
||
if (label === 'p/3') return 'p3';
|
||
if (label === 'p/4') return 'p4';
|
||
if (label === 'deadline/hard') return 'hard';
|
||
return 'plain';
|
||
}
|
||
function Tag({
|
||
label,
|
||
onRemove,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("span", _extends({
|
||
className: `ct-tag ct-tag--${toneFor(label)}`,
|
||
style: style
|
||
}, rest), label, onRemove ? /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
className: "ct-tag__x",
|
||
"aria-label": `Remove ${label}`,
|
||
onClick: onRemove
|
||
}, /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: "x",
|
||
size: 11,
|
||
strokeWidth: 2
|
||
})) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Tag });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Tag.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/feedback/Dialog.jsx
|
||
try { (() => {
|
||
const CSS = `
|
||
.ct-dialog-scrim {
|
||
position: fixed; inset: 0;
|
||
background: rgba(32, 38, 29, 0.4);
|
||
display: flex; align-items: center; justify-content: center;
|
||
z-index: 100;
|
||
animation: ct-dialog-fade var(--duration-base) var(--ease-out);
|
||
}
|
||
.ct-dialog {
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: var(--radius-3);
|
||
box-shadow: var(--shadow-3);
|
||
width: min(480px, calc(100vw - 48px));
|
||
max-height: calc(100vh - 96px);
|
||
display: flex; flex-direction: column;
|
||
animation: ct-dialog-rise var(--duration-base) var(--ease-out);
|
||
}
|
||
.ct-dialog__header {
|
||
display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
|
||
padding: 20px 20px 12px;
|
||
border-bottom: 3px double var(--border-strong);
|
||
margin: 0 20px; padding-left: 0; padding-right: 0;
|
||
}
|
||
.ct-dialog__title { font: var(--text-title); color: var(--ink-1); margin: 0; }
|
||
.ct-dialog__body { padding: 16px 20px; overflow-y: auto; font: var(--text-body); color: var(--ink-1); }
|
||
.ct-dialog__footer {
|
||
display: flex; justify-content: flex-end; gap: 8px;
|
||
padding: 12px 20px 20px;
|
||
}
|
||
@keyframes ct-dialog-fade { from { opacity: 0; } }
|
||
@keyframes ct-dialog-rise { from { opacity: 0; transform: translateY(8px); } }
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.ct-dialog-scrim, .ct-dialog { animation: none; }
|
||
}
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-dialog-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-dialog-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Dialog({
|
||
open,
|
||
onClose,
|
||
title,
|
||
footer,
|
||
children,
|
||
style
|
||
}) {
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onKey = e => {
|
||
if (e.key === 'Escape' && onClose) onClose();
|
||
};
|
||
document.addEventListener('keydown', onKey);
|
||
return () => document.removeEventListener('keydown', onKey);
|
||
}, [open, onClose]);
|
||
if (!open) return null;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-dialog-scrim",
|
||
onClick: e => {
|
||
if (e.target === e.currentTarget && onClose) onClose();
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-dialog",
|
||
role: "dialog",
|
||
"aria-modal": "true",
|
||
style: style
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
className: "ct-dialog__header"
|
||
}, /*#__PURE__*/React.createElement("h2", {
|
||
className: "ct-dialog__title"
|
||
}, title), onClose ? /*#__PURE__*/React.createElement(__ds_scope.IconButton, {
|
||
icon: "x",
|
||
label: "Close",
|
||
size: "sm",
|
||
onClick: onClose
|
||
}) : null), /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-dialog__body"
|
||
}, children), footer ? /*#__PURE__*/React.createElement("footer", {
|
||
className: "ct-dialog__footer"
|
||
}, footer) : null));
|
||
}
|
||
Object.assign(__ds_scope, { Dialog });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/feedback/Dialog.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/feedback/Toast.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-toast {
|
||
display: flex; align-items: flex-start; gap: 10px;
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: var(--radius-2);
|
||
box-shadow: var(--shadow-2);
|
||
padding: 12px 14px;
|
||
max-width: 420px;
|
||
font: var(--text-body);
|
||
color: var(--ink-1);
|
||
animation: ct-toast-in var(--duration-slow) var(--ease-out);
|
||
}
|
||
.ct-toast__icon { display: flex; margin-top: 1px; }
|
||
.ct-toast--ok .ct-toast__icon { color: var(--ok); }
|
||
.ct-toast--warn .ct-toast__icon { color: var(--warn); }
|
||
.ct-toast--danger .ct-toast__icon { color: var(--danger); }
|
||
.ct-toast--info .ct-toast__icon { color: var(--info); }
|
||
.ct-toast__content { flex: 1; min-width: 0; }
|
||
.ct-toast__title { font: var(--text-body-strong); margin: 0 0 2px; }
|
||
@keyframes ct-toast-in { from { opacity: 0; transform: translateY(6px); } }
|
||
@media (prefers-reduced-motion: reduce) { .ct-toast { animation: none; } }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-toast-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-toast-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
const TOAST_ICONS = {
|
||
ok: 'circle-check',
|
||
warn: 'triangle-alert',
|
||
danger: 'circle-alert',
|
||
info: 'info'
|
||
};
|
||
function Toast({
|
||
tone = 'info',
|
||
title,
|
||
onDismiss,
|
||
children,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("div", _extends({
|
||
className: `ct-toast ct-toast--${tone}`,
|
||
role: "status",
|
||
style: style
|
||
}, rest), /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-toast__icon"
|
||
}, /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: TOAST_ICONS[tone],
|
||
size: 16
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-toast__content"
|
||
}, title ? /*#__PURE__*/React.createElement("p", {
|
||
className: "ct-toast__title"
|
||
}, title) : null, children), onDismiss ? /*#__PURE__*/React.createElement(__ds_scope.IconButton, {
|
||
icon: "x",
|
||
label: "Dismiss",
|
||
size: "sm",
|
||
onClick: onDismiss
|
||
}) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Toast });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/feedback/Toast.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/feedback/Tooltip.jsx
|
||
try { (() => {
|
||
const CSS = `
|
||
.ct-tooltip-wrap { position: relative; display: inline-flex; }
|
||
.ct-tooltip {
|
||
position: absolute; bottom: calc(100% + 7px); left: 50%;
|
||
transform: translateX(-50%) translateY(2px);
|
||
background: var(--ink-1);
|
||
color: var(--ink-inverse);
|
||
font: 500 12px/1.4 var(--font-sans);
|
||
padding: 5px 9px;
|
||
border-radius: var(--radius-1);
|
||
white-space: nowrap;
|
||
pointer-events: none;
|
||
opacity: 0;
|
||
transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
|
||
z-index: 50;
|
||
}
|
||
.ct-tooltip--bottom { bottom: auto; top: calc(100% + 7px); transform: translateX(-50%) translateY(-2px); }
|
||
.ct-tooltip-wrap:hover .ct-tooltip,
|
||
.ct-tooltip-wrap:focus-within .ct-tooltip {
|
||
opacity: 1;
|
||
transform: translateX(-50%) translateY(0);
|
||
}
|
||
.ct-tooltip code { font: 500 11px var(--font-mono); }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-tooltip-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-tooltip-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Tooltip({
|
||
content,
|
||
side = 'top',
|
||
children,
|
||
style
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-tooltip-wrap",
|
||
style: style
|
||
}, children, /*#__PURE__*/React.createElement("span", {
|
||
className: `ct-tooltip${side === 'bottom' ? ' ct-tooltip--bottom' : ''}`,
|
||
role: "tooltip"
|
||
}, content));
|
||
}
|
||
Object.assign(__ds_scope, { Tooltip });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/feedback/Tooltip.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Checkbox.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-check { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font: var(--text-body); color: var(--ink-1); }
|
||
.ct-check--disabled { opacity: 0.5; cursor: not-allowed; }
|
||
.ct-check__input { position: absolute; opacity: 0; width: 0; height: 0; }
|
||
.ct-check__box {
|
||
width: 16px; height: 16px; flex-shrink: 0;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--line-2);
|
||
border-radius: var(--radius-1);
|
||
color: transparent;
|
||
transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-check:hover:not(.ct-check--disabled) .ct-check__box { border-color: var(--border-strong); }
|
||
.ct-check__input:checked + .ct-check__box { background: var(--accent); border-color: var(--accent); color: var(--ink-inverse); }
|
||
.ct-check__input:focus-visible + .ct-check__box { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-check-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-check-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Checkbox({
|
||
label,
|
||
checked,
|
||
onChange,
|
||
disabled = false,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: `ct-check${disabled ? ' ct-check--disabled' : ''}`,
|
||
style: style
|
||
}, /*#__PURE__*/React.createElement("input", _extends({
|
||
type: "checkbox",
|
||
className: "ct-check__input",
|
||
checked: checked,
|
||
onChange: onChange,
|
||
disabled: disabled
|
||
}, rest)), /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-check__box"
|
||
}, /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: "check",
|
||
size: 12,
|
||
strokeWidth: 2.5
|
||
})), label ? /*#__PURE__*/React.createElement("span", null, label) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Checkbox });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Checkbox.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Input.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-field { display: flex; flex-direction: column; gap: 6px; }
|
||
.ct-field__label { font: 600 13px/1.2 var(--font-sans); color: var(--ink-1); }
|
||
.ct-field__wrap { position: relative; display: flex; align-items: center; }
|
||
.ct-field__icon { position: absolute; left: 10px; color: var(--ink-3); pointer-events: none; display: flex; }
|
||
.ct-input {
|
||
width: 100%; height: 34px;
|
||
font: var(--text-body);
|
||
color: var(--ink-1);
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--line-2);
|
||
border-radius: var(--radius-2);
|
||
padding: 0 12px;
|
||
transition: border-color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-input::placeholder { color: var(--ink-3); }
|
||
.ct-input:hover:not(:disabled):not(:focus) { border-color: var(--border-strong); background: var(--paper-1); }
|
||
.ct-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
||
.ct-input:disabled { opacity: 0.5; background: var(--paper-2); cursor: not-allowed; }
|
||
.ct-input--icon { padding-left: 32px; }
|
||
.ct-input--error { border-color: var(--danger); }
|
||
.ct-input--error:focus { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
|
||
.ct-input--mono { font: var(--text-data); }
|
||
.ct-field__hint { font: var(--text-caption); color: var(--ink-3); margin: 0; }
|
||
.ct-field__error { font: var(--text-caption); color: var(--danger); margin: 0; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-input-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-input-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Input({
|
||
label,
|
||
hint,
|
||
error,
|
||
icon,
|
||
mono = false,
|
||
style,
|
||
...rest
|
||
}) {
|
||
const cls = ['ct-input', icon ? 'ct-input--icon' : '', error ? 'ct-input--error' : '', mono ? 'ct-input--mono' : ''].filter(Boolean).join(' ');
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-field",
|
||
style: style
|
||
}, label ? /*#__PURE__*/React.createElement("label", {
|
||
className: "ct-field__label"
|
||
}, label) : null, /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-field__wrap"
|
||
}, icon ? /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-field__icon"
|
||
}, /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: icon,
|
||
size: 15
|
||
})) : null, /*#__PURE__*/React.createElement("input", _extends({
|
||
className: cls
|
||
}, rest))), error ? /*#__PURE__*/React.createElement("p", {
|
||
className: "ct-field__error"
|
||
}, error) : hint ? /*#__PURE__*/React.createElement("p", {
|
||
className: "ct-field__hint"
|
||
}, hint) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Input });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Input.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Radio.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-radio { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font: var(--text-body); color: var(--ink-1); }
|
||
.ct-radio--disabled { opacity: 0.5; cursor: not-allowed; }
|
||
.ct-radio__input { position: absolute; opacity: 0; width: 0; height: 0; }
|
||
.ct-radio__dot {
|
||
width: 16px; height: 16px; flex-shrink: 0;
|
||
border: 1px solid var(--line-2);
|
||
border-radius: 50%;
|
||
background: var(--surface-card);
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
transition: border-color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-radio__dot::after {
|
||
content: '';
|
||
width: 8px; height: 8px; border-radius: 50%;
|
||
background: transparent;
|
||
transition: background var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-radio:hover:not(.ct-radio--disabled) .ct-radio__dot { border-color: var(--border-strong); }
|
||
.ct-radio__input:checked + .ct-radio__dot { border-color: var(--accent); }
|
||
.ct-radio__input:checked + .ct-radio__dot::after { background: var(--accent); }
|
||
.ct-radio__input:focus-visible + .ct-radio__dot { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-radio-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-radio-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Radio({
|
||
label,
|
||
checked,
|
||
onChange,
|
||
name,
|
||
value,
|
||
disabled = false,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: `ct-radio${disabled ? ' ct-radio--disabled' : ''}`,
|
||
style: style
|
||
}, /*#__PURE__*/React.createElement("input", _extends({
|
||
type: "radio",
|
||
className: "ct-radio__input",
|
||
checked: checked,
|
||
onChange: onChange,
|
||
name: name,
|
||
value: value,
|
||
disabled: disabled
|
||
}, rest)), /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-radio__dot"
|
||
}), label ? /*#__PURE__*/React.createElement("span", null, label) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Radio });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Radio.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Select.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-select-field { display: flex; flex-direction: column; gap: 6px; }
|
||
.ct-select-field__label { font: 600 13px/1.2 var(--font-sans); color: var(--ink-1); }
|
||
.ct-select__wrap { position: relative; display: flex; align-items: center; }
|
||
.ct-select {
|
||
width: 100%; height: 34px;
|
||
font: var(--text-body);
|
||
color: var(--ink-1);
|
||
background: var(--surface-card);
|
||
border: 1px solid var(--line-2);
|
||
border-radius: var(--radius-2);
|
||
padding: 0 30px 0 12px;
|
||
appearance: none;
|
||
cursor: pointer;
|
||
transition: border-color var(--duration-fast) var(--ease-out);
|
||
}
|
||
.ct-select:hover:not(:disabled):not(:focus) { border-color: var(--border-strong); }
|
||
.ct-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
||
.ct-select:disabled { opacity: 0.5; cursor: not-allowed; }
|
||
.ct-select__chevron { position: absolute; right: 10px; color: var(--ink-3); pointer-events: none; display: flex; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-select-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-select-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Select({
|
||
label,
|
||
options,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-select-field",
|
||
style: style
|
||
}, label ? /*#__PURE__*/React.createElement("label", {
|
||
className: "ct-select-field__label"
|
||
}, label) : null, /*#__PURE__*/React.createElement("div", {
|
||
className: "ct-select__wrap"
|
||
}, /*#__PURE__*/React.createElement("select", _extends({
|
||
className: "ct-select"
|
||
}, rest), options.map(o => /*#__PURE__*/React.createElement("option", {
|
||
key: o.value,
|
||
value: o.value
|
||
}, o.label))), /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-select__chevron"
|
||
}, /*#__PURE__*/React.createElement(__ds_scope.Icon, {
|
||
name: "chevron-down",
|
||
size: 15
|
||
}))));
|
||
}
|
||
Object.assign(__ds_scope, { Select });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Select.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Switch.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
const CSS = `
|
||
.ct-switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font: var(--text-body); color: var(--ink-1); }
|
||
.ct-switch--disabled { opacity: 0.5; cursor: not-allowed; }
|
||
.ct-switch__input { position: absolute; opacity: 0; width: 0; height: 0; }
|
||
.ct-switch__track {
|
||
width: 34px; height: 20px; flex-shrink: 0;
|
||
border-radius: var(--radius-round);
|
||
background: var(--paper-3);
|
||
border: 1px solid var(--line-2);
|
||
position: relative;
|
||
transition: background var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-out);
|
||
}
|
||
.ct-switch__track::after {
|
||
content: '';
|
||
position: absolute; top: 2px; left: 2px;
|
||
width: 14px; height: 14px; border-radius: 50%;
|
||
background: var(--surface-card);
|
||
box-shadow: var(--shadow-1);
|
||
transition: transform var(--duration-base) var(--ease-out);
|
||
}
|
||
.ct-switch__input:checked + .ct-switch__track { background: var(--accent); border-color: var(--accent); }
|
||
.ct-switch__input:checked + .ct-switch__track::after { transform: translateX(14px); }
|
||
.ct-switch__input:focus-visible + .ct-switch__track { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-switch-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-switch-css';
|
||
s.textContent = CSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function Switch({
|
||
label,
|
||
checked,
|
||
onChange,
|
||
disabled = false,
|
||
style,
|
||
...rest
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: `ct-switch${disabled ? ' ct-switch--disabled' : ''}`,
|
||
style: style
|
||
}, /*#__PURE__*/React.createElement("input", _extends({
|
||
type: "checkbox",
|
||
role: "switch",
|
||
className: "ct-switch__input",
|
||
checked: checked,
|
||
onChange: onChange,
|
||
disabled: disabled
|
||
}, rest)), /*#__PURE__*/React.createElement("span", {
|
||
className: "ct-switch__track"
|
||
}), label ? /*#__PURE__*/React.createElement("span", null, label) : null);
|
||
}
|
||
Object.assign(__ds_scope, { Switch });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Switch.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/BoardScreen.jsx
|
||
try { (() => {
|
||
// Board — kanban over inferred lifecycle, with Gantt/Dependencies stubs
|
||
function BoardScreen({
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Tag,
|
||
Badge,
|
||
Tabs,
|
||
IconButton,
|
||
Input,
|
||
Icon
|
||
} = DS;
|
||
const d = window.CT_DATA;
|
||
const [tab, setTab] = React.useState('board');
|
||
const [query, setQuery] = React.useState('');
|
||
const q = query.trim().toLowerCase();
|
||
const filtered = d.columns.map(c => ({
|
||
...c,
|
||
issues: q ? c.issues.filter(i => (i.title + ' #' + i.id).toLowerCase().includes(q)) : c.issues
|
||
}));
|
||
const anyMatch = filtered.some(c => c.issues.length > 0);
|
||
const openCount = d.columns.reduce((n, c) => n + (c.id === 'done' ? 0 : c.issues.length), 0);
|
||
const IssueCard = ({
|
||
issue
|
||
}) => /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => onOpenIssue(issue),
|
||
style: {
|
||
background: 'var(--surface-card)',
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '10px 12px',
|
||
cursor: 'pointer',
|
||
boxShadow: 'var(--shadow-1)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.borderColor = 'var(--line-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.borderColor = 'var(--line-1)';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-small)',
|
||
fontWeight: 500,
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, issue.title), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "#", issue.id), issue.labels.map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l,
|
||
style: {
|
||
transform: 'scale(0.95)',
|
||
transformOrigin: 'left center'
|
||
}
|
||
})), issue.days ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--warn)'
|
||
}
|
||
}, issue.days) : null, issue.pr ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 3,
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--info)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "git-pull-request",
|
||
size: 12
|
||
}), issue.pr) : null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
width: 20,
|
||
height: 20,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 9px/20px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, issue.who)));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14,
|
||
height: '100%',
|
||
minHeight: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0,
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "The pot"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
width: 240
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
icon: "search",
|
||
placeholder: "Search the pot\u2026",
|
||
value: query,
|
||
onChange: e => setQuery(e.target.value)
|
||
}))), /*#__PURE__*/React.createElement(Tabs, {
|
||
items: [{
|
||
id: 'board',
|
||
label: 'Board',
|
||
icon: 'square-kanban',
|
||
count: openCount
|
||
}, {
|
||
id: 'gantt',
|
||
label: 'Gantt',
|
||
icon: 'chart-no-axes-gantt'
|
||
}, {
|
||
id: 'deps',
|
||
label: 'Dependencies',
|
||
icon: 'network'
|
||
}],
|
||
active: tab,
|
||
onChange: setTab
|
||
}), tab === 'board' ? anyMatch ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(5, 1fr)',
|
||
gap: 12,
|
||
alignItems: 'start',
|
||
flex: 1,
|
||
minHeight: 0,
|
||
overflow: 'auto'
|
||
}
|
||
}, filtered.map(col => /*#__PURE__*/React.createElement("div", {
|
||
key: col.id,
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
padding: '2px 2px 4px',
|
||
borderBottom: '1px solid var(--line-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, col.label), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, col.issues.length)), col.issues.map(i => /*#__PURE__*/React.createElement(IssueCard, {
|
||
key: i.id,
|
||
issue: i
|
||
}))))) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
border: '1px dashed var(--line-2)',
|
||
borderRadius: 'var(--radius-3)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(window.EmptyState, {
|
||
icon: "search",
|
||
title: "Nothing by that name",
|
||
line: `The pot holds ${d.columns.reduce((n, c) => n + c.issues.length, 0)} issues; none of them answer to “${query.trim()}”.`
|
||
})) : tab === 'deps' ? /*#__PURE__*/React.createElement(window.DepsGraph, {
|
||
onOpenIssue: onOpenIssue
|
||
}) : /*#__PURE__*/React.createElement(window.GanttView, {
|
||
onOpenIssue: onOpenIssue
|
||
}));
|
||
}
|
||
Object.assign(window, {
|
||
BoardScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/BoardScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/CalibrationScreen.jsx
|
||
try { (() => {
|
||
// Calibration report — estimate-vs-actual evidence behind the cones
|
||
function CalibrationScreen({
|
||
onBack
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const c = window.CT_DATA.calibration;
|
||
|
||
// scatter chart geometry
|
||
const W = 420,
|
||
H = 300,
|
||
pad = {
|
||
l: 36,
|
||
r: 16,
|
||
t: 14,
|
||
b: 30
|
||
};
|
||
const maxD = 9;
|
||
const X = d => pad.l + d / maxD * (W - pad.l - pad.r);
|
||
const Y = d => H - pad.b - d / maxD * (H - pad.t - pad.b);
|
||
const BiasBar = ({
|
||
bias
|
||
}) => {
|
||
if (bias == null) return /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "n too small");
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
flex: 1,
|
||
height: 10,
|
||
background: 'var(--paper-2)',
|
||
borderRadius: 3
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: '30%',
|
||
top: -2,
|
||
bottom: -2,
|
||
width: 1.5,
|
||
background: 'var(--line-2)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: '30%',
|
||
top: 1.5,
|
||
height: 7,
|
||
width: `${Math.min(bias * 1.6, 66)}%`,
|
||
background: bias > 15 ? 'var(--warn)' : 'var(--ok)',
|
||
borderRadius: '0 3px 3px 0',
|
||
opacity: 0.75
|
||
}
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 11.5px var(--font-mono)',
|
||
color: bias > 15 ? 'var(--warn)' : 'var(--ok)',
|
||
width: 42,
|
||
textAlign: 'right'
|
||
}
|
||
}, "+", bias, "%"));
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: onBack,
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
background: 'none',
|
||
border: 'none',
|
||
font: '500 12.5px var(--font-sans)',
|
||
color: 'var(--ink-2)',
|
||
cursor: 'pointer',
|
||
padding: '2px 0',
|
||
marginBottom: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "arrow-left",
|
||
size: 14
|
||
}), " Runway"), /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Calibration"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, c.n, " closed issues with estimates \xB7 evidence, not opinion")), /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "ok",
|
||
dot: true
|
||
}, "curve active \xB7 n \u2265 20"))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Estimate vs actual",
|
||
title: "The shape of hope",
|
||
jade: true
|
||
}, /*#__PURE__*/React.createElement("svg", {
|
||
width: "100%",
|
||
viewBox: `0 0 ${W} ${H}`,
|
||
style: {
|
||
display: 'block'
|
||
}
|
||
}, [1, 3, 5, 8].map(d => /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: d
|
||
}, /*#__PURE__*/React.createElement("line", {
|
||
x1: X(d),
|
||
x2: X(d),
|
||
y1: pad.t,
|
||
y2: H - pad.b,
|
||
stroke: "var(--line-1)",
|
||
strokeWidth: "1"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: X(d),
|
||
y: H - 12,
|
||
textAnchor: "middle",
|
||
style: {
|
||
font: '400 10px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, d, "d"), /*#__PURE__*/React.createElement("line", {
|
||
x1: pad.l,
|
||
x2: W - pad.r,
|
||
y1: Y(d),
|
||
y2: Y(d),
|
||
stroke: "var(--line-1)",
|
||
strokeWidth: "1"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: pad.l - 6,
|
||
y: Y(d) + 3,
|
||
textAnchor: "end",
|
||
style: {
|
||
font: '400 10px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, d, "d"))), /*#__PURE__*/React.createElement("line", {
|
||
x1: X(0),
|
||
y1: Y(0),
|
||
x2: X(maxD),
|
||
y2: Y(maxD),
|
||
stroke: "var(--line-2)",
|
||
strokeWidth: "1.2",
|
||
strokeDasharray: "4 4"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: X(7.6),
|
||
y: Y(7.6) + 14,
|
||
style: {
|
||
font: '400 10px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, "honest"), /*#__PURE__*/React.createElement("line", {
|
||
x1: X(0),
|
||
y1: Y(0),
|
||
x2: X(maxD / c.fit),
|
||
y2: Y(maxD),
|
||
stroke: "var(--cone-line)",
|
||
strokeWidth: "1.6"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: X(4.1),
|
||
y: Y(4.1 * c.fit) - 8,
|
||
style: {
|
||
font: '500 10px var(--font-mono)',
|
||
fill: 'var(--cone-line)'
|
||
}
|
||
}, "you \xB7 \xD7", c.fit), c.scatter.map(([e, a], i) => /*#__PURE__*/React.createElement("circle", {
|
||
key: i,
|
||
cx: X(e) + (i % 5 - 2) * 3,
|
||
cy: Y(a),
|
||
r: "3",
|
||
fill: "var(--accent)",
|
||
opacity: "0.55"
|
||
}))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: '8px 0 0'
|
||
}
|
||
}, "estimated (x) vs actual days (y) \xB7 actuals inferred from git events, never tracked")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Bias by estimate label",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, c.labels.map((r, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: r.label,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 14,
|
||
padding: '10px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 11.5px var(--font-mono)',
|
||
color: 'var(--ink-1)',
|
||
width: 52
|
||
}
|
||
}, r.label), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
width: 66
|
||
}
|
||
}, "n=", r.n, " \xB7 ", r.median), /*#__PURE__*/React.createElement(BiasBar, {
|
||
bias: r.bias
|
||
}))))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "By person",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, c.people.map((p, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: p.who,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12,
|
||
padding: '11px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 24,
|
||
height: 24,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 9px/24px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, p.who.split(' ').map(w => w[0]).join('')), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, p.who), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, " \xB7 n=", p.n, " \xB7 ", p.note)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 12px var(--font-mono)',
|
||
color: p.bias > 15 ? 'var(--warn)' : 'var(--ok)'
|
||
}
|
||
}, "+", p.bias, "%"))))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "What this does to your forecasts"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, c.effect.raw), /*#__PURE__*/React.createElement(Icon, {
|
||
name: "arrow-right",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 12.5px var(--font-mono)',
|
||
color: 'var(--ink-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, c.effect.banded)), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '10px 0 0'
|
||
}
|
||
}, "You are not bad at estimating; you are optimistic in a very stable way. Stable, I can work with.")))));
|
||
}
|
||
Object.assign(window, {
|
||
CalibrationScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/CalibrationScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/CaptureScreen.jsx
|
||
try { (() => {
|
||
// Capture interview — braindump → interview → approved ticket set (< 2 min)
|
||
function CaptureScreen({
|
||
onDone
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Button,
|
||
Card,
|
||
Tag,
|
||
Badge,
|
||
Select,
|
||
Icon
|
||
} = DS;
|
||
const [stage, setStage] = React.useState('dump'); // dump | interview | review | filed
|
||
const [dump, setDump] = React.useState('auth is flaky \u2014 token refresh dies silently, sometimes session storage goes stale. ' + 'also the webhook debounce thing keeps double-firing. and we owe docs for auth setup');
|
||
const [qi, setQi] = React.useState(0);
|
||
const [log, setLog] = React.useState([]);
|
||
const [split, setSplit] = React.useState(null);
|
||
const [webEst, setWebEst] = React.useState(null);
|
||
const [secs, setSecs] = React.useState(0);
|
||
const running = stage === 'interview' || stage === 'review';
|
||
React.useEffect(() => {
|
||
if (!running) return;
|
||
const t = setInterval(() => setSecs(s => s + 1), 1000);
|
||
return () => clearInterval(t);
|
||
}, [running]);
|
||
const clock = `${Math.floor(secs / 60)}:${String(secs % 60).padStart(2, '0')}`;
|
||
const QUESTIONS = [{
|
||
q: 'The auth work \u2014 one ticket, or shall I split token refresh from session storage? They fail differently.',
|
||
chips: ['One ticket', 'Split them'],
|
||
set: a => setSplit(a === 'Split them')
|
||
}, {
|
||
q: 'The webhook double-fire \u2014 how long? I should mention your "quick" has averaged two days.',
|
||
chips: ['est/1d', 'est/2d', 'est/3d'],
|
||
set: a => setWebEst(a)
|
||
}, {
|
||
q: 'Milestone Beta, I presume? It has room, provided the auth work stays under four days.',
|
||
chips: ['Beta', 'New milestone'],
|
||
set: () => {}
|
||
}];
|
||
const answer = a => {
|
||
QUESTIONS[qi].set(a);
|
||
setLog(l => [...l, {
|
||
q: QUESTIONS[qi].q,
|
||
a
|
||
}]);
|
||
if (qi + 1 < QUESTIONS.length) setQi(qi + 1);else setStage('review');
|
||
};
|
||
|
||
// draft tickets build as the interview progresses
|
||
const tickets = [];
|
||
if (split === true) {
|
||
tickets.push({
|
||
title: 'Token refresh: retry with backoff',
|
||
est: 'est/2d',
|
||
p: 'p/2'
|
||
});
|
||
tickets.push({
|
||
title: 'Session storage: stale reads on wake',
|
||
est: 'est/1d',
|
||
p: 'p/3'
|
||
});
|
||
} else if (split === false) {
|
||
tickets.push({
|
||
title: 'Auth: token refresh + session storage',
|
||
est: 'est/3d',
|
||
p: 'p/2'
|
||
});
|
||
}
|
||
if (webEst) tickets.push({
|
||
title: 'Webhook debounce: double-fire guard',
|
||
est: webEst,
|
||
p: 'p/1',
|
||
dep: 'blocked by auth work'
|
||
});
|
||
if (stage === 'review' || stage === 'filed') {
|
||
tickets.push({
|
||
title: 'Docs: auth setup guide',
|
||
est: 'est/1d',
|
||
p: 'p/4',
|
||
byReginald: true
|
||
});
|
||
}
|
||
const totalDays = tickets.reduce((n, t) => n + parseInt(t.est.replace('est/', '')), 0);
|
||
const estOptions = ['est/1d', 'est/2d', 'est/3d', 'est/5d', 'est/8d'].map(v => ({
|
||
value: v,
|
||
label: v
|
||
}));
|
||
const pOptions = ['p/1', 'p/2', 'p/3', 'p/4'].map(v => ({
|
||
value: v,
|
||
label: v
|
||
}));
|
||
const Tray = ({
|
||
editable
|
||
}) => /*#__PURE__*/React.createElement(Card, {
|
||
overline: "The tray",
|
||
title: tickets.length ? `${tickets.length} draft${tickets.length > 1 ? 's' : ''}` : 'Empty, for now',
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, tickets.length === 0 ? /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0,
|
||
padding: '14px 20px 18px'
|
||
}
|
||
}, "Tickets appear here as we talk.") : tickets.map((t, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: t.title,
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8,
|
||
padding: '12px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, t.title), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, editable ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, {
|
||
options: estOptions,
|
||
defaultValue: t.est,
|
||
style: {
|
||
width: 96
|
||
}
|
||
}), /*#__PURE__*/React.createElement(Select, {
|
||
options: pOptions,
|
||
defaultValue: t.p,
|
||
style: {
|
||
width: 76
|
||
}
|
||
})) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Tag, {
|
||
label: t.est
|
||
}), /*#__PURE__*/React.createElement(Tag, {
|
||
label: t.p
|
||
})), t.dep ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 4
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "network",
|
||
size: 11
|
||
}), t.dep) : null, t.byReginald ? /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "jade"
|
||
}, "added by Reginald") : null)))));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Capture"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "braindump \u2192 approved tickets")), stage !== 'dump' ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
textAlign: 'right'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 24px/1 var(--font-serif-display)',
|
||
color: secs > 120 ? 'var(--warn)' : 'var(--ink-1)'
|
||
}
|
||
}, clock), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginTop: 4
|
||
}
|
||
}, "budget 2:00")) : null), stage === 'dump' ? /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Braindump",
|
||
title: "Tell me what you're planning",
|
||
jade: true
|
||
}, /*#__PURE__*/React.createElement("textarea", {
|
||
value: dump,
|
||
onChange: e => setDump(e.target.value),
|
||
rows: 5,
|
||
style: {
|
||
width: '100%',
|
||
resize: 'vertical',
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
background: 'var(--paper-0)',
|
||
border: '1px solid var(--line-2)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '10px 12px',
|
||
outline: 'none',
|
||
lineHeight: 1.55
|
||
}
|
||
}), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '10px 0 14px'
|
||
}
|
||
}, "Sentences, fragments, grievances \u2014 all welcome. I'll sort it into tickets and only ask what I can't infer."), /*#__PURE__*/React.createElement(Button, {
|
||
icon: "sparkles",
|
||
onClick: () => setStage('interview')
|
||
}, "Brew tickets")) : null, stage === 'interview' ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1.3fr 1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: `Interview \u00b7 ${qi + 1} of ${QUESTIONS.length}`,
|
||
jade: true
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, log.map((e, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 6,
|
||
opacity: 0.66
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, e.q), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
alignSelf: 'flex-start',
|
||
font: 'var(--text-small)',
|
||
background: 'var(--paper-2)',
|
||
borderRadius: 'var(--radius-round)',
|
||
padding: '4px 11px'
|
||
}
|
||
}, e.a))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent-lg)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, QUESTIONS[qi].q), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, QUESTIONS[qi].chips.map(c => /*#__PURE__*/React.createElement(Button, {
|
||
key: c,
|
||
variant: "secondary",
|
||
size: "sm",
|
||
onClick: () => answer(c)
|
||
}, c))))), /*#__PURE__*/React.createElement(Tray, null)) : null, stage === 'review' ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1.1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Consequence",
|
||
title: `${tickets.length} tickets \u00b7 ~${totalDays}d of work`,
|
||
jade: true,
|
||
footer: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
onClick: () => setStage('filed')
|
||
}, "Approve all"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => {
|
||
setStage('dump');
|
||
setQi(0);
|
||
setLog([]);
|
||
setSplit(null);
|
||
setWebEst(null);
|
||
setSecs(0);
|
||
}
|
||
}, "Discard"))
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
margin: '0 0 8px'
|
||
}
|
||
}, "Beta's 80% window moves ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)'
|
||
}
|
||
}, "Mar 3\u201312 \u2192 Mar 5\u201314"), ". Capacity absorbs the rest."), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "I added the docs ticket you mentioned and wired the dependency. Shall I make it so?")), /*#__PURE__*/React.createElement(Tray, {
|
||
editable: true
|
||
})) : null, stage === 'filed' ? /*#__PURE__*/React.createElement(Card, {
|
||
jade: true,
|
||
style: {
|
||
maxWidth: 560
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 10,
|
||
alignItems: 'flex-start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--ok)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
font: 'var(--text-title)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "circle-check",
|
||
size: 22
|
||
}), " Filed"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
margin: 0
|
||
}
|
||
}, tickets.length, " issues opened in gitea with ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)'
|
||
}
|
||
}, "est/*"), " and ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)'
|
||
}
|
||
}, "p/*"), " labels \u2014 nothing else touched."), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "Elapsed ", clock, " \u2014 under budget. No bot comments, no synthetic issues; your repo remains yours."), /*#__PURE__*/React.createElement(Button, {
|
||
iconRight: "arrow-right",
|
||
onClick: onDone
|
||
}, "To morning service"))) : null);
|
||
}
|
||
Object.assign(window, {
|
||
CaptureScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/CaptureScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/Chart.jsx
|
||
try { (() => {
|
||
// Burn-up chart with Monte Carlo forecast cone — geometry, not decoration.
|
||
function BurnUpCone({
|
||
width = 640,
|
||
height = 220
|
||
}) {
|
||
const pad = {
|
||
l: 34,
|
||
r: 96,
|
||
t: 16,
|
||
b: 26
|
||
};
|
||
const W = width - pad.l - pad.r;
|
||
const H = height - pad.t - pad.b;
|
||
const x = f => pad.l + f * W;
|
||
const y = f => pad.t + (1 - f) * H;
|
||
|
||
// scope line (total work), actual completed, cone from today
|
||
const today = 0.58;
|
||
const actual = [[0, 0], [0.08, 0.05], [0.18, 0.13], [0.26, 0.16], [0.36, 0.27], [0.46, 0.38], [0.58, 0.47]];
|
||
const coneHi = [[0.58, 0.47], [0.72, 0.66], [0.86, 0.88], [0.95, 1.0]];
|
||
const coneLo = [[0.58, 0.47], [0.74, 0.58], [0.9, 0.74], [1.0, 0.86]];
|
||
const mid = [[0.58, 0.47], [0.76, 0.63], [0.92, 0.83], [1.0, 0.93]];
|
||
const pts = arr => arr.map(([a, b]) => `${x(a)},${y(b)}`).join(' ');
|
||
const cone = [...coneHi, ...[...coneLo].reverse()];
|
||
return /*#__PURE__*/React.createElement("svg", {
|
||
width: "100%",
|
||
viewBox: `0 0 ${width} ${height}`,
|
||
style: {
|
||
display: 'block'
|
||
}
|
||
}, [0, 0.25, 0.5, 0.75, 1].map(f => /*#__PURE__*/React.createElement("line", {
|
||
key: f,
|
||
x1: pad.l,
|
||
x2: width - pad.r,
|
||
y1: y(f),
|
||
y2: y(f),
|
||
stroke: "var(--line-1)",
|
||
strokeWidth: "1"
|
||
})), /*#__PURE__*/React.createElement("line", {
|
||
x1: pad.l,
|
||
x2: width - pad.r,
|
||
y1: y(1),
|
||
y2: y(1),
|
||
stroke: "var(--line-2)",
|
||
strokeWidth: "1.5"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: pad.l,
|
||
y: y(1) - 6,
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, "scope \xB7 42 issues"), /*#__PURE__*/React.createElement("polygon", {
|
||
points: pts(cone),
|
||
fill: "var(--cone-fill)"
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: pts(coneHi),
|
||
fill: "none",
|
||
stroke: "var(--cone-line)",
|
||
strokeWidth: "1.2",
|
||
strokeDasharray: "3 3"
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: pts(coneLo),
|
||
fill: "none",
|
||
stroke: "var(--cone-line)",
|
||
strokeWidth: "1.2",
|
||
strokeDasharray: "3 3"
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: pts(mid),
|
||
fill: "none",
|
||
stroke: "var(--cone-line)",
|
||
strokeWidth: "1.4"
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: pts(actual),
|
||
fill: "none",
|
||
stroke: "var(--cone-actual)",
|
||
strokeWidth: "2"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: x(0.58),
|
||
cy: y(0.47),
|
||
r: "3.5",
|
||
fill: "var(--cone-actual)"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: x(today),
|
||
x2: x(today),
|
||
y1: pad.t,
|
||
y2: height - pad.b,
|
||
stroke: "var(--jade)",
|
||
strokeWidth: "1"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: x(today) + 5,
|
||
y: pad.t + 10,
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
fill: 'var(--jade-7)'
|
||
}
|
||
}, "today"), /*#__PURE__*/React.createElement("line", {
|
||
x1: x(0.95) + 4,
|
||
x2: x(0.95) + 4,
|
||
y1: y(1.0),
|
||
y2: y(0.86) + H * 0.14 * 0 + (y(0.86) - y(0.86)),
|
||
stroke: "none"
|
||
}), /*#__PURE__*/React.createElement("text", {
|
||
x: width - pad.r + 10,
|
||
y: y(0.95),
|
||
style: {
|
||
font: '500 11.5px var(--font-mono)',
|
||
fill: 'var(--ink-1)'
|
||
}
|
||
}, "80%"), /*#__PURE__*/React.createElement("text", {
|
||
x: width - pad.r + 10,
|
||
y: y(0.95) + 14,
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
fill: 'var(--ink-2)'
|
||
}
|
||
}, "Mar 3\u201312"), /*#__PURE__*/React.createElement("text", {
|
||
x: pad.l,
|
||
y: height - 8,
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, "Jan 6"), /*#__PURE__*/React.createElement("text", {
|
||
x: width - pad.r - 34,
|
||
y: height - 8,
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
fill: 'var(--ink-3)'
|
||
}
|
||
}, "Mar 15"));
|
||
}
|
||
|
||
// Runway bar: milestone due date vs forecast range position
|
||
function RunwayBar({
|
||
m
|
||
}) {
|
||
const toneColor = m.tone === 'warn' ? 'var(--warn)' : 'var(--ok)';
|
||
const left = Math.max(0, (m.pos - m.spread / 2) * 100);
|
||
const w = Math.min(100 - left, m.spread * 100);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
height: 22,
|
||
background: 'var(--paper-2)',
|
||
borderRadius: 4,
|
||
overflow: 'hidden'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: `${left}%`,
|
||
width: `${w}%`,
|
||
top: 0,
|
||
bottom: 0,
|
||
background: 'var(--cone-fill)',
|
||
borderLeft: `1.5px solid ${toneColor}`,
|
||
borderRight: `1.5px solid ${toneColor}`
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: `${m.pos * 100}%`,
|
||
top: 0,
|
||
bottom: 0,
|
||
width: 2,
|
||
background: toneColor
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: 'calc(88% - 1px)',
|
||
top: 0,
|
||
bottom: 0,
|
||
width: 2,
|
||
background: 'var(--ink-1)'
|
||
}
|
||
}));
|
||
}
|
||
Object.assign(window, {
|
||
BurnUpCone,
|
||
RunwayBar
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/Chart.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/ChatPanel.jsx
|
||
try { (() => {
|
||
// Agent panel — chat is the write-path
|
||
function ChatPanel({
|
||
onOpenDirectives,
|
||
offline
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Icon,
|
||
IconButton
|
||
} = DS;
|
||
const d = window.CT_DATA;
|
||
const [msgs, setMsgs] = React.useState(d.chat);
|
||
const [text, setText] = React.useState('');
|
||
const [thinking, setThinking] = React.useState(false);
|
||
const scrollRef = React.useRef(null);
|
||
React.useEffect(() => {
|
||
const el = scrollRef.current;
|
||
if (el) el.scrollTop = el.scrollHeight;
|
||
}, [msgs, thinking]);
|
||
const send = () => {
|
||
const t = text.trim();
|
||
if (!t) return;
|
||
setMsgs(m => [...m, {
|
||
from: 'user',
|
||
text: t
|
||
}]);
|
||
setText('');
|
||
setThinking(true);
|
||
setTimeout(() => {
|
||
setThinking(false);
|
||
setMsgs(m => [...m, {
|
||
from: 'agent',
|
||
text: d.cannedReply
|
||
}]);
|
||
}, 900);
|
||
};
|
||
return /*#__PURE__*/React.createElement("aside", {
|
||
style: {
|
||
width: 330,
|
||
flexShrink: 0,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
background: 'var(--surface-card)',
|
||
borderLeft: '1px solid var(--line-1)',
|
||
minHeight: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '14px 16px',
|
||
borderBottom: '1px solid var(--line-1)',
|
||
flexShrink: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "sparkles",
|
||
size: 16,
|
||
style: {
|
||
color: offline ? 'var(--ink-3)' : 'var(--jade)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Reginald"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginLeft: 'auto'
|
||
}
|
||
}, offline ? 'offline · queueing' : 'gemma-4b · local'), /*#__PURE__*/React.createElement(IconButton, {
|
||
icon: "history",
|
||
label: "Directive log",
|
||
size: "sm",
|
||
onClick: onOpenDirectives
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
ref: scrollRef,
|
||
style: {
|
||
flex: 1,
|
||
overflowY: 'auto',
|
||
padding: 16,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12,
|
||
minHeight: 0
|
||
}
|
||
}, msgs.map((m, i) => m.from === 'agent' ? /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-1)',
|
||
lineHeight: 1.55
|
||
}
|
||
}, m.text) : /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
style: {
|
||
alignSelf: 'flex-end',
|
||
maxWidth: '85%',
|
||
background: 'var(--paper-2)',
|
||
borderRadius: '10px 10px 2px 10px',
|
||
padding: '8px 12px',
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, m.text)), offline ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "The model is away from its desk. Reads still work; writes will wait their turn.") : null, thinking ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "considering\u2026") : null), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: 14,
|
||
borderTop: '1px solid var(--line-1)',
|
||
flexShrink: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'flex-end',
|
||
gap: 8,
|
||
background: 'var(--paper-0)',
|
||
border: '1px solid var(--line-2)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '8px 8px 8px 12px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("textarea", {
|
||
value: text,
|
||
onChange: e => setText(e.target.value),
|
||
onKeyDown: e => {
|
||
if (e.key === 'Enter' && !e.shiftKey) {
|
||
e.preventDefault();
|
||
send();
|
||
}
|
||
},
|
||
placeholder: offline ? 'Writes wait for the connection…' : 'Tell me what to do…',
|
||
disabled: offline,
|
||
rows: 1,
|
||
style: {
|
||
flex: 1,
|
||
resize: 'none',
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
lineHeight: 1.45,
|
||
maxHeight: 96
|
||
}
|
||
}), /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: send,
|
||
"aria-label": "Send",
|
||
disabled: offline,
|
||
style: {
|
||
width: 30,
|
||
height: 30,
|
||
borderRadius: 'var(--radius-2)',
|
||
border: 'none',
|
||
cursor: offline ? 'not-allowed' : 'pointer',
|
||
background: offline ? 'var(--paper-3)' : 'var(--accent)',
|
||
color: offline ? 'var(--ink-3)' : 'var(--ink-inverse)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "send",
|
||
size: 14
|
||
}))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: '8px 2px 0'
|
||
}
|
||
}, "Chat is the write-path. Destructive changes are proposed, never assumed.")));
|
||
}
|
||
Object.assign(window, {
|
||
ChatPanel
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/ChatPanel.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/DepsGraph.jsx
|
||
try { (() => {
|
||
// Dependency graph drill-in — layered DAG, critical path in spruce
|
||
function DepsGraph({
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Tag,
|
||
Icon
|
||
} = DS;
|
||
const g = window.CT_DATA.deps;
|
||
const PAD = 14,
|
||
COLW = 206,
|
||
ROWH = 106,
|
||
NW = 176,
|
||
NH = 84;
|
||
const X = c => PAD + c * COLW;
|
||
const Y = r => PAD + r * ROWH;
|
||
const maxCol = g.milestone.col;
|
||
const maxRow = Math.max(...g.nodes.map(n => n.row), g.milestone.row);
|
||
const W = PAD * 2 + maxCol * COLW + NW;
|
||
const H = PAD * 2 + maxRow * ROWH + NH;
|
||
const MSW = 158,
|
||
MSH = 44;
|
||
const pos = {};
|
||
g.nodes.forEach(n => {
|
||
pos[n.id] = {
|
||
x: X(n.col),
|
||
y: Y(n.row),
|
||
w: NW,
|
||
h: NH
|
||
};
|
||
});
|
||
pos['ms'] = {
|
||
x: X(g.milestone.col),
|
||
y: Y(g.milestone.row) + (NH - MSH) / 2,
|
||
w: MSW,
|
||
h: MSH
|
||
};
|
||
const edgePath = e => {
|
||
const a = pos[e.from],
|
||
b = pos[e.to];
|
||
const x1 = a.x + a.w,
|
||
y1 = a.y + a.h / 2;
|
||
const x2 = b.x,
|
||
y2 = b.y + b.h / 2;
|
||
const dx = Math.max(28, (x2 - x1) / 2);
|
||
return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2 - 5} ${y2}`;
|
||
};
|
||
const STATES = {
|
||
done: {
|
||
icon: 'circle-check',
|
||
color: 'var(--ok)',
|
||
label: 'done'
|
||
},
|
||
steeping: {
|
||
icon: 'clock',
|
||
color: 'var(--warn)',
|
||
label: 'steeping'
|
||
},
|
||
review: {
|
||
icon: 'git-pull-request',
|
||
color: 'var(--info)',
|
||
label: 'in review'
|
||
},
|
||
triage: {
|
||
icon: 'circle-dot',
|
||
color: 'var(--ink-3)',
|
||
label: 'triage'
|
||
},
|
||
diagnosis: {
|
||
icon: 'circle-dashed',
|
||
color: 'var(--ink-3)',
|
||
label: 'diagnosis'
|
||
}
|
||
};
|
||
const Node = ({
|
||
n
|
||
}) => {
|
||
const st = STATES[n.state];
|
||
const crit = g.critical.includes(n.id);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => onOpenIssue({
|
||
id: n.id,
|
||
title: n.title,
|
||
labels: n.tags,
|
||
rationale: n.rationale,
|
||
days: n.state === 'steeping' ? n.days : undefined
|
||
}),
|
||
style: {
|
||
position: 'absolute',
|
||
left: pos[n.id].x,
|
||
top: pos[n.id].y,
|
||
width: NW,
|
||
height: NH,
|
||
background: n.state === 'done' ? 'var(--paper-2)' : 'var(--surface-card)',
|
||
border: `1px solid ${crit ? 'var(--spruce-5)' : 'var(--line-1)'}`,
|
||
boxShadow: crit ? 'var(--shadow-1), inset 2px 0 0 var(--accent)' : 'var(--shadow-1)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '9px 11px',
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 6,
|
||
opacity: n.state === 'done' ? 0.72 : 1,
|
||
transition: 'border-color var(--duration-fast) var(--ease-out)'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.borderColor = crit ? 'var(--accent)' : 'var(--line-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.borderColor = crit ? 'var(--spruce-5)' : 'var(--line-1)';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '500 12px/1.3 var(--font-sans)',
|
||
color: 'var(--ink-1)',
|
||
display: '-webkit-box',
|
||
WebkitLineClamp: 2,
|
||
WebkitBoxOrient: 'vertical',
|
||
overflow: 'hidden'
|
||
}
|
||
}, n.title), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
marginTop: 'auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "#", n.id), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 4,
|
||
font: '400 10.5px var(--font-mono)',
|
||
color: st.color,
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: st.icon,
|
||
size: 11
|
||
}), st.label, n.state === 'steeping' && n.days ? ` ${n.days}` : ''), n.tags.filter(t => t.startsWith('p/')).map(t => /*#__PURE__*/React.createElement("span", {
|
||
key: t,
|
||
style: {
|
||
font: '500 10.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginLeft: 'auto'
|
||
}
|
||
}, t))));
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12,
|
||
flex: 1,
|
||
minHeight: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 18,
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 7
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 22,
|
||
height: 2,
|
||
background: 'var(--accent)',
|
||
display: 'inline-block'
|
||
}
|
||
}), "critical path"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 7
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 22,
|
||
height: 0,
|
||
borderTop: '1.5px solid var(--line-2)',
|
||
display: 'inline-block'
|
||
}
|
||
}), "blocks"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "unattached: ", g.unattached.map(i => `#${i}`).join(' · '))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
overflow: 'auto',
|
||
flex: 1,
|
||
minHeight: 0,
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-3)',
|
||
background: 'var(--surface-app)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
width: W,
|
||
height: H
|
||
}
|
||
}, /*#__PURE__*/React.createElement("svg", {
|
||
width: W,
|
||
height: H,
|
||
style: {
|
||
position: 'absolute',
|
||
inset: 0,
|
||
pointerEvents: 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("marker", {
|
||
id: "dg-arrow",
|
||
viewBox: "0 0 8 8",
|
||
refX: "7",
|
||
refY: "4",
|
||
markerWidth: "7",
|
||
markerHeight: "7",
|
||
orient: "auto-start-reverse"
|
||
}, /*#__PURE__*/React.createElement("path", {
|
||
d: "M 0 0.5 L 7.5 4 L 0 7.5 z",
|
||
fill: "var(--line-2)"
|
||
})), /*#__PURE__*/React.createElement("marker", {
|
||
id: "dg-arrow-crit",
|
||
viewBox: "0 0 8 8",
|
||
refX: "7",
|
||
refY: "4",
|
||
markerWidth: "7",
|
||
markerHeight: "7",
|
||
orient: "auto-start-reverse"
|
||
}, /*#__PURE__*/React.createElement("path", {
|
||
d: "M 0 0.5 L 7.5 4 L 0 7.5 z",
|
||
fill: "var(--accent)"
|
||
}))), g.edges.map((e, i) => /*#__PURE__*/React.createElement("path", {
|
||
key: i,
|
||
d: edgePath(e),
|
||
fill: "none",
|
||
stroke: e.crit ? 'var(--accent)' : 'var(--line-2)',
|
||
strokeWidth: e.crit ? 2 : 1.5,
|
||
markerEnd: `url(#${e.crit ? 'dg-arrow-crit' : 'dg-arrow'})`
|
||
}))), g.nodes.map(n => /*#__PURE__*/React.createElement(Node, {
|
||
key: n.id,
|
||
n: n
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: pos['ms'].x,
|
||
top: pos['ms'].y,
|
||
width: MSW,
|
||
height: MSH,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '0 14px',
|
||
background: 'var(--accent)',
|
||
color: 'var(--ink-inverse)',
|
||
borderRadius: 'var(--radius-round)',
|
||
boxShadow: 'var(--shadow-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "milestone",
|
||
size: 15
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '600 12.5px/1.2 var(--font-sans)'
|
||
}
|
||
}, g.milestone.name), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 10.5px/1.2 var(--font-mono)',
|
||
opacity: 0.8
|
||
}
|
||
}, "due ", g.milestone.due))))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "Four issues sit on the critical path, and #87 is the cork in the bottle. Remove it and everything pours."));
|
||
}
|
||
Object.assign(window, {
|
||
DepsGraph
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/DepsGraph.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/DirectivesScreen.jsx
|
||
try { (() => {
|
||
// Directive log — append-only ledger + the consequence diff (propose-approve)
|
||
function DirectivesScreen() {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Button,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const d = window.CT_DATA.directives;
|
||
const [pending, setPending] = React.useState(d.pending);
|
||
const [entries, setEntries] = React.useState(d.entries);
|
||
const resolve = status => {
|
||
setEntries(e => [{
|
||
seq: pending.seq,
|
||
who: pending.who,
|
||
when: pending.when,
|
||
what: pending.what,
|
||
why: 'pilot demo on the 14th',
|
||
status,
|
||
consequence: status === 'applied' ? '#78 +5d · Beta 80% Mar 5–14' : 'withdrawn before apply'
|
||
}, ...e]);
|
||
setPending(null);
|
||
};
|
||
const toneColor = {
|
||
ok: 'var(--ok)',
|
||
warn: 'var(--warn)',
|
||
info: 'var(--info)',
|
||
danger: 'var(--danger)'
|
||
};
|
||
const statusBadge = {
|
||
applied: {
|
||
tone: 'ok',
|
||
label: 'applied'
|
||
},
|
||
withdrawn: {
|
||
tone: 'neutral',
|
||
label: 'withdrawn'
|
||
},
|
||
superseded: {
|
||
tone: 'info',
|
||
label: 'superseded'
|
||
}
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
maxWidth: 760,
|
||
margin: '0 auto',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Directives"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0'
|
||
}
|
||
}, "append-only \xB7 JSONL in pm-state \xB7 who, when, what, why")), pending ? /*#__PURE__*/React.createElement(Card, {
|
||
overline: `Awaiting your word · directive #00${pending.seq}`,
|
||
title: "Consequence diff",
|
||
jade: true,
|
||
footer: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
onClick: () => resolve('applied')
|
||
}, "Make it so"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "secondary",
|
||
onClick: () => {}
|
||
}, "Amend"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => resolve('withdrawn')
|
||
}, "Withdraw"))
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
margin: 0,
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, pending.who), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, " \xB7 ", pending.when), /*#__PURE__*/React.createElement("br", null), "\u201C", pending.what, "\u201D"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
borderTop: '1px solid var(--line-1)'
|
||
}
|
||
}, pending.diff.map(r => /*#__PURE__*/React.createElement("div", {
|
||
key: r.change,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: '9px 0',
|
||
borderBottom: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: '50%',
|
||
background: toneColor[r.tone],
|
||
flexShrink: 0
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-1)',
|
||
flex: 1
|
||
}
|
||
}, r.change), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, r.from, " ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, "\u2192"), " ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: r.tone === 'warn' ? 'var(--warn)' : 'var(--ink-1)'
|
||
}
|
||
}, r.to))))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "Cheap, as consequences go. Shall I make it so?"))) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-3)',
|
||
padding: '2px 2px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "circle-check",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ok)'
|
||
}
|
||
}), "Nothing awaits your word. Directives are given in chat; consequences appear here first."), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "The ledger",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, entries.map((e, i) => {
|
||
const sb = statusBadge[e.status];
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
key: e.seq,
|
||
style: {
|
||
display: 'flex',
|
||
gap: 14,
|
||
padding: '14px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
flexShrink: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "#00", e.seq), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 1,
|
||
flex: 1,
|
||
background: 'var(--line-1)'
|
||
}
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 5
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 20,
|
||
height: 20,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 8.5px/20px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, e.who.split(' ').map(w => w[0]).join('')), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, e.who), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, e.when), e.why ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "\xB7 why: ", e.why) : null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Badge, {
|
||
tone: sb.tone
|
||
}, sb.label))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "\u201C", e.what, "\u201D"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, e.consequence)));
|
||
}))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, "Entries are never edited. Corrections are new entries \u2014 the ledger remembers everything, politely."));
|
||
}
|
||
Object.assign(window, {
|
||
DirectivesScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/DirectivesScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/FocusScreen.jsx
|
||
try { (() => {
|
||
// 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
|
||
}) => /*#__PURE__*/React.createElement(Card, {
|
||
overline: slot,
|
||
jade: jade,
|
||
title: /*#__PURE__*/React.createElement("a", {
|
||
href: "#",
|
||
onClick: e => {
|
||
e.preventDefault();
|
||
onOpenIssue(issue);
|
||
},
|
||
style: {
|
||
color: 'inherit',
|
||
border: 'none'
|
||
}
|
||
}, issue.title),
|
||
actions: /*#__PURE__*/React.createElement(IconButton, {
|
||
icon: "ellipsis",
|
||
label: "More",
|
||
size: "sm"
|
||
}),
|
||
footer: jade ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
size: "sm"
|
||
}, "Start"), /*#__PURE__*/React.createElement(Button, {
|
||
size: "sm",
|
||
variant: "ghost"
|
||
}, "Defer"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "scheduler pick \xB7 critical path")) : null
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
marginBottom: 10,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "#", issue.id), issue.labels.map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
})), issue.steeping ? /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "warn",
|
||
dot: true
|
||
}, "steeping ", issue.steeping) : null), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, issue.rationale));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Morning service"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, d.today, " \xB7 reconcile 3.2s")), /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "ok",
|
||
dot: true
|
||
}, "ahead of forecast")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1.4fr 1fr 1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(FocusRow, {
|
||
slot: "Now",
|
||
issue: d.focus.now,
|
||
jade: true
|
||
}), /*#__PURE__*/React.createElement(FocusRow, {
|
||
slot: "Next",
|
||
issue: d.focus.next
|
||
}), /*#__PURE__*/React.createElement(FocusRow, {
|
||
slot: "Later",
|
||
issue: d.focus.later
|
||
})), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Milestone \xB7 Beta",
|
||
title: /*#__PURE__*/React.createElement(React.Fragment, null, "80% this lands ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "Mar 3\u201312")),
|
||
actions: /*#__PURE__*/React.createElement(IconButton, {
|
||
icon: "chart-line",
|
||
label: "Open runway",
|
||
size: "sm"
|
||
})
|
||
}, /*#__PURE__*/React.createElement(window.BurnUpCone, null), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '10px 0 0'
|
||
}
|
||
}, "The cone has narrowed since Friday. I'm quietly pleased.")));
|
||
}
|
||
Object.assign(window, {
|
||
FocusScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/FocusScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/GanttView.jsx
|
||
try { (() => {
|
||
// Gantt drill-in — scheduler-derived bars, critical chain, 80% forecast tails
|
||
function GanttView({
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Icon
|
||
} = DS;
|
||
const g = window.CT_DATA.gantt;
|
||
const LABELW = 232,
|
||
DAYW = 21,
|
||
ROWH = 36,
|
||
HEADH = 30;
|
||
const chartW = g.days * DAYW;
|
||
const W = LABELW + chartW;
|
||
const H = HEADH + g.rows.length * ROWH;
|
||
const X = d => LABELW + d * DAYW;
|
||
const BAR = {
|
||
done: {
|
||
bg: 'var(--paper-3)',
|
||
border: 'transparent',
|
||
text: 'var(--ink-3)'
|
||
},
|
||
steeping: {
|
||
bg: 'var(--accent)',
|
||
border: 'transparent',
|
||
text: 'var(--ink-inverse)'
|
||
},
|
||
review: {
|
||
bg: 'var(--info-tint)',
|
||
border: 'var(--info)',
|
||
text: 'var(--info)'
|
||
},
|
||
scheduled: {
|
||
bg: 'var(--spruce-2)',
|
||
border: 'var(--spruce-3)',
|
||
text: 'var(--accent-text)'
|
||
}
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12,
|
||
flex: 1,
|
||
minHeight: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 16,
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
whiteSpace: 'nowrap',
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, [['steeping', 'in work'], ['review', 'in review'], ['scheduled', 'scheduled'], ['done', 'done']].map(([k, label]) => /*#__PURE__*/React.createElement("span", {
|
||
key: k,
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 16,
|
||
height: 9,
|
||
borderRadius: 3,
|
||
background: BAR[k].bg,
|
||
border: `1px solid ${BAR[k].border}`,
|
||
display: 'inline-block'
|
||
}
|
||
}), label)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 18,
|
||
height: 0,
|
||
borderTop: '2px dotted var(--cone-line)',
|
||
display: 'inline-block'
|
||
}
|
||
}), "80% tail"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 2,
|
||
height: 12,
|
||
background: 'var(--jade)',
|
||
display: 'inline-block'
|
||
}
|
||
}), "today")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
overflow: 'auto',
|
||
flex: 1,
|
||
minHeight: 0,
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-3)',
|
||
background: 'var(--surface-card)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
width: W,
|
||
height: H
|
||
}
|
||
}, g.weeks.map(w => /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: w.at
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(w.at),
|
||
top: HEADH,
|
||
bottom: 0,
|
||
width: 1,
|
||
background: 'var(--line-1)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(w.at) + 5,
|
||
top: 8,
|
||
font: '400 10.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, w.label))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(g.band.from),
|
||
width: (g.band.to - g.band.from) * DAYW,
|
||
top: HEADH,
|
||
bottom: 0,
|
||
background: 'var(--cone-fill)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(g.band.from) + 5,
|
||
bottom: 6,
|
||
font: '500 10.5px var(--font-mono)',
|
||
color: 'var(--cone-line)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, g.band.label), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(g.due.at) - 1,
|
||
top: HEADH,
|
||
bottom: 0,
|
||
width: 2,
|
||
background: 'var(--ink-1)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(g.due.at) - 4,
|
||
top: HEADH - 12,
|
||
width: 8,
|
||
height: 8,
|
||
background: 'var(--ink-1)',
|
||
transform: 'rotate(45deg)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(g.today),
|
||
top: HEADH,
|
||
bottom: 0,
|
||
width: 2,
|
||
background: 'var(--jade)'
|
||
}
|
||
}), g.rows.map((r, i) => {
|
||
const top = HEADH + i * ROWH;
|
||
const st = BAR[r.state];
|
||
return /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: r.id
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: 0,
|
||
right: 0,
|
||
top: top,
|
||
height: 1,
|
||
background: 'var(--line-1)',
|
||
opacity: 0.6
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => onOpenIssue({
|
||
id: r.id,
|
||
title: r.title,
|
||
labels: [],
|
||
days: r.state === 'steeping' ? '4d' : undefined
|
||
}),
|
||
style: {
|
||
position: 'absolute',
|
||
left: 0,
|
||
width: LABELW,
|
||
height: ROWH,
|
||
top: top,
|
||
zIndex: 2,
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '0 12px 0 14px',
|
||
background: 'var(--surface-card)',
|
||
borderRight: '1px solid var(--line-1)',
|
||
boxShadow: r.crit ? 'inset 2px 0 0 var(--accent)' : 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
flexShrink: 0
|
||
}
|
||
}, "#", r.id), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 12px/1.3 var(--font-sans)',
|
||
color: 'var(--ink-1)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, r.title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '600 8.5px/16px var(--font-sans)',
|
||
color: 'var(--accent-text)',
|
||
background: 'var(--spruce-2)',
|
||
width: 16,
|
||
height: 16,
|
||
borderRadius: '50%',
|
||
textAlign: 'center',
|
||
flexShrink: 0,
|
||
marginLeft: 'auto'
|
||
}
|
||
}, r.who)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(r.start),
|
||
width: (r.end - r.start) * DAYW,
|
||
top: top + 9,
|
||
height: 18,
|
||
background: st.bg,
|
||
border: `1px solid ${st.border}`,
|
||
borderRadius: 4,
|
||
boxShadow: r.crit && r.state !== 'steeping' ? 'inset 0 -2px 0 var(--accent)' : 'none'
|
||
}
|
||
}), r.p80 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(r.end),
|
||
width: (r.p80 - r.end) * DAYW,
|
||
top: top + 17,
|
||
height: 0,
|
||
borderTop: '2px dotted var(--cone-line)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
left: X(r.p80) - 1,
|
||
top: top + 13,
|
||
width: 2,
|
||
height: 10,
|
||
background: 'var(--cone-line)'
|
||
}
|
||
})) : null);
|
||
}))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "The path holds if #87 lands by Wednesday. The dotted tails are your own history, wagging."));
|
||
}
|
||
Object.assign(window, {
|
||
GanttView
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/GanttView.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/InboxScreen.jsx
|
||
try { (() => {
|
||
// Inbox — Reginald only rings the bell when it matters
|
||
function InboxScreen({
|
||
onOpenIssue,
|
||
onOpenDirectives,
|
||
readIds,
|
||
setReadIds
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Tabs,
|
||
Button,
|
||
Icon
|
||
} = DS;
|
||
const all = window.CT_DATA.inbox;
|
||
const [tab, setTab] = React.useState('all');
|
||
const isRead = n => !n.unread || readIds.includes(n.id);
|
||
const unreadCount = all.filter(n => !isRead(n)).length;
|
||
const FILTERS = {
|
||
all: () => true,
|
||
mentions: n => n.type === 'mention' || n.type === 'assignment',
|
||
drift: n => n.type === 'drift' || n.type === 'nag' || n.type === 'milestone',
|
||
system: n => n.type === 'system' || n.type === 'review'
|
||
};
|
||
const items = all.filter(FILTERS[tab]);
|
||
const days = [...new Set(items.map(n => n.day))];
|
||
const toneColor = {
|
||
ok: 'var(--ok)',
|
||
warn: 'var(--warn)',
|
||
info: 'var(--info)',
|
||
neutral: 'var(--ink-3)'
|
||
};
|
||
const open = n => {
|
||
setReadIds(r => r.includes(n.id) ? r : [...r, n.id]);
|
||
if (n.issue) onOpenIssue(n.issue);else if (n.to === 'directives') onOpenDirectives();
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
maxWidth: 760,
|
||
margin: '0 auto',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Inbox"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, unreadCount ? `${unreadCount} unread` : 'all read', " \xB7 nothing here rings twice")), unreadCount ? /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
size: "sm",
|
||
onClick: () => setReadIds(all.map(n => n.id))
|
||
}, "Mark all read") : null), /*#__PURE__*/React.createElement(Tabs, {
|
||
items: [{
|
||
id: 'all',
|
||
label: 'All',
|
||
count: all.length
|
||
}, {
|
||
id: 'mentions',
|
||
label: 'Mentions',
|
||
icon: 'message-square'
|
||
}, {
|
||
id: 'drift',
|
||
label: 'Drift',
|
||
icon: 'chart-line'
|
||
}, {
|
||
id: 'system',
|
||
label: 'System',
|
||
icon: 'refresh-cw'
|
||
}],
|
||
active: tab,
|
||
onChange: setTab
|
||
}), /*#__PURE__*/React.createElement(Card, {
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, days.map(day => /*#__PURE__*/React.createElement("div", {
|
||
key: day
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
padding: '12px 20px 4px'
|
||
}
|
||
}, day), items.filter(n => n.day === day).map(n => {
|
||
const read = isRead(n);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
key: n.id,
|
||
onClick: () => open(n),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'flex-start',
|
||
gap: 12,
|
||
padding: '11px 20px',
|
||
cursor: n.issue || n.to ? 'pointer' : 'default',
|
||
opacity: read ? 0.72 : 1
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--paper-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: '50%',
|
||
background: read ? 'transparent' : 'var(--accent)',
|
||
flexShrink: 0,
|
||
marginTop: 7
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: toneColor[n.tone],
|
||
display: 'inline-flex',
|
||
marginTop: 1,
|
||
flexShrink: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: n.icon,
|
||
size: 15
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: read ? 'var(--text-body)' : 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, n.who ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 600
|
||
}
|
||
}, n.who, " ") : null, n.text), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
marginTop: 2
|
||
}
|
||
}, n.detail)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap',
|
||
marginTop: 2
|
||
}
|
||
}, n.time));
|
||
}))))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "I only ring the bell when it matters. The rest can wait for morning service."));
|
||
}
|
||
Object.assign(window, {
|
||
InboxScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/InboxScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/IssueScreen.jsx
|
||
try { (() => {
|
||
// Issue detail — human intent (gitea) on the left, machine-derived (pm-state) on the right
|
||
function IssueScreen({
|
||
issue,
|
||
onBack,
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Tag,
|
||
Badge,
|
||
Button,
|
||
Icon
|
||
} = DS;
|
||
const det = window.CT_DATA.issueDetail[issue.id] || {
|
||
state: 'triage',
|
||
assignee: 'Stephen',
|
||
milestone: 'Beta',
|
||
body: '',
|
||
comments: [],
|
||
lifecycle: [{
|
||
stage: 'Diagnosis',
|
||
event: 'issue opened',
|
||
when: 'Feb 4 · 10:20',
|
||
icon: 'circle-dot',
|
||
done: true
|
||
}, {
|
||
stage: 'Triage',
|
||
event: 'labeled · milestoned Beta',
|
||
when: 'Feb 5 · 09:12',
|
||
icon: 'tag',
|
||
done: true
|
||
}, {
|
||
stage: 'Work start',
|
||
event: 'first branch or commit ref',
|
||
when: 'pending',
|
||
icon: 'git-commit-horizontal',
|
||
done: false
|
||
}, {
|
||
stage: 'Deploy',
|
||
event: 'PR merged',
|
||
when: 'pending',
|
||
icon: 'git-merge',
|
||
done: false
|
||
}, {
|
||
stage: 'Complete',
|
||
event: 'issue closed',
|
||
when: 'pending',
|
||
icon: 'circle-check',
|
||
done: false
|
||
}],
|
||
forecast: {
|
||
p80: 'starts wk of Feb 16',
|
||
note: 'queue position from scheduler'
|
||
},
|
||
blocks: [],
|
||
blockedBy: [],
|
||
note: null
|
||
};
|
||
const stateBadge = {
|
||
steeping: {
|
||
tone: 'warn',
|
||
label: `steeping${issue.days || issue.steeping ? ' ' + (issue.days || issue.steeping) : ''}`
|
||
},
|
||
triage: {
|
||
tone: 'neutral',
|
||
label: 'triage'
|
||
},
|
||
review: {
|
||
tone: 'info',
|
||
label: 'in review'
|
||
},
|
||
done: {
|
||
tone: 'ok',
|
||
label: 'done'
|
||
}
|
||
}[det.state] || {
|
||
tone: 'neutral',
|
||
label: det.state
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: onBack,
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
background: 'none',
|
||
border: 'none',
|
||
font: '500 12.5px var(--font-sans)',
|
||
color: 'var(--ink-2)',
|
||
cursor: 'pointer',
|
||
padding: '2px 0',
|
||
marginBottom: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "arrow-left",
|
||
size: 14
|
||
}), " Back"), /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'flex-start',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: '400 13px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
margin: '0 0 6px'
|
||
}
|
||
}, "#", issue.id, " \xB7 stephen/commitea"), /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-title)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, issue.title), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
marginTop: 10,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Badge, {
|
||
tone: stateBadge.tone,
|
||
dot: true
|
||
}, stateBadge.label), (issue.labels || []).map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 5
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "milestone",
|
||
size: 12
|
||
}), det.milestone), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 5
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "user",
|
||
size: 12
|
||
}), det.assignee))), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "secondary",
|
||
icon: "arrow-up-right"
|
||
}, "Open in Gitea"))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 300px',
|
||
gap: 16,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Description"
|
||
}, det.body ? /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0,
|
||
lineHeight: 1.6
|
||
}
|
||
}, det.body) : /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, "No description was written. I have opinions about that, but I'll keep them warm.")), /*#__PURE__*/React.createElement(Card, {
|
||
overline: `Comments · ${det.comments.length}`,
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, det.comments.map((c, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
style: {
|
||
display: 'flex',
|
||
gap: 12,
|
||
padding: '14px 20px',
|
||
borderBottom: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 24,
|
||
height: 24,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 9px/24px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, c.who.split(' ').map(w => w[0]).join('')), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, c.who), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, c.when)), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
margin: '4px 0 0'
|
||
}
|
||
}, c.text)))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
padding: '14px 20px',
|
||
alignItems: 'flex-end'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("textarea", {
|
||
placeholder: "Comment \u2014 this writes to gitea, as you",
|
||
rows: 2,
|
||
style: {
|
||
flex: 1,
|
||
resize: 'none',
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
lineHeight: 1.5,
|
||
background: 'var(--paper-0)',
|
||
border: '1px solid var(--line-2)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '8px 11px',
|
||
outline: 'none'
|
||
}
|
||
}), /*#__PURE__*/React.createElement(Button, {
|
||
size: "sm",
|
||
variant: "secondary"
|
||
}, "Comment")))), det.note ? /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0,
|
||
padding: '0 2px'
|
||
}
|
||
}, det.note) : null), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Machine-derived",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '14px 20px',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 0
|
||
}
|
||
}, det.lifecycle.map((s, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: s.stage,
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
color: s.done ? 'var(--ok)' : 'var(--ink-3)',
|
||
padding: '2px 0'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: s.icon,
|
||
size: 14
|
||
})), i < det.lifecycle.length - 1 ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 1,
|
||
flex: 1,
|
||
minHeight: 14,
|
||
background: s.done ? 'var(--spruce-3)' : 'var(--line-1)'
|
||
}
|
||
}) : null), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
paddingBottom: i < det.lifecycle.length - 1 ? 12 : 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: `500 12px var(--font-sans)`,
|
||
color: s.done ? 'var(--ink-1)' : 'var(--ink-3)'
|
||
}
|
||
}, s.stage), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginTop: 2,
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, s.event), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
color: s.done ? 'var(--ink-2)' : 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, s.when))))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '12px 20px',
|
||
borderTop: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
marginBottom: 6
|
||
}
|
||
}, "Forecast"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '500 13px var(--font-mono)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "80% ", det.forecast.p80), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 10.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginTop: 3
|
||
}
|
||
}, det.forecast.note)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '12px 20px',
|
||
borderTop: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
marginBottom: 6
|
||
}
|
||
}, "Dependencies"), det.blocks.length === 0 && det.blockedBy.length === 0 ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "none") : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 6
|
||
}
|
||
}, det.blocks.length ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "blocks"), det.blocks.map(b => /*#__PURE__*/React.createElement("button", {
|
||
key: b,
|
||
type: "button",
|
||
onClick: () => onOpenIssue({
|
||
id: b,
|
||
title: b === 91 ? 'Webhook listener: reconcile on reconnect' : 'Monte Carlo engine: percentile bands',
|
||
labels: b === 91 ? ['est/3d', 'p/2'] : ['est/5d', 'p/1']
|
||
}),
|
||
style: {
|
||
font: '500 11px var(--font-mono)',
|
||
color: 'var(--accent-text)',
|
||
background: 'var(--spruce-1)',
|
||
border: '1px solid var(--spruce-2)',
|
||
borderRadius: 'var(--radius-1)',
|
||
padding: '2px 7px',
|
||
cursor: 'pointer'
|
||
}
|
||
}, "#", b))) : null, det.blockedBy.length ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "blocked by"), det.blockedBy.map(b => /*#__PURE__*/React.createElement("span", {
|
||
key: b,
|
||
style: {
|
||
font: '500 11px var(--font-mono)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, "#", b))) : null)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '10px 20px 14px',
|
||
borderTop: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, "Lives in pm-state. Your repo never sees any of it."))))));
|
||
}
|
||
Object.assign(window, {
|
||
IssueScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/IssueScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/MilestoneScreen.jsx
|
||
try { (() => {
|
||
// Milestone detail — scope, cone, issues; forecasts stay ranges
|
||
function MilestoneScreen({
|
||
onBack,
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Tag,
|
||
Badge,
|
||
Button,
|
||
Icon
|
||
} = DS;
|
||
const cols = window.CT_DATA.columns;
|
||
const byState = ids => cols.flatMap(c => c.issues.map(i => ({
|
||
...i,
|
||
col: c.label
|
||
}))).filter(i => ids.includes(i.id));
|
||
const groups = [{
|
||
label: 'Steeping',
|
||
issues: byState([87, 84])
|
||
}, {
|
||
label: 'In review',
|
||
issues: byState([92])
|
||
}, {
|
||
label: 'Queued',
|
||
issues: byState([102, 103, 99, 96, 78])
|
||
}, {
|
||
label: 'Done',
|
||
issues: byState([71, 69, 65]),
|
||
muted: true
|
||
}];
|
||
const Stat = ({
|
||
label,
|
||
value,
|
||
tone
|
||
}) => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
padding: '12px 18px',
|
||
borderRight: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
marginBottom: 5
|
||
}
|
||
}, label), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: `500 14px var(--font-mono)`,
|
||
color: tone || 'var(--ink-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, value));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: onBack,
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
background: 'none',
|
||
border: 'none',
|
||
font: '500 12.5px var(--font-sans)',
|
||
color: 'var(--ink-2)',
|
||
cursor: 'pointer',
|
||
padding: '2px 0',
|
||
marginBottom: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "arrow-left",
|
||
size: 14
|
||
}), " Runway"), /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14,
|
||
display: 'flex',
|
||
alignItems: 'flex-start',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
margin: '0 0 6px',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "milestone",
|
||
size: 13
|
||
}), " milestone \xB7 due Mar 15 \xB7 soft \u2014 scope may flex"), /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Beta"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
marginTop: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "ok",
|
||
dot: true
|
||
}, "ahead of forecast"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "80% Mar 3\u201312"))), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "secondary",
|
||
icon: "arrow-up-right"
|
||
}, "Open in Gitea"))), /*#__PURE__*/React.createElement(Card, {
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Stat, {
|
||
label: "Scope",
|
||
value: "42 issues \xB7 est 61d"
|
||
}), /*#__PURE__*/React.createElement(Stat, {
|
||
label: "Done",
|
||
value: "24 \xB7 57%"
|
||
}), /*#__PURE__*/React.createElement(Stat, {
|
||
label: "Forecast",
|
||
value: "80% Mar 3\u201312"
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
padding: '12px 18px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
marginBottom: 5
|
||
}
|
||
}, "Drift \xB7 7d"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '500 14px var(--font-mono)',
|
||
color: 'var(--ok)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "\u22122d \xB7 cone narrowed")))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1.2fr 1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Burn-up",
|
||
title: /*#__PURE__*/React.createElement(React.Fragment, null, "80% this lands ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "Mar 3\u201312")),
|
||
jade: true
|
||
}, /*#__PURE__*/React.createElement(window.BurnUpCone, null), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '10px 0 0'
|
||
}
|
||
}, "Comfortably ahead. Beta needs #87 more than it needs my commentary.")), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Issues",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, groups.map(g => /*#__PURE__*/React.createElement("div", {
|
||
key: g.label
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7,
|
||
padding: '10px 20px 6px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, g.label), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, g.issues.length)), g.issues.map(i => /*#__PURE__*/React.createElement("div", {
|
||
key: i.id,
|
||
onClick: () => onOpenIssue({
|
||
id: i.id,
|
||
title: i.title,
|
||
labels: i.labels,
|
||
days: i.days
|
||
}),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '7px 20px',
|
||
cursor: 'pointer',
|
||
opacity: g.muted ? 0.6 : 1
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--paper-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
width: 34,
|
||
flexShrink: 0
|
||
}
|
||
}, "#", i.id), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-1)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap',
|
||
flex: 1
|
||
}
|
||
}, i.title), (i.labels || []).filter(l => l.startsWith('est/')).map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
}))))))))));
|
||
}
|
||
Object.assign(window, {
|
||
MilestoneScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/MilestoneScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/OnboardingScreen.jsx
|
||
try { (() => {
|
||
// Onboarding / first connect — welcome → connect gitea → choose repo → bootstrap
|
||
function OnboardingScreen({
|
||
onDone
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Button,
|
||
Input,
|
||
Radio,
|
||
Tag,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const [step, setStep] = React.useState(0);
|
||
const [conn, setConn] = React.useState('idle'); // idle | testing | ok
|
||
const [repo, setRepo] = React.useState('stephen/commitea');
|
||
const [boot, setBoot] = React.useState(-1); // -1 idle, 0..2 running, 3 done
|
||
|
||
React.useEffect(() => {
|
||
if (conn !== 'testing') return;
|
||
const t = setTimeout(() => setConn('ok'), 1100);
|
||
return () => clearTimeout(t);
|
||
}, [conn]);
|
||
React.useEffect(() => {
|
||
if (boot < 0 || boot >= 3) return;
|
||
const t = setTimeout(() => setBoot(boot + 1), 700);
|
||
return () => clearTimeout(t);
|
||
}, [boot]);
|
||
const STEPS = ['Welcome', 'Connect', 'Repo', 'Bootstrap'];
|
||
const BOOT_TASKS = ['Create stephen/pm-state (the sidecar)', 'Apply the label schema to stephen/commitea', 'Install a webhook · endpoint :48731'];
|
||
const Frame = ({
|
||
children,
|
||
footer
|
||
}) => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--surface-card)',
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-3)',
|
||
boxShadow: 'var(--shadow-jade-line), var(--shadow-2)',
|
||
padding: '30px 36px',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16,
|
||
width: '100%'
|
||
}
|
||
}, children, footer ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
justifyContent: 'flex-end',
|
||
borderTop: '1px solid var(--line-1)',
|
||
paddingTop: 16
|
||
}
|
||
}, footer) : null);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
minHeight: '100vh',
|
||
background: 'var(--surface-app)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
padding: 32,
|
||
gap: 22
|
||
},
|
||
"data-screen-label": "onboarding"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("img", {
|
||
src: "../../assets/logo-icon.png",
|
||
width: "34",
|
||
height: "34",
|
||
alt: "",
|
||
style: {
|
||
borderRadius: 8,
|
||
display: 'block'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 27px/1 var(--font-serif-display)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Commi", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--accent-text)'
|
||
}
|
||
}, "Tea"))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 14
|
||
}
|
||
}, STEPS.map((s, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: s,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 7
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 20,
|
||
height: 20,
|
||
borderRadius: '50%',
|
||
textAlign: 'center',
|
||
font: '500 10.5px/20px var(--font-mono)',
|
||
background: i < step ? 'var(--accent)' : i === step ? 'var(--spruce-2)' : 'var(--paper-2)',
|
||
color: i < step ? 'var(--ink-inverse)' : i === step ? 'var(--accent-text)' : 'var(--ink-3)'
|
||
}
|
||
}, i < step ? '\u2713' : i + 1), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: `${i === step ? 600 : 400} 12px/1 var(--font-sans)`,
|
||
color: i === step ? 'var(--ink-1)' : 'var(--ink-3)'
|
||
}
|
||
}, s)), i < STEPS.length - 1 ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 24,
|
||
height: 1,
|
||
background: 'var(--line-2)'
|
||
}
|
||
}) : null))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
width: 'min(540px, 100%)'
|
||
}
|
||
}, step === 0 ? /*#__PURE__*/React.createElement(Frame, {
|
||
footer: /*#__PURE__*/React.createElement(Button, {
|
||
iconRight: "arrow-right",
|
||
onClick: () => setStep(1)
|
||
}, "Begin")
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-title)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Good morning."), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent-lg)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "I'm Reginald, your project manager. I interview you instead of making you fill in forms, I forecast in honest ranges, and I never do the arithmetic myself \u2014 there's a scheduler for that."), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "Your plans live in your own Gitea as ordinary issues and labels. Delete me and nothing human is lost.")) : null, step === 1 ? /*#__PURE__*/React.createElement(Frame, {
|
||
footer: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => setStep(0)
|
||
}, "Back"), /*#__PURE__*/React.createElement(Button, {
|
||
iconRight: "arrow-right",
|
||
disabled: conn !== 'ok',
|
||
onClick: () => setStep(2)
|
||
}, "Continue"))
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-title)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Your Gitea"), /*#__PURE__*/React.createElement(Input, {
|
||
label: "Base URL",
|
||
icon: "link",
|
||
mono: true,
|
||
defaultValue: "https://gitea.stephenmann.io"
|
||
}), /*#__PURE__*/React.createElement(Input, {
|
||
label: "Access token",
|
||
icon: "keyboard",
|
||
mono: true,
|
||
type: "password",
|
||
defaultValue: "ct_9f2e81c4a7d6",
|
||
hint: "Scopes: repo, issue. Nothing more."
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "secondary",
|
||
icon: conn === 'testing' ? 'loader-circle' : 'zap',
|
||
disabled: conn === 'testing',
|
||
onClick: () => setConn('testing')
|
||
}, conn === 'testing' ? 'Ringing the bell…' : 'Test connection'), conn === 'ok' ? /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "ok",
|
||
dot: true
|
||
}, "connected \xB7 3 repos visible") : null)) : null, step === 2 ? /*#__PURE__*/React.createElement(Frame, {
|
||
footer: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => setStep(1)
|
||
}, "Back"), /*#__PURE__*/React.createElement(Button, {
|
||
iconRight: "arrow-right",
|
||
onClick: () => setStep(3)
|
||
}, "Continue"))
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-title)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Which repo shall I manage?"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8
|
||
}
|
||
}, ['stephen/commitea', 'stephen/novelpad', 'stephen/infra'].map(r => /*#__PURE__*/React.createElement("label", {
|
||
key: r,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: '10px 14px',
|
||
cursor: 'pointer',
|
||
background: repo === r ? 'var(--spruce-1)' : 'var(--paper-0)',
|
||
border: `1px solid ${repo === r ? 'var(--spruce-3)' : 'var(--line-1)'}`,
|
||
borderRadius: 'var(--radius-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Radio, {
|
||
name: "repo",
|
||
checked: repo === r,
|
||
onChange: () => setRepo(r)
|
||
}), /*#__PURE__*/React.createElement(Icon, {
|
||
name: "git-branch",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, r)))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, "One to start. You can add more later in Settings.")) : null, step === 3 ? /*#__PURE__*/React.createElement(Frame, {
|
||
footer: boot === 3 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => onDone('focus')
|
||
}, "Just look around"), /*#__PURE__*/React.createElement(Button, {
|
||
icon: "sparkles",
|
||
onClick: () => onDone('capture')
|
||
}, "Start a capture")) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: () => setStep(2),
|
||
disabled: boot >= 0
|
||
}, "Back"), /*#__PURE__*/React.createElement(Button, {
|
||
disabled: boot >= 0,
|
||
onClick: () => setBoot(0)
|
||
}, "Make it so"))
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-title)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, boot === 3 ? 'All set.' : 'With your approval'), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 10
|
||
}
|
||
}, BOOT_TASKS.map((t, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: t,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
color: boot > i ? 'var(--ok)' : boot === i ? 'var(--warn)' : 'var(--ink-3)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: boot > i ? 'circle-check' : boot === i ? 'loader-circle' : 'circle-dashed',
|
||
size: 15
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: boot > i ? 'var(--ink-1)' : 'var(--ink-2)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, t))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexWrap: 'wrap',
|
||
gap: 5,
|
||
paddingLeft: 25
|
||
}
|
||
}, ['est/1d', 'est/2d', 'est/3d', 'est/5d', 'est/8d', 'p/1', 'p/2', 'p/3', 'p/4', 'deadline/hard'].map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
})))), boot === 3 ? /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "The pot is empty. Tell me what you're planning and I'll draw up the tickets.") : /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, "No bot comments, no body frontmatter, no synthetic issues \u2014 ever. Labels are the only footprint.")) : null), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "first run \xB7 everything reversible"));
|
||
}
|
||
Object.assign(window, {
|
||
OnboardingScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/OnboardingScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/RunwayScreen.jsx
|
||
try { (() => {
|
||
// Runway — capacity vs milestone dates; ranges, never points
|
||
function RunwayScreen({
|
||
onOpenCalibration,
|
||
onOpenMilestone
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Badge,
|
||
Tag,
|
||
Icon
|
||
} = DS;
|
||
const d = window.CT_DATA;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Runway"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0'
|
||
}
|
||
}, "capacity vs milestone dates \xB7 calibrated on 27 closed issues")), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Milestones",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, d.runway.map((m, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: m.name,
|
||
onClick: onOpenMilestone,
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '160px 1fr 150px 90px',
|
||
gap: 16,
|
||
alignItems: 'center',
|
||
cursor: 'pointer',
|
||
padding: '14px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--paper-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "milestone",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}), m.name), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginTop: 3
|
||
}
|
||
}, "due ", m.due, m.hard ? ' ' : ''), m.hard ? /*#__PURE__*/React.createElement(Tag, {
|
||
label: "deadline/hard",
|
||
style: {
|
||
marginTop: 5
|
||
}
|
||
}) : null), /*#__PURE__*/React.createElement(window.RunwayBar, {
|
||
m: m
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, "80% ", m.p80), /*#__PURE__*/React.createElement(Badge, {
|
||
tone: m.tone,
|
||
dot: true
|
||
}, m.note))))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: 14,
|
||
alignItems: 'start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Capacity",
|
||
flush: true
|
||
}, /*#__PURE__*/React.createElement("div", null, d.capacity.map((p, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: p.who,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12,
|
||
padding: '12px 20px',
|
||
borderTop: i === 0 ? 'none' : '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 26,
|
||
height: 26,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 10px/26px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, p.who.split(' ').map(w => w[0]).join('')), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-body-strong)'
|
||
}
|
||
}, p.who), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginTop: 2
|
||
}
|
||
}, p.slices)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, p.hours))))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Calibration",
|
||
actions: /*#__PURE__*/React.createElement(DS.IconButton, {
|
||
icon: "arrow-up-right",
|
||
label: "Full report",
|
||
size: "sm",
|
||
onClick: onOpenCalibration
|
||
})
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
margin: '0 0 8px'
|
||
}
|
||
}, "Your estimates run ", /*#__PURE__*/React.createElement("strong", null, "18% optimistic"), " on ", /*#__PURE__*/React.createElement("code", null, "est/3d"), " and above. Smaller tickets are honest."), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "I widen the cone accordingly. No judgement \u2014 it's the most common shape of hope."))));
|
||
}
|
||
Object.assign(window, {
|
||
RunwayScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/RunwayScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/SettingsScreen.jsx
|
||
try { (() => {
|
||
// Settings — gitea connection, sync, model roles, labels, rituals, appearance
|
||
function SettingsScreen({
|
||
dark,
|
||
setDark
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Card,
|
||
Input,
|
||
Select,
|
||
Switch,
|
||
Radio,
|
||
Button,
|
||
IconButton,
|
||
Tag,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const [webhooks, setWebhooks] = React.useState(true);
|
||
const [reconcile, setReconcile] = React.useState(true);
|
||
const [poll, setPoll] = React.useState(true);
|
||
const [nag, setNag] = React.useState(true);
|
||
const Row = ({
|
||
children,
|
||
style
|
||
}) => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12,
|
||
...style
|
||
}
|
||
}, children);
|
||
const Note = ({
|
||
children
|
||
}) => /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-caption)',
|
||
color: 'var(--ink-3)',
|
||
margin: 0
|
||
}
|
||
}, children);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
maxWidth: 720,
|
||
margin: '0 auto',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Settings"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0'
|
||
}
|
||
}, "config lives in pm-state \xB7 versioned, portable")), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Gitea",
|
||
title: "Connection"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: "Base URL",
|
||
icon: "link",
|
||
mono: true,
|
||
defaultValue: "https://gitea.stephenmann.io"
|
||
}), /*#__PURE__*/React.createElement(Input, {
|
||
label: "Access token",
|
||
icon: "keyboard",
|
||
mono: true,
|
||
type: "password",
|
||
defaultValue: "ct_9f2e81c4a7d6",
|
||
hint: "Scopes: repo, issue. Nothing more."
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '600 13px/1.2 var(--font-sans)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Managed repos"), /*#__PURE__*/React.createElement(Row, {
|
||
style: {
|
||
padding: '8px 12px',
|
||
background: 'var(--paper-0)',
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "git-branch",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-1)',
|
||
flex: 1
|
||
}
|
||
}, "stephen/commitea"), /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "ok",
|
||
dot: true
|
||
}, "syncing"), /*#__PURE__*/React.createElement(IconButton, {
|
||
icon: "x",
|
||
label: "Stop managing",
|
||
size: "sm"
|
||
})), /*#__PURE__*/React.createElement(Row, {
|
||
style: {
|
||
padding: '8px 12px',
|
||
background: 'var(--paper-0)',
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "layers",
|
||
size: 14,
|
||
style: {
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-1)',
|
||
flex: 1
|
||
}
|
||
}, "stephen/pm-state"), /*#__PURE__*/React.createElement(Badge, null, "sidecar")), /*#__PURE__*/React.createElement(Note, null, "The sidecar holds machine-derived state only. Delete it and resync \u2014 no truth is lost."), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "secondary",
|
||
size: "sm",
|
||
icon: "plus",
|
||
style: {
|
||
alignSelf: 'flex-start'
|
||
}
|
||
}, "Add repo")))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Sync",
|
||
title: "Staying current"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement(Switch, {
|
||
label: "Webhooks while running",
|
||
checked: webhooks,
|
||
onChange: e => setWebhooks(e.target.checked)
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
marginLeft: 'auto'
|
||
}
|
||
}, "endpoint :48731 \xB7 healthy")), /*#__PURE__*/React.createElement(Switch, {
|
||
label: "Full reconcile on launch",
|
||
checked: reconcile,
|
||
onChange: e => setReconcile(e.target.checked)
|
||
}), /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement(Switch, {
|
||
label: "Poll fallback",
|
||
checked: poll,
|
||
onChange: e => setPoll(e.target.checked)
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
width: 140
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Select, {
|
||
options: [{
|
||
value: '2',
|
||
label: 'every 2 min'
|
||
}, {
|
||
value: '5',
|
||
label: 'every 5 min'
|
||
}, {
|
||
value: '15',
|
||
label: 'every 15 min'
|
||
}],
|
||
defaultValue: "5"
|
||
}))), /*#__PURE__*/React.createElement(Note, null, "last reconcile 3.2s \xB7 500 issues \xB7 nothing lost"))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Models",
|
||
title: "The router"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: '12px 14px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Select, {
|
||
label: "Prose & rituals",
|
||
options: [{
|
||
value: 'gemma-4b',
|
||
label: 'gemma-4b · local'
|
||
}, {
|
||
value: 'qwen-7b',
|
||
label: 'qwen-7b · local'
|
||
}],
|
||
defaultValue: "gemma-4b"
|
||
}), /*#__PURE__*/React.createElement(Input, {
|
||
label: "Base URL",
|
||
mono: true,
|
||
defaultValue: "http://localhost:1234/v1"
|
||
}), /*#__PURE__*/React.createElement(Select, {
|
||
label: "Decomposition & negotiation",
|
||
options: [{
|
||
value: 'qwen-72b',
|
||
label: 'qwen-72b · lm-studio box'
|
||
}, {
|
||
value: 'gpt-4o',
|
||
label: 'gpt-4o · OpenAI API'
|
||
}],
|
||
defaultValue: "qwen-72b"
|
||
}), /*#__PURE__*/React.createElement(Input, {
|
||
label: "Base URL",
|
||
mono: true,
|
||
defaultValue: "http://10.0.0.42:1234/v1"
|
||
})), /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "hot memory \u2264 2k tokens \xB7 math is never delegated to either")), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "The small one writes my standup; the large one argues with your estimates. Neither is allowed near the arithmetic."))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Labels",
|
||
title: "Schema"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Row, {
|
||
style: {
|
||
flexWrap: 'wrap',
|
||
gap: 6
|
||
}
|
||
}, ['est/1d', 'est/2d', 'est/3d', 'est/5d', 'est/8d'].map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
}))), /*#__PURE__*/React.createElement(Row, {
|
||
style: {
|
||
flexWrap: 'wrap',
|
||
gap: 6
|
||
}
|
||
}, ['p/1', 'p/2', 'p/3', 'p/4'].map(l => /*#__PURE__*/React.createElement(Tag, {
|
||
key: l,
|
||
label: l
|
||
})), /*#__PURE__*/React.createElement(Tag, {
|
||
label: "deadline/hard"
|
||
})), /*#__PURE__*/React.createElement(Note, null, "Fixed sets, human-meaningful, visible in gitea. Not configurable \u2014 that is rather the point."))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Rituals",
|
||
title: "Reginald's calendar"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Morning standup"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
width: 120
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Select, {
|
||
options: [{
|
||
value: '0630',
|
||
label: '06:30'
|
||
}, {
|
||
value: '0700',
|
||
label: '07:00'
|
||
}, {
|
||
value: '0800',
|
||
label: '08:00'
|
||
}],
|
||
defaultValue: "0700"
|
||
}))), /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement(Switch, {
|
||
label: "Stale-blocker nagging",
|
||
checked: nag,
|
||
onChange: e => setNag(e.target.checked)
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
width: 140
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Select, {
|
||
options: [{
|
||
value: '2',
|
||
label: 'after 2 days'
|
||
}, {
|
||
value: '3',
|
||
label: 'after 3 days'
|
||
}, {
|
||
value: '5',
|
||
label: 'after 5 days'
|
||
}],
|
||
defaultValue: "3"
|
||
}))))), /*#__PURE__*/React.createElement(Card, {
|
||
overline: "Appearance",
|
||
title: "Service"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 20
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Radio, {
|
||
name: "theme",
|
||
label: "Morning (light)",
|
||
checked: !dark,
|
||
onChange: () => setDark(false)
|
||
}), /*#__PURE__*/React.createElement(Radio, {
|
||
name: "theme",
|
||
label: "Evening (dark)",
|
||
checked: dark,
|
||
onChange: () => setDark(true)
|
||
}))), /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Forget this gitea"), /*#__PURE__*/React.createElement(Note, null, "Removes the connection and the local cache. Gitea itself is untouched.")), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "danger"
|
||
}, "Forget"))));
|
||
}
|
||
Object.assign(window, {
|
||
SettingsScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/SettingsScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/Shell.jsx
|
||
try { (() => {
|
||
// App shell — left rail + content + agent panel, issue page, theme toggle
|
||
function Shell() {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Icon,
|
||
Switch
|
||
} = DS;
|
||
const [view, setView] = React.useState('focus');
|
||
const [prevView, setPrevView] = React.useState('focus');
|
||
const [dark, setDark] = React.useState(false);
|
||
const [issue, setIssue] = React.useState(null);
|
||
const [offline, setOffline] = React.useState(false);
|
||
const [readIds, setReadIds] = React.useState([]);
|
||
const inboxUnread = window.CT_DATA.inbox.filter(n => n.unread && !readIds.includes(n.id)).length;
|
||
const openIssue = i => {
|
||
setIssue(i);
|
||
if (view !== 'issue') setPrevView(view);
|
||
setView('issue');
|
||
};
|
||
React.useEffect(() => {
|
||
document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light');
|
||
}, [dark]);
|
||
if (view === 'firstrun') {
|
||
return /*#__PURE__*/React.createElement(window.OnboardingScreen, {
|
||
onDone: dest => setView(dest)
|
||
});
|
||
}
|
||
const NAV = [{
|
||
id: 'standup',
|
||
label: 'Standup',
|
||
icon: 'sun'
|
||
}, {
|
||
id: 'focus',
|
||
label: 'Morning service',
|
||
icon: 'coffee'
|
||
}, {
|
||
id: 'inbox',
|
||
label: 'Inbox',
|
||
icon: 'bell',
|
||
count: inboxUnread || null
|
||
}, {
|
||
id: 'capture',
|
||
label: 'Capture',
|
||
icon: 'plus'
|
||
}, {
|
||
id: 'board',
|
||
label: 'The pot',
|
||
icon: 'square-kanban'
|
||
}, {
|
||
id: 'runway',
|
||
label: 'Runway',
|
||
icon: 'chart-line'
|
||
}, {
|
||
id: 'directives',
|
||
label: 'Directives',
|
||
icon: 'flag'
|
||
}];
|
||
const NavItem = ({
|
||
item
|
||
}) => {
|
||
const active = view === item.id || view === 'issue' && prevView === item.id || (view === 'calibration' || view === 'milestone') && item.id === 'runway';
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: () => setView(item.id),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
width: '100%',
|
||
font: `${active ? 600 : 500} 13.5px/1 var(--font-sans)`,
|
||
color: active ? 'var(--ink-1)' : 'var(--ink-2)',
|
||
background: active ? 'var(--paper-2)' : 'transparent',
|
||
border: 'none',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '9px 12px',
|
||
cursor: 'pointer',
|
||
textAlign: 'left',
|
||
transition: 'background var(--duration-fast) var(--ease-out)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: item.icon,
|
||
size: 16,
|
||
style: {
|
||
color: active ? 'var(--accent-text)' : 'var(--ink-3)'
|
||
}
|
||
}), item.label, item.count ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
font: '500 10.5px/16px var(--font-mono)',
|
||
color: 'var(--accent-text)',
|
||
background: 'var(--spruce-2)',
|
||
borderRadius: 'var(--radius-round)',
|
||
padding: '0 6px'
|
||
}
|
||
}, item.count) : null);
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
height: '100vh',
|
||
minWidth: 1280,
|
||
background: 'var(--surface-app)',
|
||
overflow: 'hidden'
|
||
},
|
||
"data-screen-label": `app-${view}`
|
||
}, /*#__PURE__*/React.createElement("nav", {
|
||
style: {
|
||
width: 208,
|
||
flexShrink: 0,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 4,
|
||
padding: '18px 12px 14px',
|
||
borderRight: '1px solid var(--line-1)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 9,
|
||
padding: '0 12px 16px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("img", {
|
||
src: "../../assets/logo-icon.png",
|
||
width: "24",
|
||
height: "24",
|
||
alt: "",
|
||
style: {
|
||
borderRadius: 6,
|
||
display: 'block'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 21px/1 var(--font-serif-display)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "Commi", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--accent-text)'
|
||
}
|
||
}, "Tea"))), NAV.map(n => /*#__PURE__*/React.createElement(NavItem, {
|
||
key: n.id,
|
||
item: n
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
borderTop: '1px solid var(--line-1)',
|
||
margin: '10px 8px'
|
||
}
|
||
}), /*#__PURE__*/React.createElement(NavItem, {
|
||
item: {
|
||
id: 'settings',
|
||
label: 'Settings',
|
||
icon: 'settings-2'
|
||
}
|
||
}), /*#__PURE__*/React.createElement(NavItem, {
|
||
item: {
|
||
id: 'firstrun',
|
||
label: 'First run',
|
||
icon: 'play'
|
||
}
|
||
}), /*#__PURE__*/React.createElement(NavItem, {
|
||
item: {
|
||
id: 'states',
|
||
label: 'States',
|
||
icon: 'circle-dashed'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginTop: 'auto',
|
||
padding: '0 12px',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
onClick: () => setOffline(!offline),
|
||
title: "Toggle the connection (demo)",
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
background: 'none',
|
||
border: 'none',
|
||
padding: 0,
|
||
cursor: 'pointer',
|
||
textAlign: 'left'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: '50%',
|
||
background: offline ? 'var(--danger)' : 'var(--ok)',
|
||
display: 'inline-block'
|
||
}
|
||
}), "gitea.stephenmann.io"), /*#__PURE__*/React.createElement(Switch, {
|
||
label: /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-caption)'
|
||
}
|
||
}, "Evening service"),
|
||
checked: dark,
|
||
onChange: e => setDark(e.target.checked)
|
||
}))), /*#__PURE__*/React.createElement("main", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0,
|
||
overflowY: 'auto',
|
||
padding: '24px 28px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
maxWidth: 1120,
|
||
margin: '0 auto',
|
||
height: view === 'board' ? '100%' : 'auto',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, offline ? /*#__PURE__*/React.createElement(window.OfflineBanner, null) : null, view === 'focus' ? /*#__PURE__*/React.createElement(window.FocusScreen, {
|
||
onOpenIssue: openIssue
|
||
}) : null, view === 'board' ? /*#__PURE__*/React.createElement(window.BoardScreen, {
|
||
onOpenIssue: openIssue
|
||
}) : null, view === 'runway' ? /*#__PURE__*/React.createElement(window.RunwayScreen, {
|
||
onOpenCalibration: () => setView('calibration'),
|
||
onOpenMilestone: () => setView('milestone')
|
||
}) : null, view === 'capture' ? /*#__PURE__*/React.createElement(window.CaptureScreen, {
|
||
onDone: () => setView('focus')
|
||
}) : null, view === 'standup' ? /*#__PURE__*/React.createElement(window.StandupScreen, {
|
||
onBegin: () => setView('focus'),
|
||
onOpenIssue: openIssue
|
||
}) : null, view === 'settings' ? /*#__PURE__*/React.createElement(window.SettingsScreen, {
|
||
dark: dark,
|
||
setDark: setDark
|
||
}) : null, view === 'directives' ? /*#__PURE__*/React.createElement(window.DirectivesScreen, null) : null, view === 'issue' && issue ? /*#__PURE__*/React.createElement(window.IssueScreen, {
|
||
issue: issue,
|
||
onBack: () => setView(prevView),
|
||
onOpenIssue: openIssue
|
||
}) : null, view === 'calibration' ? /*#__PURE__*/React.createElement(window.CalibrationScreen, {
|
||
onBack: () => setView('runway')
|
||
}) : null, view === 'milestone' ? /*#__PURE__*/React.createElement(window.MilestoneScreen, {
|
||
onBack: () => setView('runway'),
|
||
onOpenIssue: openIssue
|
||
}) : null, view === 'states' ? /*#__PURE__*/React.createElement(window.StatesScreen, {
|
||
onCapture: () => setView('capture')
|
||
}) : null, view === 'inbox' ? /*#__PURE__*/React.createElement(window.InboxScreen, {
|
||
onOpenIssue: openIssue,
|
||
onOpenDirectives: () => setView('directives'),
|
||
readIds: readIds,
|
||
setReadIds: setReadIds
|
||
}) : null)), /*#__PURE__*/React.createElement(window.ChatPanel, {
|
||
onOpenDirectives: () => setView('directives'),
|
||
offline: offline
|
||
}));
|
||
}
|
||
Object.assign(window, {
|
||
Shell
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/Shell.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/StandupScreen.jsx
|
||
try { (() => {
|
||
// Morning standup ritual — a typeset letter from Reginald: drift, plan, nag
|
||
const standupCSS = `
|
||
@keyframes ct-standup-settle {
|
||
from { opacity: 0; transform: translateY(6px); }
|
||
to { opacity: 1; transform: none; }
|
||
}
|
||
.ct-standup-section { opacity: 1; }
|
||
@media (prefers-reduced-motion: no-preference) {
|
||
.ct-standup-section { animation: ct-standup-settle 320ms var(--ease-out) both; }
|
||
}
|
||
`;
|
||
(function inject() {
|
||
if (typeof document !== 'undefined' && !document.getElementById('ct-standup-css')) {
|
||
const s = document.createElement('style');
|
||
s.id = 'ct-standup-css';
|
||
s.textContent = standupCSS;
|
||
document.head.appendChild(s);
|
||
}
|
||
})();
|
||
function StandupScreen({
|
||
onBegin,
|
||
onOpenIssue
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Button,
|
||
Tag,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const s = window.CT_DATA.standup;
|
||
const Section = ({
|
||
overline,
|
||
children,
|
||
order
|
||
}) => /*#__PURE__*/React.createElement("section", {
|
||
className: "ct-standup-section",
|
||
style: {
|
||
animationDelay: `${order * 90}ms`,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
margin: 0,
|
||
borderTop: '1px solid var(--line-1)',
|
||
paddingTop: 14
|
||
}
|
||
}, overline), children);
|
||
const toneColor = {
|
||
ok: 'var(--ok)',
|
||
warn: 'var(--warn)',
|
||
danger: 'var(--danger)'
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
maxWidth: 660,
|
||
margin: '0 auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("article", {
|
||
style: {
|
||
background: 'var(--surface-card)',
|
||
border: '1px solid var(--line-1)',
|
||
borderRadius: 'var(--radius-3)',
|
||
boxShadow: 'var(--shadow-jade-line), var(--shadow-1)',
|
||
padding: '36px 44px 32px',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 20
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
className: "ct-standup-section",
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '0 0 8px'
|
||
}
|
||
}, s.date, " \xB7 prepared 07:00"), /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "Morning standup")), /*#__PURE__*/React.createElement(Section, {
|
||
overline: "Overnight drift",
|
||
order: 1
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 10
|
||
}
|
||
}, s.drift.map(d => /*#__PURE__*/React.createElement("div", {
|
||
key: d.text,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: '50%',
|
||
background: toneColor[d.tone],
|
||
flexShrink: 0,
|
||
position: 'relative',
|
||
top: -1
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body)',
|
||
color: 'var(--ink-1)',
|
||
flex: 1
|
||
}
|
||
}, d.text), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, d.delta))))), /*#__PURE__*/React.createElement(Section, {
|
||
overline: "Today's plan",
|
||
order: 2
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 12
|
||
}
|
||
}, s.plan.map(p => /*#__PURE__*/React.createElement("div", {
|
||
key: p.who,
|
||
style: {
|
||
display: 'flex',
|
||
gap: 12,
|
||
alignItems: 'flex-start'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 26,
|
||
height: 26,
|
||
borderRadius: '50%',
|
||
background: 'var(--spruce-2)',
|
||
color: 'var(--accent-text)',
|
||
font: '600 10px/26px var(--font-sans)',
|
||
textAlign: 'center',
|
||
flexShrink: 0
|
||
}
|
||
}, p.who.split(' ').map(w => w[0]).join('')), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-1)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, p.who), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 12px var(--font-mono)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, p.pick), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, p.title)), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '4px 0 0'
|
||
}
|
||
}, p.why)))))), /*#__PURE__*/React.createElement(Section, {
|
||
overline: "Stale blockers",
|
||
order: 3
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => onOpenIssue({
|
||
id: s.nag.id,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
labels: ['est/2d', 'p/1'],
|
||
days: s.nag.days
|
||
}),
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10,
|
||
alignItems: 'flex-start',
|
||
cursor: 'pointer',
|
||
background: 'var(--warn-tint)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '12px 14px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--warn)',
|
||
display: 'inline-flex',
|
||
marginTop: 2
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "clock",
|
||
size: 15
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '500 12.5px var(--font-mono)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, "#", s.nag.id), /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "warn",
|
||
dot: true
|
||
}, "steeping ", s.nag.days), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "blocks ", s.nag.blocks.join(', '))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: '5px 0 0'
|
||
}
|
||
}, s.nag.text)))), /*#__PURE__*/React.createElement("footer", {
|
||
className: "ct-standup-section",
|
||
style: {
|
||
animationDelay: '360ms',
|
||
borderTop: '1px solid var(--line-1)',
|
||
paddingTop: 16,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent-lg)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0,
|
||
flex: 1
|
||
}
|
||
}, "The kettle's on. \u2014 R."), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
onClick: onBegin
|
||
}, "Ask about the drift"), /*#__PURE__*/React.createElement(Button, {
|
||
iconRight: "arrow-right",
|
||
onClick: onBegin
|
||
}, "Begin the day"))));
|
||
}
|
||
Object.assign(window, {
|
||
StandupScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/StandupScreen.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/StatesGallery.jsx
|
||
try { (() => {
|
||
// Shared empty/trouble states + the States gallery screen
|
||
function EmptyState({
|
||
icon,
|
||
title,
|
||
line,
|
||
action,
|
||
onAction,
|
||
compact
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Button,
|
||
Icon
|
||
} = DS;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
textAlign: 'center',
|
||
gap: 10,
|
||
padding: compact ? '28px 20px' : '52px 24px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 44,
|
||
height: 44,
|
||
borderRadius: '50%',
|
||
background: 'var(--paper-2)',
|
||
color: 'var(--ink-3)',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: icon,
|
||
size: 19
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
font: '400 20px/1.25 var(--font-serif-display)',
|
||
color: 'var(--ink-1)'
|
||
}
|
||
}, title), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0,
|
||
maxWidth: 380
|
||
}
|
||
}, line), action ? /*#__PURE__*/React.createElement(Button, {
|
||
style: {
|
||
marginTop: 6
|
||
},
|
||
onClick: onAction
|
||
}, action) : null);
|
||
}
|
||
function OfflineBanner({
|
||
retryIn
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Icon
|
||
} = DS;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
background: 'var(--warn-tint)',
|
||
border: '1px solid var(--warn)',
|
||
borderRadius: 'var(--radius-2)',
|
||
padding: '9px 14px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--warn)',
|
||
display: 'inline-flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "triangle-alert",
|
||
size: 15
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-small)',
|
||
color: 'var(--ink-1)',
|
||
flex: 1
|
||
}
|
||
}, "Gitea isn't answering. I'll keep trying and say nothing more about it."), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, "retry in ", retryIn || '0:12', " \xB7 reads from cache"));
|
||
}
|
||
function ModelAwayState() {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Icon,
|
||
Badge
|
||
} = DS;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8,
|
||
padding: '14px 16px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--ink-3)',
|
||
display: 'inline-flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, {
|
||
name: "sparkles",
|
||
size: 15
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: 'var(--text-body-strong)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, "Reginald"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, "model offline"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Badge, null, "queued: 1 directive"))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-agent)',
|
||
color: 'var(--ink-2)',
|
||
margin: 0
|
||
}
|
||
}, "The model is away from its desk. Reads still work; writes will wait their turn."));
|
||
}
|
||
function StatesScreen({
|
||
onCapture
|
||
}) {
|
||
const DS = window.CommiTeaDesignSystem_20e63b;
|
||
const {
|
||
Button,
|
||
Badge,
|
||
Icon
|
||
} = DS;
|
||
const Specimen = ({
|
||
label,
|
||
children
|
||
}) => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11px var(--font-mono)',
|
||
color: 'var(--ink-3)'
|
||
}
|
||
}, label), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
border: '1px dashed var(--line-2)',
|
||
borderRadius: 'var(--radius-3)',
|
||
background: 'var(--surface-card)',
|
||
overflow: 'hidden'
|
||
}
|
||
}, children));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 16
|
||
}
|
||
}, /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
borderBottom: 'var(--rule-double)',
|
||
paddingBottom: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("h1", {
|
||
style: {
|
||
font: 'var(--text-display)',
|
||
color: 'var(--ink-1)',
|
||
margin: 0
|
||
}
|
||
}, "States"), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-data)',
|
||
color: 'var(--ink-3)',
|
||
margin: '6px 0 0'
|
||
}
|
||
}, "empty & trouble \xB7 specimens as wired in the app")), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
margin: '4px 0 0'
|
||
}
|
||
}, "Empty"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "the pot \xB7 no issues"
|
||
}, /*#__PURE__*/React.createElement(EmptyState, {
|
||
compact: true,
|
||
icon: "inbox",
|
||
title: "The pot is empty",
|
||
line: "Tell me what you're planning and I'll draw up the tickets.",
|
||
action: "Start a capture",
|
||
onAction: onCapture
|
||
})), /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "morning service \xB7 nothing scheduled"
|
||
}, /*#__PURE__*/React.createElement(EmptyState, {
|
||
compact: true,
|
||
icon: "coffee",
|
||
title: "Nothing to pour",
|
||
line: "Capture some work, or enjoy the silence \u2014 it never lasts."
|
||
})), /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "directives \xB7 no entries"
|
||
}, /*#__PURE__*/React.createElement(EmptyState, {
|
||
compact: true,
|
||
icon: "flag",
|
||
title: "No directives yet",
|
||
line: "When you overrule the scheduler, it goes on the record here \u2014 who, when, what, why."
|
||
})), /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "board search \xB7 no match"
|
||
}, /*#__PURE__*/React.createElement(EmptyState, {
|
||
compact: true,
|
||
icon: "search",
|
||
title: "Nothing by that name",
|
||
line: "The pot holds 24 issues; none of them answer to that."
|
||
}))), /*#__PURE__*/React.createElement("p", {
|
||
style: {
|
||
font: 'var(--text-overline)',
|
||
letterSpacing: 'var(--letter-spacing-wide)',
|
||
textTransform: 'uppercase',
|
||
color: 'var(--ink-3)',
|
||
margin: '8px 0 0'
|
||
}
|
||
}, "Trouble"), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "gitea unreachable \xB7 banner above main content (toggle the rail's connection dot to see it live)"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(OfflineBanner, null))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "reginald's panel \xB7 model offline"
|
||
}, /*#__PURE__*/React.createElement(ModelAwayState, null)), /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "webhooks down \xB7 poll fallback"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: '14px 16px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Badge, {
|
||
tone: "warn",
|
||
dot: true
|
||
}, "webhooks down"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
font: '400 11.5px var(--font-mono)',
|
||
color: 'var(--ink-2)'
|
||
}
|
||
}, "polling every 2 min \xB7 updates may lag")))), /*#__PURE__*/React.createElement(Specimen, {
|
||
label: "first reconcile failed \xB7 full-screen"
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
padding: '8px 0 20px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(EmptyState, {
|
||
compact: true,
|
||
icon: "refresh-cw",
|
||
title: "The reconcile failed",
|
||
line: "Gitea answered, then hung up mid-sentence. Your cache is intact; nothing human is lost."
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
marginTop: -6
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, null, "Try again"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost"
|
||
}, "Work from cache"))))));
|
||
}
|
||
Object.assign(window, {
|
||
EmptyState,
|
||
OfflineBanner,
|
||
ModelAwayState,
|
||
StatesScreen
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/StatesGallery.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/app/data.js
|
||
try { (() => {
|
||
// CommiTea fixture data — human-authored intent (gitea) + machine-derived state (sidecar)
|
||
window.CT_DATA = {
|
||
today: 'Tuesday 7 July 2026',
|
||
milestone: {
|
||
name: 'Beta',
|
||
due: '2026-03-15',
|
||
hard: false,
|
||
forecast: {
|
||
p80: 'Mar 3–12',
|
||
p50: 'Mar 5–8',
|
||
drift: '+0d'
|
||
}
|
||
},
|
||
focus: {
|
||
now: {
|
||
id: 87,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
labels: ['est/2d', 'p/1'],
|
||
steeping: '4d',
|
||
rationale: 'It blocks #91 and #92. I\u2019d take it first \u2014 the critical path agrees with me.'
|
||
},
|
||
next: {
|
||
id: 91,
|
||
title: 'Webhook listener: reconcile on reconnect',
|
||
labels: ['est/3d', 'p/2'],
|
||
rationale: 'Ready the moment #87 lands. The estimate is yours; history says add a day.'
|
||
},
|
||
later: {
|
||
id: 78,
|
||
title: 'Calibration store cold-start distributions',
|
||
labels: ['est/5d', 'p/3'],
|
||
rationale: 'Nothing depends on it yet. It can steep.'
|
||
}
|
||
},
|
||
columns: [{
|
||
id: 'diagnosis',
|
||
label: 'Diagnosis',
|
||
issues: [{
|
||
id: 102,
|
||
title: 'Scheduler ignores standing allocation slices',
|
||
labels: ['p/2'],
|
||
who: 'SM'
|
||
}, {
|
||
id: 103,
|
||
title: 'Dark theme: cone fill too faint',
|
||
labels: ['p/4'],
|
||
who: 'SM'
|
||
}]
|
||
}, {
|
||
id: 'triage',
|
||
label: 'Triage',
|
||
issues: [{
|
||
id: 99,
|
||
title: 'Directive log: conflict-free merge test',
|
||
labels: ['est/1d', 'p/2'],
|
||
who: 'SM'
|
||
}, {
|
||
id: 96,
|
||
title: 'Label schema bootstrap for new repos',
|
||
labels: ['est/2d', 'p/3'],
|
||
who: 'AK'
|
||
}, {
|
||
id: 78,
|
||
title: 'Calibration store cold-start distributions',
|
||
labels: ['est/5d', 'p/3'],
|
||
who: 'SM'
|
||
}]
|
||
}, {
|
||
id: 'steeping',
|
||
label: 'Steeping',
|
||
issues: [{
|
||
id: 87,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
labels: ['est/2d', 'p/1'],
|
||
who: 'SM',
|
||
blocked: false,
|
||
days: '4d'
|
||
}, {
|
||
id: 84,
|
||
title: 'Capacity model: focus factor per person',
|
||
labels: ['est/3d', 'p/2'],
|
||
who: 'AK',
|
||
days: '1d'
|
||
}]
|
||
}, {
|
||
id: 'review',
|
||
label: 'In review',
|
||
issues: [{
|
||
id: 92,
|
||
title: 'Monte Carlo engine: percentile bands',
|
||
labels: ['est/5d', 'p/1'],
|
||
who: 'SM',
|
||
pr: '#141'
|
||
}]
|
||
}, {
|
||
id: 'done',
|
||
label: 'Done',
|
||
issues: [{
|
||
id: 71,
|
||
title: 'Gitea client: token auth + retries',
|
||
labels: ['est/2d', 'p/2'],
|
||
who: 'SM'
|
||
}, {
|
||
id: 69,
|
||
title: 'pm-state repo bootstrap',
|
||
labels: ['est/1d', 'p/1'],
|
||
who: 'SM'
|
||
}, {
|
||
id: 65,
|
||
title: 'Electron shell + window state',
|
||
labels: ['est/3d', 'p/2'],
|
||
who: 'AK'
|
||
}]
|
||
}],
|
||
runway: [{
|
||
name: 'Beta',
|
||
due: 'Mar 15',
|
||
hard: false,
|
||
p80: 'Mar 3–12',
|
||
pos: 0.62,
|
||
spread: 0.18,
|
||
tone: 'ok',
|
||
note: 'ahead'
|
||
}, {
|
||
name: 'Pilot-ready',
|
||
due: 'Apr 30',
|
||
hard: true,
|
||
p80: 'Apr 21 – May 9',
|
||
pos: 0.94,
|
||
spread: 0.26,
|
||
tone: 'warn',
|
||
note: 'drifting'
|
||
}, {
|
||
name: 'v1.0',
|
||
due: 'Jun 12',
|
||
hard: false,
|
||
p80: 'May 30 – Jun 20',
|
||
pos: 0.88,
|
||
spread: 0.3,
|
||
tone: 'ok',
|
||
note: 'on watch'
|
||
}],
|
||
capacity: [{
|
||
who: 'Stephen',
|
||
hours: '5.2h/day',
|
||
focus: 0.65,
|
||
slices: 'dev 70% · pilots 20% · compliance 10%'
|
||
}, {
|
||
who: 'Ana K.',
|
||
hours: '3.8h/day',
|
||
focus: 0.8,
|
||
slices: 'dev 100%'
|
||
}],
|
||
chat: [{
|
||
from: 'agent',
|
||
text: 'Morning service. Two things drifted overnight; one needs your opinion.'
|
||
}, {
|
||
from: 'agent',
|
||
text: '#84 grew a dependency on #92 \u2014 I\u2019ve reordered. And #87 has been steeping for four days; it blocks two others. Worth a look.'
|
||
}, {
|
||
from: 'user',
|
||
text: 'Push the calibration work to next week, pilots come first'
|
||
}, {
|
||
from: 'agent',
|
||
text: 'Done \u2014 #78 moves to next week. Milestone Beta is unmoved; the cone doesn\u2019t care for calibration either. Logged as a directive.'
|
||
}],
|
||
cannedReply: 'Noted and logged as a directive. The scheduler is re-running \u2014 I\u2019ll show you the consequence diff in a moment.',
|
||
standup: {
|
||
date: 'Tuesday 7 July 2026',
|
||
drift: [{
|
||
tone: 'warn',
|
||
text: '#84 grew a dependency on #92 overnight.',
|
||
delta: 'reordered \u00b7 no date impact'
|
||
}, {
|
||
tone: 'warn',
|
||
text: '#92 has sat in review for two days.',
|
||
delta: 'Beta 80% +1d if idle past Thu'
|
||
}, {
|
||
tone: 'ok',
|
||
text: 'Webhook outage 02:14\u201302:31; full reconcile ran.',
|
||
delta: 'nothing lost'
|
||
}],
|
||
plan: [{
|
||
who: 'Stephen',
|
||
pick: '#87',
|
||
title: 'Fix lifecycle inference on merge events',
|
||
why: 'It blocks two others and the critical path runs straight through it.'
|
||
}, {
|
||
who: 'Ana K.',
|
||
pick: '#84',
|
||
title: 'Capacity model: focus factor per person',
|
||
why: 'Already steeping \u2014 finish it before anything new is poured.'
|
||
}],
|
||
nag: {
|
||
id: 87,
|
||
days: '4d',
|
||
blocks: ['#91', '#92'],
|
||
text: 'Four days is a long steep. It blocks #91 and #92 \u2014 worth a look before it stains.'
|
||
}
|
||
},
|
||
calibration: {
|
||
n: 27,
|
||
active: true,
|
||
labels: [{
|
||
label: 'est/1d',
|
||
n: 8,
|
||
median: '1.1d',
|
||
bias: 8
|
||
}, {
|
||
label: 'est/2d',
|
||
n: 9,
|
||
median: '2.4d',
|
||
bias: 18
|
||
}, {
|
||
label: 'est/3d',
|
||
n: 6,
|
||
median: '3.7d',
|
||
bias: 22
|
||
}, {
|
||
label: 'est/5d',
|
||
n: 3,
|
||
median: '6.5d',
|
||
bias: 30
|
||
}, {
|
||
label: 'est/8d',
|
||
n: 1,
|
||
median: '8.5d',
|
||
bias: null
|
||
}],
|
||
people: [{
|
||
who: 'Stephen',
|
||
n: 19,
|
||
bias: 21,
|
||
note: 'optimism grows with ticket size'
|
||
}, {
|
||
who: 'Ana K.',
|
||
n: 8,
|
||
bias: 9,
|
||
note: 'close to honest \u2014 suspicious'
|
||
}],
|
||
scatter: [[1, 1], [1, 1.2], [1, 0.9], [1, 1.5], [1, 1.1], [1, 0.8], [1, 1.3], [1, 1.2], [2, 2], [2, 2.5], [2, 3.1], [2, 2.2], [2, 2.6], [2, 1.8], [2, 2.4], [2, 2.9], [2, 2.3], [3, 3.5], [3, 4.1], [3, 3.1], [3, 4.6], [3, 3.6], [3, 3.9], [5, 6.1], [5, 7.2], [5, 6.4], [8, 8.5]],
|
||
fit: 1.18,
|
||
effect: {
|
||
raw: '42d of estimates',
|
||
banded: '80% band 46\u201353d',
|
||
p50: '48d'
|
||
}
|
||
},
|
||
inbox: [{
|
||
id: 1,
|
||
day: 'Today',
|
||
type: 'drift',
|
||
icon: 'chart-line',
|
||
tone: 'warn',
|
||
text: 'Beta\u2019s 80% window moved',
|
||
detail: 'Mar 3\u201312 \u2192 Mar 5\u201314 \u00b7 directive #007',
|
||
time: '09:14',
|
||
unread: true,
|
||
to: 'directives'
|
||
}, {
|
||
id: 2,
|
||
day: 'Today',
|
||
type: 'mention',
|
||
icon: 'message-square',
|
||
tone: 'info',
|
||
who: 'Ana K.',
|
||
text: 'mentioned you on #92',
|
||
detail: '\u201cpercentile bands ready for a second pair of eyes\u201d',
|
||
time: '08:52',
|
||
unread: true,
|
||
issue: {
|
||
id: 92,
|
||
title: 'Monte Carlo engine: percentile bands',
|
||
labels: ['est/5d', 'p/1']
|
||
}
|
||
}, {
|
||
id: 3,
|
||
day: 'Today',
|
||
type: 'nag',
|
||
icon: 'clock',
|
||
tone: 'warn',
|
||
text: '#87 is steeping \u00b7 4d',
|
||
detail: 'blocks #91 and #92 \u2014 worth a look before it stains',
|
||
time: '07:00',
|
||
unread: true,
|
||
issue: {
|
||
id: 87,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
labels: ['est/2d', 'p/1'],
|
||
days: '4d'
|
||
}
|
||
}, {
|
||
id: 4,
|
||
day: 'Yesterday',
|
||
type: 'review',
|
||
icon: 'git-pull-request',
|
||
tone: 'info',
|
||
text: 'PR #141 awaits review',
|
||
detail: '#92 \u00b7 idle two days',
|
||
time: '16:20',
|
||
unread: false,
|
||
issue: {
|
||
id: 92,
|
||
title: 'Monte Carlo engine: percentile bands',
|
||
labels: ['est/5d', 'p/1']
|
||
}
|
||
}, {
|
||
id: 5,
|
||
day: 'Yesterday',
|
||
type: 'assignment',
|
||
icon: 'user',
|
||
tone: 'neutral',
|
||
who: 'Ana K.',
|
||
text: 'took #96 from the pot',
|
||
detail: 'Label schema bootstrap for new repos',
|
||
time: '11:03',
|
||
unread: false,
|
||
issue: {
|
||
id: 96,
|
||
title: 'Label schema bootstrap for new repos',
|
||
labels: ['est/2d', 'p/3']
|
||
}
|
||
}, {
|
||
id: 6,
|
||
day: 'Yesterday',
|
||
type: 'system',
|
||
icon: 'refresh-cw',
|
||
tone: 'ok',
|
||
text: 'Webhook outage 02:14\u201302:31',
|
||
detail: 'full reconcile ran \u00b7 nothing lost',
|
||
time: '02:31',
|
||
unread: false
|
||
}, {
|
||
id: 7,
|
||
day: 'Yesterday',
|
||
type: 'milestone',
|
||
icon: 'milestone',
|
||
tone: 'ok',
|
||
text: 'P2 \u2014 Scheduler closed two days early',
|
||
detail: 'the calibration noticed. So did I.',
|
||
time: '09:40',
|
||
unread: false
|
||
}],
|
||
issueDetail: {
|
||
87: {
|
||
state: 'steeping',
|
||
assignee: 'Stephen',
|
||
milestone: 'Beta',
|
||
body: 'Squash-merges emit events out of order when CI runs long: the PR-closed webhook lands before the merge event, so lifecycle inference marks deploy before work-end and the actuals go negative. Regular merges infer correctly.',
|
||
comments: [{
|
||
who: 'Ana K.',
|
||
when: 'Feb 8 \u00b7 14:12',
|
||
text: 'Repro: squash-merge only. Regular merges infer fine.'
|
||
}, {
|
||
who: 'Stephen',
|
||
when: 'Feb 9 \u00b7 09:30',
|
||
text: 'Confirmed \u2014 the event order flips whenever CI takes more than ~5 minutes.'
|
||
}],
|
||
lifecycle: [{
|
||
stage: 'Diagnosis',
|
||
event: 'issue opened',
|
||
when: 'Feb 2 \u00b7 09:14',
|
||
icon: 'circle-dot',
|
||
done: true
|
||
}, {
|
||
stage: 'Triage',
|
||
event: 'labeled est/2d \u00b7 milestoned Beta',
|
||
when: 'Feb 3 \u00b7 10:02',
|
||
icon: 'tag',
|
||
done: true
|
||
}, {
|
||
stage: 'Work start',
|
||
event: 'first commit ref a41f09',
|
||
when: 'Feb 6 \u00b7 11:47',
|
||
icon: 'git-commit-horizontal',
|
||
done: true
|
||
}, {
|
||
stage: 'Deploy',
|
||
event: 'PR merged',
|
||
when: 'pending',
|
||
icon: 'git-merge',
|
||
done: false
|
||
}, {
|
||
stage: 'Complete',
|
||
event: 'issue closed',
|
||
when: 'pending',
|
||
icon: 'circle-check',
|
||
done: false
|
||
}],
|
||
forecast: {
|
||
p80: 'done Feb 11\u201313',
|
||
note: 'from your est/2d history \u00b7 n=14'
|
||
},
|
||
blocks: [91, 92],
|
||
blockedBy: [],
|
||
note: 'It blocks #91 and #92. I\u2019d take it first \u2014 the critical path agrees with me.'
|
||
}
|
||
},
|
||
directives: {
|
||
pending: {
|
||
seq: 7,
|
||
who: 'Stephen',
|
||
when: 'today 09:12',
|
||
what: 'Pilots before calibration \u2014 push #78 to next week.',
|
||
diff: [{
|
||
tone: 'info',
|
||
change: '#78 Calibration store',
|
||
from: 'this week',
|
||
to: 'wk of Feb 23'
|
||
}, {
|
||
tone: 'warn',
|
||
change: 'Beta \u00b7 80% window',
|
||
from: 'Mar 3\u201312',
|
||
to: 'Mar 5\u201314'
|
||
}, {
|
||
tone: 'ok',
|
||
change: "Today's plan",
|
||
from: '#87',
|
||
to: '#87 \u00b7 unchanged'
|
||
}]
|
||
},
|
||
entries: [{
|
||
seq: 6,
|
||
who: 'Stephen',
|
||
when: 'Feb 8 \u00b7 16:40',
|
||
what: 'Ana takes nothing new until #84 lands.',
|
||
why: 'context thrash',
|
||
status: 'applied',
|
||
consequence: 'WIP capped \u00b7 v1.0 unmoved'
|
||
}, {
|
||
seq: 5,
|
||
who: 'Stephen',
|
||
when: 'Feb 6 \u00b7 09:03',
|
||
what: 'Ship Beta a week early.',
|
||
why: 'board meeting',
|
||
status: 'withdrawn',
|
||
consequence: '80% would need scope \u22129d \u2014 withdrawn after diff'
|
||
}, {
|
||
seq: 4,
|
||
who: 'Stephen',
|
||
when: 'Feb 3 \u00b7 11:21',
|
||
what: 'deadline/hard on Pilot-ready.',
|
||
why: 'contract date',
|
||
status: 'applied',
|
||
consequence: 'label applied \u00b7 runway flag raised'
|
||
}, {
|
||
seq: 3,
|
||
who: 'Stephen',
|
||
when: 'Jan 28 \u00b7 08:47',
|
||
what: 'Webhook work ahead of UI polish.',
|
||
why: '',
|
||
status: 'applied',
|
||
consequence: '#91 +2 ranks \u00b7 Beta unmoved'
|
||
}, {
|
||
seq: 2,
|
||
who: 'Stephen',
|
||
when: 'Jan 20 \u00b7 14:02',
|
||
what: 'Estimates in days, never hours.',
|
||
why: 'sanity',
|
||
status: 'applied',
|
||
consequence: 'label schema est/* confirmed'
|
||
}, {
|
||
seq: 1,
|
||
who: 'Stephen',
|
||
when: 'Jan 19 \u00b7 09:00',
|
||
what: 'CommiTea manages its own backlog.',
|
||
why: 'dogfood',
|
||
status: 'applied',
|
||
consequence: 'stephen/commitea under management'
|
||
}]
|
||
},
|
||
gantt: {
|
||
// day offsets from Feb 2; chart spans 42 days (Feb 2 – Mar 16)
|
||
days: 42,
|
||
weeks: [{
|
||
at: 0,
|
||
label: 'Feb 2'
|
||
}, {
|
||
at: 7,
|
||
label: 'Feb 9'
|
||
}, {
|
||
at: 14,
|
||
label: 'Feb 16'
|
||
}, {
|
||
at: 21,
|
||
label: 'Feb 23'
|
||
}, {
|
||
at: 28,
|
||
label: 'Mar 2'
|
||
}, {
|
||
at: 35,
|
||
label: 'Mar 9'
|
||
}, {
|
||
at: 41,
|
||
label: 'Mar 15'
|
||
}],
|
||
today: 8,
|
||
band: {
|
||
from: 29,
|
||
to: 38,
|
||
label: '80% · Mar 3–12'
|
||
},
|
||
due: {
|
||
at: 41,
|
||
label: 'Beta due'
|
||
},
|
||
rows: [{
|
||
id: 71,
|
||
title: 'Gitea client: token auth + retries',
|
||
who: 'SM',
|
||
state: 'done',
|
||
start: 0,
|
||
end: 4
|
||
}, {
|
||
id: 69,
|
||
title: 'pm-state repo bootstrap',
|
||
who: 'SM',
|
||
state: 'done',
|
||
start: 0,
|
||
end: 1
|
||
}, {
|
||
id: 87,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
who: 'SM',
|
||
state: 'steeping',
|
||
start: 4,
|
||
end: 9,
|
||
p80: 11,
|
||
crit: true
|
||
}, {
|
||
id: 92,
|
||
title: 'Monte Carlo engine: percentile bands',
|
||
who: 'SM',
|
||
state: 'review',
|
||
start: 9,
|
||
end: 18,
|
||
p80: 21,
|
||
crit: true
|
||
}, {
|
||
id: 91,
|
||
title: 'Webhook listener: reconcile on reconnect',
|
||
who: 'AK',
|
||
state: 'scheduled',
|
||
start: 9,
|
||
end: 14,
|
||
p80: 16
|
||
}, {
|
||
id: 99,
|
||
title: 'Directive log: conflict-free merge test',
|
||
who: 'SM',
|
||
state: 'scheduled',
|
||
start: 10,
|
||
end: 11
|
||
}, {
|
||
id: 96,
|
||
title: 'Label schema bootstrap for new repos',
|
||
who: 'AK',
|
||
state: 'scheduled',
|
||
start: 14,
|
||
end: 16
|
||
}, {
|
||
id: 84,
|
||
title: 'Capacity model: focus factor per person',
|
||
who: 'AK',
|
||
state: 'scheduled',
|
||
start: 18,
|
||
end: 23,
|
||
p80: 26,
|
||
crit: true
|
||
}, {
|
||
id: 102,
|
||
title: 'Scheduler ignores standing allocation slices',
|
||
who: 'SM',
|
||
state: 'scheduled',
|
||
start: 23,
|
||
end: 25,
|
||
p80: 28,
|
||
crit: true
|
||
}, {
|
||
id: 78,
|
||
title: 'Calibration store cold-start distributions',
|
||
who: 'SM',
|
||
state: 'scheduled',
|
||
start: 25,
|
||
end: 30
|
||
}]
|
||
},
|
||
deps: {
|
||
nodes: [{
|
||
id: 71,
|
||
title: 'Gitea client: token auth + retries',
|
||
tags: ['est/2d'],
|
||
state: 'done',
|
||
col: 0,
|
||
row: 0.2
|
||
}, {
|
||
id: 69,
|
||
title: 'pm-state repo bootstrap',
|
||
tags: ['est/1d'],
|
||
state: 'done',
|
||
col: 0,
|
||
row: 1.9
|
||
}, {
|
||
id: 87,
|
||
title: 'Fix lifecycle inference on merge events',
|
||
tags: ['est/2d', 'p/1'],
|
||
state: 'steeping',
|
||
days: '4d',
|
||
col: 1,
|
||
row: 0.7,
|
||
rationale: 'It blocks #91 and #92. I\u2019d take it first \u2014 the critical path agrees with me.'
|
||
}, {
|
||
id: 99,
|
||
title: 'Directive log: conflict-free merge test',
|
||
tags: ['est/1d', 'p/2'],
|
||
state: 'triage',
|
||
col: 1,
|
||
row: 1.9
|
||
}, {
|
||
id: 91,
|
||
title: 'Webhook listener: reconcile on reconnect',
|
||
tags: ['est/3d', 'p/2'],
|
||
state: 'triage',
|
||
col: 2,
|
||
row: 0
|
||
}, {
|
||
id: 92,
|
||
title: 'Monte Carlo engine: percentile bands',
|
||
tags: ['est/5d', 'p/1'],
|
||
state: 'review',
|
||
col: 2,
|
||
row: 1.4
|
||
}, {
|
||
id: 84,
|
||
title: 'Capacity model: focus factor per person',
|
||
tags: ['est/3d', 'p/2'],
|
||
state: 'steeping',
|
||
days: '1d',
|
||
col: 3,
|
||
row: 1.4
|
||
}, {
|
||
id: 102,
|
||
title: 'Scheduler ignores standing allocation slices',
|
||
tags: ['p/2'],
|
||
state: 'diagnosis',
|
||
col: 4,
|
||
row: 1.4
|
||
}],
|
||
milestone: {
|
||
name: 'Beta',
|
||
due: 'Mar 15',
|
||
col: 5,
|
||
row: 1.4
|
||
},
|
||
edges: [{
|
||
from: 71,
|
||
to: 87
|
||
}, {
|
||
from: 69,
|
||
to: 99
|
||
}, {
|
||
from: 87,
|
||
to: 91
|
||
}, {
|
||
from: 87,
|
||
to: 92,
|
||
crit: true
|
||
}, {
|
||
from: 92,
|
||
to: 84,
|
||
crit: true
|
||
}, {
|
||
from: 84,
|
||
to: 102,
|
||
crit: true
|
||
}, {
|
||
from: 102,
|
||
to: 'ms',
|
||
crit: true
|
||
}],
|
||
critical: [87, 92, 84, 102],
|
||
unattached: [78, 96, 103, 65]
|
||
}
|
||
};
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/app/data.js", error: String((e && e.message) || e) }); }
|
||
|
||
__ds_ns.Badge = __ds_scope.Badge;
|
||
|
||
__ds_ns.Button = __ds_scope.Button;
|
||
|
||
__ds_ns.Card = __ds_scope.Card;
|
||
|
||
__ds_ns.Icon = __ds_scope.Icon;
|
||
|
||
__ds_ns.ICON_NAMES = __ds_scope.ICON_NAMES;
|
||
|
||
__ds_ns.IconButton = __ds_scope.IconButton;
|
||
|
||
__ds_ns.Tabs = __ds_scope.Tabs;
|
||
|
||
__ds_ns.Tag = __ds_scope.Tag;
|
||
|
||
__ds_ns.Dialog = __ds_scope.Dialog;
|
||
|
||
__ds_ns.Toast = __ds_scope.Toast;
|
||
|
||
__ds_ns.Tooltip = __ds_scope.Tooltip;
|
||
|
||
__ds_ns.Checkbox = __ds_scope.Checkbox;
|
||
|
||
__ds_ns.Input = __ds_scope.Input;
|
||
|
||
__ds_ns.Radio = __ds_scope.Radio;
|
||
|
||
__ds_ns.Select = __ds_scope.Select;
|
||
|
||
__ds_ns.Switch = __ds_scope.Switch;
|
||
|
||
})();
|