diff --git a/apps/board/package.json b/apps/board/package.json
index 41e3dfdabc..c8c7a78508 100644
--- a/apps/board/package.json
+++ b/apps/board/package.json
@@ -27,6 +27,7 @@
"@mattstack/tui-kit": "workspace:*",
"@pierre/diffs": "catalog:",
"invadrs": "^1.3.1",
+ "motion": "14.2.0",
"pngjs": "^7.0.0",
"react": "catalog:",
"react-dom": "catalog:",
diff --git a/apps/board/src/client/board/ClickToEditField.stories.tsx b/apps/board/src/client/board/ClickToEditField.stories.tsx
new file mode 100644
index 0000000000..ace80a57ce
--- /dev/null
+++ b/apps/board/src/client/board/ClickToEditField.stories.tsx
@@ -0,0 +1,323 @@
+import { useState, type ReactNode } from 'react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { Chip, Markdown } from '@mattstack/tui-kit';
+import { registerTheme, SoribashiProvider } from '@mattstack/tui-kit/provider';
+import { tuiTheme } from '@mattstack/tui-kit/theme';
+
+import '@mattstack/tui-kit/theme.css';
+import '@mattstack/tui-kit/canvas.css';
+import '../../style.css';
+
+import { ClickToEditField } from './ClickToEditField.tsx';
+import { AgentGlyph, CodeGlyph, CommentGlyph, FileGlyph } from './icons.tsx';
+
+/**
+ * First build pass of the click-to-edit comment (board.pen B26 and B27):
+ * every comment reads rendered, a click on its text opens the raw Markdown
+ * with the caret at the click, and there is no Write/Preview toggle. The
+ * summary card stacks bare fields so it reads as the one comment the forge
+ * shows; a comment from a finding edits in the summary or in its own card,
+ * both on the same text. Invented content only (the repo is public).
+ */
+function Stage({
+ scheme,
+ children,
+}: {
+ scheme: 'light' | 'dark';
+ children: ReactNode;
+}) {
+ return (
+
+ );
+}
+
+const meta = {
+ title: 'Gates/Board/Click to edit',
+ decorators: [
+ (Story, context) => (
+
+
+
+ ),
+ ],
+ parameters: { layout: 'fullscreen' },
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+registerTheme(tuiTheme);
+
+interface StoryFinding {
+ id: string;
+ title: string;
+ body: string;
+ comment: string;
+ file?: { path: string; line: number };
+}
+
+const FINDINGS: StoryFinding[] = [
+ {
+ id: 'd1',
+ title: 'retryPolicy retries a job that already failed for good',
+ body: '`retryPolicy` retries every rejection, including `PermanentJobError`, so a job that can never succeed burns all five attempts.',
+ comment:
+ "**issue:** this retries `PermanentJobError` too, so a job that can't succeed eats all five attempts before it fails. could we skip retries for that one?",
+ file: { path: 'src/jobs/retry-policy.ts', line: 34 },
+ },
+ {
+ id: 'd2',
+ title: 'The delay never backs off',
+ body: 'The delay is fixed at `200ms`; the spec asks for exponential backoff capped at 5s.',
+ comment:
+ '**suggestion:** the spec wants exponential backoff capped at 5s, and this is a flat `200ms`. something like `Math.min(200 * 2 ** attempt, 5000)` would cover it.',
+ file: { path: 'src/jobs/retry-policy.ts', line: 41 },
+ },
+ {
+ id: 'f1',
+ title: 'No run for the --changed flag',
+ body: 'The AC for `--changed` on files under `src/jobs/**` has no run in the evidence.',
+ comment:
+ '**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?',
+ },
+ {
+ id: 'f2',
+ title: 'Stale comments and a stale stat name',
+ body: 'Comments in `scan-jobs.ts` still describe the old single folder, and `stats.reachableInJobs` now counts both.',
+ comment:
+ "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ },
+ {
+ id: 'f3',
+ title: 'README is out of step with the script',
+ body: 'The README still names the old folder, and nothing mentions the path change.',
+ comment:
+ '**suggestion:** the `README.md` still says the scanner reads `src/jobs` (:42). anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about both? see [the overlay docs](https://example.test/docs/overlay).',
+ },
+];
+
+function SummaryAndFindings() {
+ const [summary, setSummary] = useState(
+ 'Left a few comments, the `retryPolicy` one is the main one.'
+ );
+ const [texts, setTexts] = useState>(
+ Object.fromEntries(FINDINGS.map(f => [f.id, f.comment]))
+ );
+ const [ticked, setTicked] = useState(new Set(FINDINGS.map(f => f.id)));
+ const [editing, setEditing] = useState(null);
+ const setText = (id: string) => (t: string) =>
+ setTexts(prev => ({ ...prev, [id]: t }));
+ const track = (key: string) => (on: boolean) =>
+ setEditing(prev => (on ? key : prev === key ? null : prev));
+ const folded = FINDINGS.filter(f => !f.file && ticked.has(f.id));
+ return (
+ <>
+
+ Summary comment
+
+
+ for comment
+
+ posts on !1182
+
+
+
+
+
+
+ {folded.map(f => (
+
+ ))}
+
+ {editing?.startsWith('summary') && (
+ Markdown supported
+ )}
+
+
+
+
+ Findings
+
+ {ticked.size} of {FINDINGS.length} selected
+
+
+
+ {FINDINGS.map(f => {
+ const on = ticked.has(f.id);
+ return (
+
+
+
+ setTicked(prev => {
+ const next = new Set(prev);
+ if (e.currentTarget.checked) next.add(f.id);
+ else next.delete(f.id);
+ return next;
+ })
+ }
+ />
+ {f.title}
+
+ {on && (
+ <>
+ {f.file && (
+
+
+
+
+ The Code
+
+
+
+
+
+
+ {f.file.path}
+
+ :{f.file.line}
+
+
+
+
+
+ )}
+
+
+
+
+
+ Comment
+
+
+ {f.file
+ ? 'drafted by the agent'
+ : editing === `summary:${f.id}`
+ ? 'editing in summary'
+ : 'posts in summary'}
+
+
+
+
+ >
+ )}
+
+ );
+ })}
+
+ >
+ );
+}
+
+export const SummaryWithFindings: Story = {
+ name: 'Summary and finding cards',
+ render: () => ,
+};
+
+function OneField() {
+ const [text, setText] = useState(
+ [
+ '**question:** does the retry here back off, or hammer the queue?',
+ '',
+ '- `retryPolicy.max` is 5',
+ '- the delay looks fixed at 200ms',
+ '',
+ '```ts',
+ 'await retry(job, { max: 5, delayMs: 200 });',
+ '```',
+ '',
+ 'see [the retry notes](https://example.test/retry) for the old numbers.',
+ ].join('\n')
+ );
+ return ;
+}
+
+export const SingleField: Story = {
+ name: 'One boxed field (lists, code, a link)',
+ render: () => ,
+};
+
+function EmptyField() {
+ const [text, setText] = useState('');
+ return (
+
+ );
+}
+
+export const Empty: Story = {
+ name: 'An empty comment',
+ render: () => ,
+};
diff --git a/apps/board/src/client/board/ClickToEditField.tsx b/apps/board/src/client/board/ClickToEditField.tsx
new file mode 100644
index 0000000000..6680655e47
--- /dev/null
+++ b/apps/board/src/client/board/ClickToEditField.tsx
@@ -0,0 +1,351 @@
+import {
+ useEffect,
+ useLayoutEffect,
+ useRef,
+ useState,
+ type KeyboardEvent,
+ type MouseEvent,
+ type ReactNode,
+} from 'react';
+import {
+ AnimatePresence,
+ domAnimation,
+ LazyMotion,
+ m,
+ MotionConfig,
+} from 'motion/react';
+
+import { sourceOffset } from './caret-map.ts';
+import { CommentMarkdown } from './CommentMarkdown.tsx';
+import { CheckGlyph, PencilLineIcon } from './icons.tsx';
+
+const FLASH_MS = 1600;
+const FADE_MS = 150;
+
+type CaretDocument = Document & {
+ caretPositionFromPoint?: (
+ x: number,
+ y: number
+ ) => { offsetNode: Node; offset: number } | null;
+ caretRangeFromPoint?: (x: number, y: number) => Range | null;
+};
+
+function caretAtPoint(x: number, y: number) {
+ const doc = document as CaretDocument;
+ if (doc.caretPositionFromPoint) {
+ const p = doc.caretPositionFromPoint(x, y);
+ return p && { node: p.offsetNode, offset: p.offset };
+ }
+ const r = doc.caretRangeFromPoint?.(x, y);
+ return r ? { node: r.startContainer, offset: r.startOffset } : null;
+}
+
+/** The click's offset in the rendered text of `root`, or its end when the
+ click missed the text. */
+function renderedOffset(root: HTMLElement, x: number, y: number): number {
+ const all = root.textContent ?? '';
+ const hit = caretAtPoint(x, y);
+ if (!hit || hit.node.nodeType !== Node.TEXT_NODE || !root.contains(hit.node))
+ return all.length;
+ const walk = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
+ let total = 0;
+ for (let n = walk.nextNode(); n; n = walk.nextNode()) {
+ if (n === hit.node) return total + hit.offset;
+ total += n.textContent?.length ?? 0;
+ }
+ return all.length;
+}
+
+const SWAP = { duration: 0.15, ease: [0.4, 0, 0.2, 1] as const };
+const STILL = { duration: 0 };
+
+/** Each face fades over the other; the leaving one is popped out of flow
+ and stops taking clicks, so the box sizes to the face arriving. */
+const FADE = {
+ initial: { opacity: 0 },
+ animate: { opacity: 1 },
+ exit: { opacity: 0, pointerEvents: 'none' as const },
+ transition: SWAP,
+};
+
+function grow(el: HTMLTextAreaElement) {
+ el.style.height = 'auto';
+ el.style.height = `${el.scrollHeight + el.offsetHeight - el.clientHeight}px`;
+}
+
+/** A comment that reads rendered and edits raw. A click on the text opens
+ the Markdown with the caret where you clicked; Tab onto it opens it with
+ the caret at the end. Leaving the field renders it again; Escape does
+ too and keeps focus on it, so a second Escape reaches the sheet. A click
+ on a link follows the link, and a drag that selects text stays put. */
+export function ClickToEditField({
+ label,
+ text,
+ variant = 'boxed',
+ stripe,
+ hint = true,
+ readOnly = false,
+ invalid = false,
+ describedBy,
+ onChange,
+ onEditing,
+ heading,
+ actions,
+ badge,
+}: {
+ label: string;
+ text: string;
+ variant?: 'boxed' | 'bare' | 'filled' | 'plain';
+ stripe?: 'always' | 'focus';
+ hint?: boolean;
+ readOnly?: boolean;
+ invalid?: boolean;
+ describedBy?: string;
+ onChange: (text: string) => void;
+ onEditing?: (editing: boolean) => void;
+ /** Names the mode while writing, e.g. "Editing comment". */
+ heading?: string;
+ /** Controls on the header's right while writing, such as a reset. */
+ actions?: ReactNode;
+ /** At rest, a pill on the field's top-left border, such as "Edited". */
+ badge?: ReactNode;
+}) {
+ const [editing, setEditing] = useState(false);
+ const area = useRef(null);
+ const view = useRef(null);
+ const caret = useRef(null);
+ const pressed = useRef(false);
+ const refocus = useRef(false);
+ const faces = useRef(null);
+ const [height, setHeight] = useState('auto');
+ // The box eases across a swap and at rest (a reset changing the text);
+ // a line typed in Write grows it at once, so the caret's line is never
+ // clipped mid-ease.
+ const [swapping, setSwapping] = useState(false);
+ // Closing on a changed text flashes "Comment updated" in the pill, then
+ // fades it; the label holds through the fade so it never swaps mid-ease.
+ const openedWith = useRef(text);
+ const [flash, setFlash] = useState<'shown' | 'fading' | null>(null);
+ useEffect(() => {
+ if (flash === null) return;
+ const id = window.setTimeout(
+ () => setFlash(flash === 'shown' ? 'fading' : null),
+ flash === 'shown' ? FLASH_MS : FADE_MS
+ );
+ return () => window.clearTimeout(id);
+ }, [flash]);
+
+ useLayoutEffect(() => {
+ const el = faces.current;
+ if (!el || typeof ResizeObserver === 'undefined') return;
+ setHeight(el.offsetHeight);
+ const observer = new ResizeObserver(() => setHeight(el.offsetHeight));
+ observer.observe(el);
+ return () => observer.disconnect();
+ }, []);
+
+ const open = (at: number) => {
+ openedWith.current = text;
+ setFlash(null);
+ caret.current = at;
+ setSwapping(true);
+ setEditing(true);
+ onEditing?.(true);
+ };
+ const close = (keepFocus: boolean) => {
+ refocus.current = keepFocus;
+ if (text !== openedWith.current) setFlash('shown');
+ setSwapping(true);
+ setEditing(false);
+ onEditing?.(false);
+ };
+
+ useLayoutEffect(() => {
+ if (editing) {
+ const el = area.current;
+ if (!el) return;
+ grow(el);
+ if (caret.current !== null) {
+ el.focus({ preventScroll: true });
+ el.setSelectionRange(caret.current, caret.current);
+ caret.current = null;
+ }
+ } else if (refocus.current) {
+ view.current?.focus({ preventScroll: true });
+ }
+ }, [editing, text]);
+
+ const onViewClick = (e: MouseEvent) => {
+ pressed.current = false;
+ if (readOnly) return;
+ if ((e.target as HTMLElement).closest('a')) return;
+ const picked = window.getSelection();
+ if (
+ picked &&
+ !picked.isCollapsed &&
+ e.currentTarget.contains(picked.anchorNode)
+ )
+ return;
+ const at = renderedOffset(e.currentTarget, e.clientX, e.clientY);
+ open(sourceOffset(text, e.currentTarget.textContent ?? '', at));
+ };
+
+ const onViewFocus = () => {
+ if (refocus.current) {
+ refocus.current = false;
+ return;
+ }
+ if (pressed.current || readOnly) return;
+ open(text.length);
+ };
+
+ const onAreaKeyDown = (e: KeyboardEvent) => {
+ const el = e.currentTarget;
+ if (e.key === 'Escape') {
+ e.preventDefault();
+ e.stopPropagation();
+ close(true);
+ return;
+ }
+ if (e.key !== 'Tab' || e.shiftKey || e.altKey || e.ctrlKey || e.metaKey)
+ return;
+ e.preventDefault();
+ e.stopPropagation();
+ if (document.execCommand?.('insertText', false, ' ')) return;
+ const { selectionStart: start, selectionEnd: end, value } = el;
+ caret.current = start + 2;
+ onChange(`${value.slice(0, start)} ${value.slice(end)}`);
+ };
+
+ const showHeading = editing && !!heading;
+ return (
+
+
+
+
+ {editing && (showHeading || actions) && (
+
+
+
+ {showHeading && (
+ <>
+
+ {heading}
+ >
+ )}
+
+ {actions}
+
+
+ )}
+
+
+ {!editing && badge && (
+
{badge}
+ )}
+
setSwapping(false)}
+ >
+
+
+ {editing ? (
+
+
+ ) : (
+
+ {
+ pressed.current = true;
+ }}
+ onFocus={onViewFocus}
+ onClick={onViewClick}
+ >
+ {text.trim() === '' ? (
+
+ Empty comment
+
+ ) : (
+
{text}
+ )}
+
+
+ )}
+
+
+
+ {hint && (editing || variant === 'plain') && (
+ // At rest, plain's hint is the hover "Click to edit" pill; the
+ // textbox already says it edits, so the pill stays out of the
+ // accessibility tree.
+
+ {editing ? (
+ <>
+ Markdown supported
+ esc to finish
+ >
+ ) : flash ? (
+ <>
+
+ Comment updated
+ >
+ ) : (
+ <>
+
+ Click to edit
+ >
+ )}
+
+ )}
+
+
+
+
+ );
+}
diff --git a/apps/board/src/client/board/CommentMarkdown.tsx b/apps/board/src/client/board/CommentMarkdown.tsx
index ec5d93dcbd..6c3a2d2122 100644
--- a/apps/board/src/client/board/CommentMarkdown.tsx
+++ b/apps/board/src/client/board/CommentMarkdown.tsx
@@ -51,6 +51,52 @@ class HighlightBoundary extends Component<
}
}
+/** A fence's info string as people name the language; an unknown one shows
+ as written. */
+const LANG_NAMES: Record = {
+ ts: 'TypeScript',
+ typescript: 'TypeScript',
+ tsx: 'TSX',
+ js: 'JavaScript',
+ javascript: 'JavaScript',
+ jsx: 'JSX',
+ json: 'JSON',
+ sh: 'Shell',
+ bash: 'Shell',
+ shell: 'Shell',
+ zsh: 'Shell',
+ py: 'Python',
+ python: 'Python',
+ rb: 'Ruby',
+ ruby: 'Ruby',
+ go: 'Go',
+ rs: 'Rust',
+ rust: 'Rust',
+ sql: 'SQL',
+ yml: 'YAML',
+ yaml: 'YAML',
+ md: 'Markdown',
+ markdown: 'Markdown',
+ css: 'CSS',
+ scss: 'SCSS',
+ html: 'HTML',
+ graphql: 'GraphQL',
+ gql: 'GraphQL',
+ diff: 'Diff',
+ swift: 'Swift',
+ kt: 'Kotlin',
+ kotlin: 'Kotlin',
+ java: 'Java',
+};
+
+function langName(lang: string | undefined): string {
+ if (!lang) return 'code';
+ // Own keys only: a fence tagged `__proto__` or `constructor` comes from
+ // MR content and must not reach Object.prototype.
+ const key = lang.toLowerCase();
+ return Object.hasOwn(LANG_NAMES, key) ? LANG_NAMES[key]! : lang;
+}
+
/** A fenced code block: a labelled block, highlighted once the sheet's
source brings the highlighter and the language is one it knows, and a
plain block otherwise. A `suggestion` fence is the forge's suggested
@@ -66,7 +112,7 @@ function CodeFence({ lang, code }: { lang?: string; code: string }) {
data-lang={suggestion ? undefined : lang}
>
- {suggestion ? 'Suggested change' : (lang ?? 'code')}
+ {suggestion ? 'Suggested change' : langName(lang)}
{Highlighted && lang && !suggestion ? (
diff --git a/apps/board/src/client/board/DiffView.tsx b/apps/board/src/client/board/DiffView.tsx
index c62b5d65ba..cfd4ab91c8 100644
--- a/apps/board/src/client/board/DiffView.tsx
+++ b/apps/board/src/client/board/DiffView.tsx
@@ -259,6 +259,18 @@ export function fenceLanguage(lang: string): string | undefined {
const CODE_CSS = `${BOARD_CSS}
:host {
--diffs-font-size: 13px;
+ --diffs-light-bg: transparent;
+ --diffs-dark-bg: transparent;
+ --diffs-bg: transparent;
+ background-color: transparent;
+}
+[data-code] {
+ padding: 0;
+ scrollbar-gutter: auto;
+ overflow: visible;
+}
+[data-line] {
+ padding-inline: 0;
}
`;
diff --git a/apps/board/src/client/board/MrCard.tsx b/apps/board/src/client/board/MrCard.tsx
index d8e908e8a2..b5b653526d 100644
--- a/apps/board/src/client/board/MrCard.tsx
+++ b/apps/board/src/client/board/MrCard.tsx
@@ -27,12 +27,12 @@ export function MrCard({ mr }: { mr: BoardMRWithReview }) {
-{mr.diff.deletions}
)}
+ {mr.sourceBranch && (
+
+ · {mr.sourceBranch}
+
+ )}
- {mr.sourceBranch && (
-
- {mr.sourceBranch}
-
- )}
);
}
diff --git a/apps/board/src/client/board/RespondSheet.tsx b/apps/board/src/client/board/RespondSheet.tsx
index ff0b577c05..a76bdceec5 100644
--- a/apps/board/src/client/board/RespondSheet.tsx
+++ b/apps/board/src/client/board/RespondSheet.tsx
@@ -44,7 +44,6 @@ import {
} from './respond-post.ts';
import {
PostResolveChoice,
- PostTick,
ReplyBlock,
ReplyChoiceBody,
SeverityPill,
@@ -956,25 +955,6 @@ function RespondSheetBody({
);
})}
- {latches.length > 0 && (
-
- Re-review
- {latches.map(l => (
- toggleReReview(l.discussionId, on)}
- >
- Ask {people.short(l.reviewer)} for a re-review once posting
- finishes
-
- ))}
-
- )}
{form.lost ? (
@@ -1048,6 +1028,55 @@ function RespondSheetBody({
{nextStep && (
{nextStep}
)}
+ {latches.length > 0 && (
+ p.resolve) || undefined
+ }
+ role="group"
+ aria-label="Re-review"
+ >
+ {latches.map(l => {
+ const on = reReviewIds.has(l.discussionId);
+ return (
+
+
+
+ re-review
+
+
+
+ ask {people.short(l.reviewer)} after posting
+
+
+
+ toggleReReview(
+ l.discussionId,
+ e.currentTarget.checked
+ )
+ }
+ />
+
+
+
+ );
+ })}
+
+ )}
>
)}
{!revising &&
diff --git a/apps/board/src/client/board/ReviewDraftCard.tsx b/apps/board/src/client/board/ReviewDraftCard.tsx
index b6bddfc75b..2ba1bb8e3a 100644
--- a/apps/board/src/client/board/ReviewDraftCard.tsx
+++ b/apps/board/src/client/board/ReviewDraftCard.tsx
@@ -10,15 +10,12 @@ import {
type ReactNode,
type RefObject,
} from 'react';
+import { AnimatePresence, domAnimation, LazyMotion, m } from 'motion/react';
-import { Chip, Markdown, Modal } from '@mattstack/tui-kit';
-import {
- CommentField,
- commentState,
- FieldTabs,
- resetToWrite,
- type FieldMode,
-} from './CommentComposer.tsx';
+import { Modal, Popover } from '@mattstack/tui-kit';
+import { ClickToEditField } from './ClickToEditField.tsx';
+import { commentState, resetToWrite } from './CommentComposer.tsx';
+import { CommentMarkdown } from './CommentMarkdown.tsx';
import {
anchorLine,
anchorPath,
@@ -35,10 +32,10 @@ import type { GateFormState } from './GateForm.tsx';
import {
AgentGlyph,
ArrowOutGlyph,
- CodeGlyph,
- CommentGlyph,
+ ChevronGlyph,
FileGlyph,
- RemoveGlyph,
+ InfoGlyph,
+ UndoGlyph,
} from './icons.tsx';
import { commentKey, hasDiffLine, summaryKey } from './review-drafts.ts';
@@ -67,28 +64,6 @@ export interface FilePin {
line: number;
}
-function SectionHead({
- icon,
- name,
- hue,
- children,
-}: {
- icon: ReactNode;
- name: string;
- hue: 'muted' | 'accent' | 'ok';
- children?: ReactNode;
-}) {
- return (
-
-
- {icon}
- {name}
-
- {children}
-
- );
-}
-
/** How long the full diff keeps re-centring the finding you came from
while the renderer, its highlighting and the pins lay out. */
const REVEAL_SETTLE_MS = 2000;
@@ -342,6 +317,8 @@ function CodeSection({
[diff, line]
);
const [open, setOpen] = useState(false);
+ const leavingField = useRef(false);
+ const [folded, setFolded] = useState(false);
const link = useRef(null);
return (
- } name="The Code" hue="muted">
- {forgeLink && (
-
- open on {forgeLink.forge}
-
-
- )}
- {openable && (
- setOpen(true)}
- >
- view full diff
-
-
- )}
-
{
- const picked = window.getSelection();
- if (
- picked &&
- !picked.isCollapsed &&
- e.currentTarget.contains(picked.anchorNode)
- )
- return;
- setOpen(true);
- }
- : undefined
- }
+ data-folded={folded || undefined}
>
+
setFolded(v => !v)}
+ >
+
+
{path}
@@ -400,31 +348,96 @@ function CodeSection({
:{line}
)}
+ {finding.body &&
}
+ {forgeLink && (
+
+ open on {forgeLink.forge}
+
+
+ )}
{openable && (
-
- click to expand
-
+
setOpen(true)}
+ >
+ full diff
+
+
)}
- {heldBack && (fetchedDiff.tooLarge || fetchedDiff.binary) && (
-
- {fetchedDiff.binary
- ? 'A binary file, with no diff to show here.'
- : 'Too large to show here.'}
-
- )}
- {error !== null && (
-
- {error}
-
- )}
- {snippet && DiffView && (
-
-
-
-
-
- )}
+
+
+ {!folded && (
+
+ {heldBack && (fetchedDiff.tooLarge || fetchedDiff.binary) && (
+
+ {fetchedDiff.binary
+ ? 'A binary file, with no diff to show here.'
+ : 'Too large to show here.'}
+
+ )}
+ {error !== null && (
+
+ {error}
+
+ )}
+ {snippet && DiffView && (
+ {
+ // A press that only closes a comment being written must
+ // not also open the full diff.
+ leavingField.current = !!document.activeElement?.closest(
+ '.tui-cte[data-editing]'
+ );
+ }}
+ onClick={e => {
+ if (leavingField.current) return;
+ const picked = window.getSelection();
+ if (
+ picked &&
+ !picked.isCollapsed &&
+ e.currentTarget.contains(picked.anchorNode)
+ )
+ return;
+ setOpen(true);
+ }}
+ >
+
+
+
+
+
+
+ )}
+
+ )}
+
+
{open && diff && DiffView && (
- edited
- ·
e.preventDefault()}
onClick={e =>
resetToWrite(e.currentTarget, '[data-draft-part]', onReset)
}
>
+
{resetText}
);
}
-/** A comment field with its blank-edit hint, in a part that `DraftMeta`'s
- reset finds by `data-draft-part`. */
-function DraftField({
+/** A comment that reads rendered and opens raw on a click, with its
+ blank-edit hint, in a part that `DraftMeta`'s reset finds by
+ `data-draft-part`. */
+function CommentEditor({
label,
draft,
value,
- mode,
+ variant,
+ hint = true,
onChange,
+ onEditing,
+ heading,
+ actions,
+ badge,
}: {
label: string;
draft: string;
value: string | undefined;
- mode: FieldMode;
+ variant: 'bare' | 'filled' | 'plain';
+ hint?: boolean;
onChange: (text: string) => void;
+ onEditing?: (editing: boolean) => void;
+ heading?: string;
+ actions?: ReactNode;
+ badge?: ReactNode;
}) {
const { text, empty } = commentState(draft, value, true);
- const hint = useId();
+ const hintId = useId();
return (
<>
-
{empty && (
-
+
the comment is empty
)}
@@ -513,39 +545,55 @@ function DraftField({
);
}
-/** A comment's framed field over its "Markdown supported" footer with the
- Write and Preview tabs: the one editor every review comment uses. */
-function CommentEditor({
- label,
- draft,
- value,
- mode,
- onMode,
- onChange,
-}: {
- label: string;
- draft: string;
- value: string | undefined;
- mode: FieldMode;
- onMode: (mode: FieldMode) => void;
- onChange: (text: string) => void;
-}) {
+/** The agent's finding behind an info mark in the code's file bar: the
+ comment already says it to the author, so it stays a click away. */
+function FindingInfo({ body }: { body: string }) {
+ const [open, setOpen] = useState(false);
return (
- <>
-
-
+
+
+
+ }
+ >
+
+ Agent finding
+ {body}
-
-
Markdown supported
-
+
+ );
+}
+
+/** With no diff line to show, the slot the code takes holds the agent's
+ finding instead, under its file when it names one. */
+function FindingSection({ finding: f }: { finding: FindingEntry }) {
+ return (
+
+ {f.file && (
+
+
+ {f.file}
+
+ )}
+
+ {f.body}
- >
+
);
}
@@ -558,44 +606,46 @@ function CommentSection({
}) {
const key = commentKey(finding.id);
const label = `Comment on ${finding.title}`;
- const [mode, setMode] = useState
('write');
const { edited } = commentState(finding.comment!, form.texts[key], true);
- const anchored = hasDiffLine(finding);
return (
- } name="Comment" hue="ok">
- {anchored && (
- {
- form.clearText(key);
- setMode('write');
- }}
- />
- )}
-
- {anchored ? (
- form.setText(key, t)}
- />
- ) : (
-
- Posts in the summary (no diff line)
-
- )}
+ form.clearText(key)}
+ />
+ )
+ }
+ badge={
+ edited && (
+ <>
+ Edited
+
+ form.clearText(key)}
+ />
+ >
+ )
+ }
+ onChange={t => form.setText(key, t)}
+ />
);
}
@@ -628,174 +678,90 @@ export function FindingCard({
data-off={checked ? undefined : ''}
>
{head}
- {checked && (
- <>
- {f.file && (
-
+
+
+ {checked && (
+
+ {hasDiffLine(f) ? (
+
+ ) : (
+
+ )}
+
+
)}
-
- }
- name="Agent Finding"
- hue="accent"
- />
-
-
- {f.body}
-
-
-
-
- >
- )}
+
+
);
}
-/** A finding with no diff line, as a section of the summary it posts in,
- with its own editor and a control to drop it from the summary. */
-function FoldedSection({
- finding: f,
+/** The review's summary line, drafted for the picked verdict, in the dock
+ beside the choice that swaps it. Two lines at rest; a click opens it
+ whole. A finding with no diff line edits in its own card; the poster
+ joins it in after this line. */
+export function SummaryCard({
+ outcome,
+ draft,
form,
- onRemove,
+ postsOn,
}: {
- finding: FindingEntry;
+ outcome: string;
+ draft: string;
form: GateFormState;
- onRemove: () => void;
+ postsOn?: string;
}) {
- const key = commentKey(f.id);
- const label = `Summary comment: ${f.title}`;
- const [mode, setMode] = useState('write');
- const { edited } = commentState(f.comment!, form.texts[key], true);
+ const key = summaryKey(outcome);
+ const { edited } = commentState(draft, form.texts[key], true);
return (
- } name={f.title} hue="muted">
-
+
+ Review comment
+ {edited ? (
{
- form.clearText(key);
- setMode('write');
- }}
+ edited
+ label="Summary line"
+ onReset={() => form.clearText(key)}
/>
-
-
- Remove
-
-
-
+ ) : (
+ postsOn && (
+ posts on {postsOn}
+ )
+ )}
+
form.setText(key, t)}
/>
);
}
-
-/** The summary's verdict badge: approving reads as done, a comment as the
- board's accent, a change request as a warning. */
-const VERDICT_INTENT: Record = {
- approve: 'ok',
- comment: 'accent',
- request_changes: 'warn',
-};
-
-/** The review's summary comment as it will post (`joinSummary`), as one
- card in the finding cards' frame: the summary line drafted for the
- picked verdict, then each ticked finding with no diff line as its own
- section. */
-export function SummaryCard({
- outcome,
- verdictLabel,
- draft,
- folded,
- form,
- onRemove,
-}: {
- outcome: string;
- verdictLabel: string;
- draft: string;
- folded: FindingEntry[];
- form: GateFormState;
- onRemove: (f: FindingEntry) => void;
-}) {
- const key = summaryKey(outcome);
- const [mode, setMode] = useState('write');
- const { edited } = commentState(draft, form.texts[key], true);
- return (
-
-
- } name="Summary" hue="ok">
-
- {
- form.clearText(key);
- setMode('write');
- }}
- />
-
- for {verdictLabel}
-
-
-
- form.setText(key, t)}
- />
-
- {folded.map(f => (
- onRemove(f)}
- />
- ))}
-
- );
-}
diff --git a/apps/board/src/client/board/ReviewGateSheet.stories.tsx b/apps/board/src/client/board/ReviewGateSheet.stories.tsx
index 96eb04cd2b..fba0b3cd93 100644
--- a/apps/board/src/client/board/ReviewGateSheet.stories.tsx
+++ b/apps/board/src/client/board/ReviewGateSheet.stories.tsx
@@ -11,6 +11,7 @@ import '../../style.css';
import type { GateQuestion, GateRow } from '../../gates/store.ts';
import type { BoardMRWithReview } from '../types.ts';
+import { DiffSourceContext, type DiffSource } from './diff-source.ts';
import { useGateForm } from './GateForm.tsx';
import { ReviewGateSheet } from './ReviewGateSheet.tsx';
@@ -838,3 +839,168 @@ export const DraftedReReview: Story = {
decorators: [no404],
render: () => ,
};
+
+// --- DraftedFirstRound ---------------------------------------------------
+
+const draftedFirstRoundFindings = question(
+ 'findings-1',
+ 'Post which findings to !31?',
+ true,
+ [
+ {
+ value: 'f1',
+ label: '[Critical] SQL built from unsanitized input',
+ description: 'lib/db/query.ts:42 · parameterize the query',
+ },
+ {
+ value: 'f5',
+ label: '[Important] Retry loop lacks backoff',
+ description: 'lib/retry.ts:41 · add exponential backoff',
+ },
+ {
+ value: 'n-readme',
+ label: '[Minor] README still names the old folder',
+ description: 'README.md · mention the new path',
+ },
+ {
+ value: 'n-evidence',
+ label: '[Minor] No run for the --changed flag',
+ description: 'evidence · one quick run',
+ },
+ ],
+ findingsCtx(
+ {
+ ...F.f1,
+ comment:
+ '**issue:** the search handler drops the raw `q` straight into the `WHERE` clause, so a crafted query string reaches the database as SQL. could this use a bound parameter?\n\n```ts\ndb.query("SELECT * FROM items WHERE name = $1", [q]);\n```',
+ },
+ {
+ ...F.f5,
+ comment:
+ '**suggestion:** the loop retries immediately up to five times, so one upstream blip turns into six requests. something like `Math.min(200 * 2 ** attempt, 5000)` would back it off.',
+ },
+ {
+ id: 'n-readme',
+ severity: 'minor',
+ title: 'README still names the old folder',
+ file: 'README.md',
+ fix: 'mention the new path',
+ body: 'The README still says the scanner reads `lib/jobs`, and nothing mentions the move to `lib/tasks`.',
+ comment:
+ '**suggestion:** the `README.md` still says the scanner reads `lib/jobs`. anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about the move?',
+ },
+ {
+ id: 'n-evidence',
+ severity: 'minor',
+ title: 'No run for the --changed flag',
+ fix: 'one quick run',
+ body: 'Every AC has a run in the evidence except `--changed` picking up a file under `lib/tasks/**`.',
+ comment:
+ '**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `lib/tasks/**`... would you mind grabbing one quick run of that?',
+ }
+ )
+);
+
+const draftedFirstRoundGate: GateRow = {
+ ...sixFindingGate,
+ gateId: 'sheet-drafted-first-round',
+ context: ctx({
+ ...(JSON.parse(sixFindingGate.context!) as Record),
+ findings: { critical: 1, important: 1, minor: 2 },
+ editable: true,
+ summaryComments: {
+ approve:
+ 'Left a few comments, the injection one is the main one. Approving once that lands.',
+ comment: 'Left a few comments, the injection one is the main one.',
+ },
+ }),
+ questions: [
+ draftedFirstRoundFindings,
+ question('outcome', 'Verdict on !31', false, [
+ {
+ value: 'comment',
+ label: 'comment (recommended)',
+ description: 'Post the selected findings without a verdict.',
+ },
+ {
+ value: 'approve',
+ label: 'approve',
+ description: 'Approve !31 and post the selected findings.',
+ },
+ ]),
+ ],
+};
+
+const FIRST_ROUND_PATCHES: Record = {
+ 'lib/db/query.ts': `@@ -35,12 +35,14 @@ export async function searchItems(
+ ) {
+ const db = await pool.connect();
+ const q = req.query.q ?? '';
+ const limit = Number(req.query.limit ?? 20);
+
+- const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);
++ const rows = await db.query(
++ \`SELECT * FROM items
++ WHERE name LIKE '%\${q}%'
++ LIMIT \${limit}\`
++ );
+ return rows.map(toItem);
+ }
+
+ export async function itemById(id: string) {`,
+ 'lib/retry.ts': `@@ -34,12 +34,14 @@ export async function withRetry(
+ job: () => Promise,
+ attempts = 5
+ ): Promise {
+- return job();
++ for (let attempt = 0; ; attempt++) {
++ try {
++ return await job();
++ } catch (err) {
++ if (attempt >= attempts) throw err;
++ log.warn('retrying', { attempt });
++ }
++ }
+ }
+
+ export function isRetryable(err: unknown) {`,
+};
+
+/** Invented patches for the two files the drafted findings sit on. */
+const firstRoundDiffs: DiffSource = {
+ fetchFileDiff: async ({ file }) =>
+ FIRST_ROUND_PATCHES[file]
+ ? {
+ path: file,
+ patch: FIRST_ROUND_PATCHES[file]!,
+ forge: 'gitlab',
+ webUrl: `${boardMr.webUrl}/diffs`,
+ }
+ : null,
+ loadView: () => import('./DiffView.tsx'),
+};
+
+/** A drafted first round with click-to-edit comments: two findings on a
+ diff line, two that fold into the summary comment. Every comment reads
+ rendered and opens raw on a click; a folded one edits in the summary or
+ in its own card. */
+export const DraftedFirstRound: Story = {
+ // A real gate's report.json carries the record cluster; without it the
+ // column falls back to the Full report disclosure, which real gates
+ // rarely show.
+ decorators: [
+ fetchStub(url =>
+ url.startsWith('/review/report.json')
+ ? new Response(reportJson, {
+ status: 200,
+ headers: { 'content-type': 'application/json' },
+ })
+ : undefined
+ ),
+ ],
+ render: () => (
+
+
+
+ ),
+};
diff --git a/apps/board/src/client/board/ReviewGateSheet.tsx b/apps/board/src/client/board/ReviewGateSheet.tsx
index a4e67b5e59..a2fe453c96 100644
--- a/apps/board/src/client/board/ReviewGateSheet.tsx
+++ b/apps/board/src/client/board/ReviewGateSheet.tsx
@@ -242,6 +242,49 @@ function readDrafts(
return { findings: map, summaries };
}
+/** The report's checks in the rail: a tally beside the title, then every
+ check. */
+function ChecksCard({
+ checks,
+}: {
+ checks: Array<{ tag: string; text: string }>;
+}) {
+ const count = (tag: string) => checks.filter(c => c.tag === tag).length;
+ const tally = [
+ [count('PASS'), 'pass'],
+ [count('FAIL'), 'fail'],
+ [checks.length - count('PASS') - count('FAIL'), 'n/a'],
+ ]
+ .filter(([n]) => (n as number) > 0)
+ .map(([n, label]) => `${n} ${label}`)
+ .join(', ');
+ return (
+
+
+ checks
+ {tally}
+
+
+ {checks.map((c, i) => (
+
+
+ {c.tag}
+
+ {c.text}
+
+ ))}
+
+
+ );
+}
+
/** The full-screen sheet a `review-post` gate opens (design doc §4). Header
carries queue chrome; the main column is the findings and the optional
record cluster; the rail is the MR card, decision context and checks,
@@ -287,6 +330,7 @@ function ReviewGateSheet({
const findingsName = findingsQuestion?.id;
const skippedName = skippedQuestion?.id;
const outcomeName = outcomeQuestion?.id;
+ const [mainTab, setMainTab] = useState<'findings' | 'report'>('findings');
const skippedEntries = useMemo(
() =>
(skippedQuestion?.options ?? []).flatMap(o => {
@@ -347,11 +391,6 @@ function ReviewGateSheet({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [gate.gateId]);
- const handleReset = () => {
- form.resetAll();
- seedDefaults(true);
- };
-
const selectedFindings = useMemo(() => {
const current = findingsName ? form.selections[findingsName] : undefined;
return new Set(Array.isArray(current) ? current : []);
@@ -375,9 +414,6 @@ function ReviewGateSheet({
const edits = drafts
? draftEdits(drafts, selectedFindings, form.texts, verdict)
: { texts: {} };
- const folded = drafts
- ? findings.filter(f => selectedFindings.has(f.id) && !hasDiffLine(f))
- : [];
const pinsByFile = useMemo(() => {
const out = new Map();
for (const f of findings) {
@@ -391,17 +427,6 @@ function ReviewGateSheet({
}
return out;
}, [findings]);
- const removeFolded = (f: FindingEntry) => {
- if (!findingsName) return;
- form.toggleMulti(findingsName, f.id, false);
- // The part's button unmounts with it, which would drop focus outside
- // the sheet's Tab trap.
- document
- .querySelector(
- `input[aria-labelledby="tui-review-finding-title-${CSS.escape(f.id)}"]`
- )
- ?.focus();
- };
const outcomeText =
outcomeQuestion && typeof selectedOutcome === 'string'
? displayForValue(selectedOutcome, outcomeQuestion.options).text
@@ -429,46 +454,6 @@ function ReviewGateSheet({
const notes = useMemo(() => safeNotes(report), [report]);
const depth = safeDepth(report);
- const mainRef = useRef(null);
- const [atEnd, setAtEnd] = useState(true);
- const [moreBelow, setMoreBelow] = useState(0);
- useEffect(() => {
- const el = mainRef.current;
- if (!el) return;
- // Rect-to-rect, not offsetTop-to-scrollTop: offsetTop is relative to the
- // nearest positioned ancestor, which is not necessarily this scroll
- // container, so mixing it with scrollTop/clientHeight silently drifts
- // once any row's offsetParent differs from `el`.
- const measure = () => {
- const box = el.getBoundingClientRect();
- const remaining = el.scrollHeight - el.scrollTop - el.clientHeight;
- setAtEnd(remaining <= 1);
- const rows = el.querySelectorAll(
- '.tui-review-find-list .tui-review-finding-row'
- );
- let below = 0;
- rows.forEach(row => {
- if (row.getBoundingClientRect().top >= box.bottom) below++;
- });
- setMoreBelow(below);
- };
- measure();
- el.addEventListener('scroll', measure);
- window.addEventListener('resize', measure);
- // Cards grow after mount (the code view loads lazily), moving rows across the fold.
- const resized =
- typeof ResizeObserver === 'undefined'
- ? null
- : new ResizeObserver(measure);
- const list = el.querySelector('.tui-review-find-list');
- if (resized && list) resized.observe(list);
- return () => {
- el.removeEventListener('scroll', measure);
- window.removeEventListener('resize', measure);
- resized?.disconnect();
- };
- }, [findings.length, report]);
-
/** A severity group's findings: drafted cards set in under the group's
heading, or the plain rows of a review the board doesn't edit. */
const findingRows = (items: FindingEntry[]) => {
@@ -534,6 +519,24 @@ function ReviewGateSheet({
{tick}
{title}
{pills}
+ {!hasDiffLine(f) && (
+
+ in summary
+
+ )}
+
+ {SEVERITY_LABEL[f.severity]}
+
}
/>
@@ -666,126 +669,143 @@ function ReviewGateSheet({
onClose={onClose}
>
-
- {review.round !== undefined && (
-
- )}
- {verdict !== undefined && summaryDraft !== undefined && (
- <>
-
-
Summary comment
- {mr && (
-
- posts on {mrRef(mr)}
-
+
+
+ {(
+ [
+ ['findings', 'Findings', findings.length],
+ ['report', 'Report', undefined],
+ ] as const
+ ).map(([id, label, count]) => (
+ setMainTab(id)}
+ >
+ {label}
+ {count !== undefined && (
+ {count}
)}
-
-
- >
- )}
- {carryovers.length > 0 && (
- <>
-
-
- Your earlier threads ({carryovers.length})
-
-
- {carryoverTally(carryovers)}
-
-
-
- {carryovers.map(c => (
-
- ))}
-
- >
- )}
- {carryovers.length > 0 && !findingsQuestion && (
- <>
-
- New this round
-
- Nothing new this round.
- >
- )}
- {findingsQuestion && (
+
+ ))}
+
+ {mainTab === 'findings' && (
<>
-
-
- {carryovers.length > 0
- ? 'New this round'
- : findingsQuestion.label}
-
-
- {selectedFindings.size} of {findings.length} selected
- {!atEnd && moreBelow > 0 ? ` · ${moreBelow} more below` : ''}
-
-
-
- {tierGroups.map(([tier, items]) => {
- const allOn = items.every(f => selectedFindings.has(f.id));
- const allOff = items.every(f => !selectedFindings.has(f.id));
- return (
-
-
-
- {SEVERITY_LABEL[tier]} ({items.length})
-
-
- toggleTier(items, true)}
- >
- all
-
-
- ·
-
- toggleTier(items, false)}
- >
- none
-
-
-
- {findingRows(items)}
-
- );
- })}
-
+ {review.round !== undefined && (
+
+ )}
+ {carryovers.length > 0 && (
+ <>
+
+
+ Your earlier threads ({carryovers.length})
+
+
+ {carryoverTally(carryovers)}
+
+
+
+ {carryovers.map(c => (
+
+ ))}
+
+ >
+ )}
+ {carryovers.length > 0 && !findingsQuestion && (
+ <>
+
+ New this round
+
+ Nothing new this round.
+ >
+ )}
+ {findingsQuestion && (
+ <>
+
+
+ {carryovers.length > 0
+ ? 'New this round'
+ : findingsQuestion.label}
+
+
+ {drafts ? 'Posting ' : ''}
+ {selectedFindings.size} of {findings.length}
+ {drafts ? '' : ' selected'}
+
+
+
+ {drafts
+ ? findingRows(tierGroups.flatMap(([, items]) => items))
+ : tierGroups.map(([tier, items]) => {
+ const allOn = items.every(f =>
+ selectedFindings.has(f.id)
+ );
+ const allOff = items.every(
+ f => !selectedFindings.has(f.id)
+ );
+ return (
+
+
+
+ {SEVERITY_LABEL[tier]} ({items.length})
+
+
+ toggleTier(items, true)}
+ >
+ all
+
+
+ ·
+
+ toggleTier(items, false)}
+ >
+ none
+
+
+
+ {findingRows(items)}
+
+ );
+ })}
+
+ >
+ )}
+ {skippedName && skippedEntries.length > 0 && (
+
+ form.toggleMulti(skippedName, value, on)
+ }
+ />
+ )}
>
)}
- {skippedName && skippedEntries.length > 0 && (
- form.toggleMulti(skippedName, value, on)}
- />
- )}
-
-
- {record ? (
+ {mainTab === 'report' && (record || checks.length > 0) && (
{strengths.length > 0 && (
@@ -839,8 +859,35 @@ function ReviewGateSheet({
)}
+ {checks.length > 0 && (
+
+
checks
+
+ {checks.map((ch, i) => (
+
+
+ {ch.tag}
+
+ {ch.text}
+
+ ))}
+
+
+ )}
- ) : (
+ )}
+ {mainTab === 'report' && !record && (
)}
@@ -869,11 +916,15 @@ function ReviewGateSheet({
{SEVERITY_ORDER.filter(s => review.findings[s] > 0).map(
s => (
- {SEVERITY_LABEL[s]} ({review.findings[s]})
+ {SEVERITY_LABEL[s]}
+
+ {review.findings[s]}
+
)
)}
@@ -881,32 +932,7 @@ function ReviewGateSheet({
)}
- {checks.length > 0 && (
-
-
checks
-
- {checks.map((c, i) => (
-
-
- {c.tag}
-
- {c.text}
-
- ))}
-
-
- )}
+ {checks.length > 0 && }
{outcomeQuestion && (
@@ -915,13 +941,6 @@ function ReviewGateSheet({
{mr ? `Verdict on ${mrRef(mr)}` : 'Verdict'}
-
- reset
-
-
- outcomeName &&
- form.setNote(outcomeName, e.currentTarget.value)
- }
- />
+ {verdict !== undefined && summaryDraft !== undefined && (
+
+ )}
{
+ test('plain text maps one to one', () => {
+ expect(sourceOffset('hello world', 'hello world', 5)).toBe(5);
+ });
+
+ test('skips bold markers before the click', () => {
+ const source = '**suggestion:** thanks for the run';
+ const rendered = 'suggestion: thanks for the run';
+ expect(source.slice(0, caretAfter(source, rendered, 'thanks'))).toBe(
+ '**suggestion:** thanks'
+ );
+ });
+
+ test('a click inside bold text lands inside the markers', () => {
+ const source = '**suggestion:** thanks';
+ const rendered = 'suggestion: thanks';
+ expect(source.slice(0, caretAfter(source, rendered, 'sugg'))).toBe(
+ '**sugg'
+ );
+ });
+
+ test('skips backticks around inline code', () => {
+ const source = 'the `--changed` flag and `src/jobs/**` too';
+ const rendered = 'the --changed flag and src/jobs/** too';
+ expect(source.slice(0, caretAfter(source, rendered, 'flag and src/'))).toBe(
+ 'the `--changed` flag and `src/'
+ );
+ });
+
+ test('a link maps to its text, not its url', () => {
+ const source = 'see [the docs](https://example.test/a.b) for more';
+ const rendered = 'see the docs for more';
+ expect(source.slice(0, caretAfter(source, rendered, 'for'))).toBe(
+ 'see [the docs](https://example.test/a.b) for'
+ );
+ });
+
+ test('paragraph breaks collapse without drifting', () => {
+ const source = 'first line\n\nsecond line';
+ const rendered = 'first line\nsecond line';
+ expect(source.slice(0, caretAfter(source, rendered, 'second'))).toBe(
+ 'first line\n\nsecond'
+ );
+ });
+
+ test('a click at the start stays at the start', () => {
+ expect(sourceOffset('**bold**', 'bold', 0)).toBe(0);
+ });
+
+ test('a click past the end lands at the end of the source', () => {
+ expect(sourceOffset('**bold**', 'bold', 99)).toBe(8);
+ });
+
+ test('rendered text the source cannot match lands at the end', () => {
+ expect(sourceOffset('abc', 'xyz', 2)).toBe(3);
+ });
+});
diff --git a/apps/board/src/client/board/__tests__/comment-field-dom.test.tsx b/apps/board/src/client/board/__tests__/comment-field-dom.test.tsx
index 384f959d8d..32db8a14d3 100644
--- a/apps/board/src/client/board/__tests__/comment-field-dom.test.tsx
+++ b/apps/board/src/client/board/__tests__/comment-field-dom.test.tsx
@@ -261,13 +261,22 @@ test('a fenced block shows its language over the code, and plain without a highl
const block = panel.querySelector(
'.tui-md-code[data-lang="ts"]'
)!;
- expect(block.querySelector('.tui-md-code-head')!.textContent).toBe('ts');
+ expect(block.querySelector('.tui-md-code-head')!.textContent).toBe(
+ 'TypeScript'
+ );
expect(block.querySelector('pre code')!.textContent).toBe(
'const mod = jest.requireActual("./config");'
);
expect(block.querySelector('.tui-md-code-hl')).toBeNull();
});
+test('a fence named after an Object.prototype key shows that name, not the prototype', async () => {
+ const panel = await preview('```__proto__\nx\n```\n\n```constructor\ny\n```');
+ expect(
+ [...panel.querySelectorAll('.tui-md-code-head')].map(h => h.textContent)
+ ).toEqual(['__proto__', 'constructor']);
+});
+
test('a suggestion fence reads as a suggested change', async () => {
const panel = await preview(RICH);
const block = panel.querySelector(
diff --git a/apps/board/src/client/board/__tests__/respond-header-dom.test.tsx b/apps/board/src/client/board/__tests__/respond-header-dom.test.tsx
index 7ae26e24b4..36eb3b8d27 100644
--- a/apps/board/src/client/board/__tests__/respond-header-dom.test.tsx
+++ b/apps/board/src/client/board/__tests__/respond-header-dom.test.tsx
@@ -173,7 +173,7 @@ test('an open plan@1 gate opens the respond sheet: threads left; MR card, decisi
'add retry to the fetch queue'
);
expect(card.querySelector('.tui-id-card-branch')!.textContent).toBe(
- 'feature/demo-12-retry'
+ '· feature/demo-12-retry'
);
const context = $('.tui-sheet-rail .tui-sheet-context-card')!;
expect(context.querySelector('.tui-id-card-lead')!.textContent).toBe(
diff --git a/apps/board/src/client/board/__tests__/respond-sheet-dom.test.tsx b/apps/board/src/client/board/__tests__/respond-sheet-dom.test.tsx
index 765b32e3f0..eaf9a0241b 100644
--- a/apps/board/src/client/board/__tests__/respond-sheet-dom.test.tsx
+++ b/apps/board/src/client/board/__tests__/respond-sheet-dom.test.tsx
@@ -1849,9 +1849,11 @@ test('a post sheet offers an unticked re-review ask for each unrequested latch',
expect(ticks).toHaveLength(1);
expect(ticks[0]!.checked).toBe(false);
expect(ticks[0]!.closest('label')!.textContent).toBe(
- 'Ask Bo for a re-review once posting finishes'
+ 're-reviewask Bo after posting'
);
- expect($('[data-section="re-review"] h3')!.textContent).toBe('Re-review');
+ expect(
+ $('.tui-sheet-dock [data-section="re-review"]')!.getAttribute('aria-label')
+ ).toBe('Re-review');
});
test('a ticked re-review ask rides the answer as the latch thread id', async () => {
@@ -1897,7 +1899,7 @@ test("a run answering one person offers only that person's latch", async () => {
)
);
expect(reReviewTicks().map(t => t.closest('label')!.textContent)).toEqual([
- 'Ask Ana for a re-review once posting finishes',
+ 're-reviewask Ana after posting',
]);
});
diff --git a/apps/board/src/client/board/__tests__/review-code-dom.test.tsx b/apps/board/src/client/board/__tests__/review-code-dom.test.tsx
index b539d551f9..1aab82360c 100644
--- a/apps/board/src/client/board/__tests__/review-code-dom.test.tsx
+++ b/apps/board/src/client/board/__tests__/review-code-dom.test.tsx
@@ -1,11 +1,12 @@
-/** A drafted finding's The Code section: the file header from the
- finding's anchor, the "view full diff" link once the sheet's DiffSource
+/** A drafted finding's code block: the file bar from the
+ finding's anchor, the "full diff" button once the sheet's DiffSource
has the file, and the full-diff modal it opens (Escape closes it back to
the link; the sheet stays open). */
import React from 'react';
import { GlobalRegistrator } from '@happy-dom/global-registrator';
import { afterAll, afterEach, beforeEach, expect, test } from 'bun:test';
+import { MotionGlobalConfig } from 'motion/react';
import { createRoot, type Root } from 'react-dom/client';
import type { GateRow } from '../../../gates/store.ts';
@@ -19,6 +20,12 @@ import { useGateForm } from '../GateForm.tsx';
import { ReviewGateSheet } from '../ReviewGateSheet.tsx';
GlobalRegistrator.register({ url: 'http://localhost/' });
+// happy-dom's Web Animations stub rejects a cancelled animation, which motion
+// raises as an unhandled error (StrictMode's double mount cancels one);
+// without `animate` motion uses its own frame loop, and skipAnimations
+// settles every fold at once.
+delete (Element.prototype as { animate?: unknown }).animate;
+MotionGlobalConfig.skipAnimations = true;
afterAll(async () => {
await GlobalRegistrator.unregister();
@@ -195,7 +202,7 @@ const codeOf = (title: string) => {
};
const fullDiffLink = (title: string) =>
[...codeOf(title).querySelectorAll('button')].find(b =>
- b.textContent?.includes('view full diff')
+ b.textContent?.includes('full diff')
);
const dialog = () =>
document.querySelector(
@@ -231,7 +238,7 @@ test('the source is asked once per file, with the MR and the path', async () =>
expect(asked).toEqual([{ mr: MR.webUrl!, file: 'lib/retry.ts' }]);
});
-test('once the diff is in, view full diff opens the whole file with every finding on it', async () => {
+test('once the diff is in, full diff opens the whole file with every finding on it', async () => {
await render(source);
const link = fullDiffLink('Retry loop lacks backoff')!;
expect(link).toBeDefined();
@@ -251,7 +258,7 @@ test('clicking the snippet opens the full diff too', async () => {
await render(source);
await React.act(async () =>
codeOf('Magic number')
- .querySelector('.tui-review-code')!
+ .querySelector('.tui-review-code-snippet')!
.click()
);
expect(dialog()).not.toBeNull();
@@ -480,10 +487,10 @@ test('under StrictMode a revision change during the first fetch still settles',
test('selecting text inside the snippet does not open the full diff', async () => {
await render({ ...source, fetchFileDiff: async () => RETRY });
const snippet = codeOf('Retry loop lacks backoff').querySelector(
- '.tui-review-code'
+ '.tui-review-code-snippet'
)!;
const range = document.createRange();
- range.selectNodeContents(snippet.querySelector('.tui-review-code-path')!);
+ range.selectNodeContents(snippet);
const picked = window.getSelection()!;
picked.removeAllRanges();
picked.addRange(range);
diff --git a/apps/board/src/client/board/__tests__/review-gate-sheet-dom.test.tsx b/apps/board/src/client/board/__tests__/review-gate-sheet-dom.test.tsx
index 8e5766bcb7..67f6121557 100644
--- a/apps/board/src/client/board/__tests__/review-gate-sheet-dom.test.tsx
+++ b/apps/board/src/client/board/__tests__/review-gate-sheet-dom.test.tsx
@@ -17,6 +17,7 @@ import {
expect,
test,
} from 'bun:test';
+import { MotionGlobalConfig } from 'motion/react';
import { createRoot, type Root } from 'react-dom/client';
import { gateDraftKey } from '@mattstack/gate-kit/react';
@@ -30,6 +31,13 @@ import {
} from './fake-resize-observer.ts';
GlobalRegistrator.register({ url: 'http://localhost/' });
+// happy-dom's Web Animations stub rejects a cancelled animation, which motion
+// raises as an unhandled error when a comment swaps faces; without `animate`
+// motion falls back to its own frame loop.
+delete (Element.prototype as { animate?: unknown }).animate;
+// Folds and fades finish at once, so an unticked card's sections leave the
+// DOM in the same act() rather than after an exit animation.
+MotionGlobalConfig.skipAnimations = true;
afterAll(async () => {
await GlobalRegistrator.unregister();
@@ -455,15 +463,10 @@ test('a clean review labels the submit with the outcome alone, never post 0', as
).toBe(false);
});
-test('a note on the outcome question posts as {value, note}, not silently dropped', async () => {
+test('a note saved in an earlier draft posts as {value, note}, not silently dropped', async () => {
seedDraft(GATE.gateId, { notes: { outcome: 'Merge once CI settles.' } });
await render();
- const note = container.querySelector(
- '.tui-sheet-dock .tui-gate-note'
- ) as HTMLInputElement;
- expect(note.value).toBe('Merge once CI settles.');
-
await click(buttonByText('approve'));
const answerPost = posts.find(p => p.url === '/gate/answer');
@@ -528,32 +531,24 @@ test('a blank or whitespace-only note posts the bare selection, not an empty not
expect(body.answers.outcome).toBe('approve');
});
-test('reset re-seeds every finding checked and the recommended outcome', async () => {
+test('the verdict dock has no reset and no note field', async () => {
await render();
-
- const first = container.querySelector(
- '.tui-review-finding-row input[type="checkbox"]'
- ) as HTMLInputElement;
- await click(first);
- const comment = [...container.querySelectorAll('input[type=radio]')].find(
- i => (i as HTMLInputElement).value === 'comment'
- ) as HTMLInputElement;
- await click(comment);
-
- expect(container.querySelector('.tui-sheet-submit')?.textContent).toBe(
- 'comment'
- );
-
- await click(buttonByText('reset'));
-
+ const dock = container.querySelector('.tui-sheet-dock')!;
expect(
- container.querySelector('.tui-sheet-list-tally')?.textContent
- ).toContain('6 of 6 selected');
- expect(container.querySelector('.tui-sheet-submit')?.textContent).toBe(
- 'approve'
- );
+ [...dock.querySelectorAll('button')].filter(b =>
+ /reset/i.test(b.textContent ?? '')
+ )
+ ).toEqual([]);
+ expect(dock.querySelector('.tui-gate-note')).toBeNull();
});
+async function openReportTab() {
+ const tab = [...container.querySelectorAll('[role="tab"]')].find(
+ b => b.textContent === 'Report'
+ ) as HTMLButtonElement;
+ await click(tab);
+}
+
function checkboxForTitle(title: string): HTMLInputElement {
const row = [...container.querySelectorAll('.tui-review-finding-row')].find(
r => r.querySelector('.tui-review-finding-title')?.textContent === title
@@ -606,13 +601,14 @@ test("a malformed report.json renders the sheet without throwing and skips the r
await React.act(async () => {
await new Promise(resolve => setTimeout(resolve, 0));
});
+ await openReportTab();
const labels = [
...container.querySelectorAll('.tui-review-record-label'),
].map(l => l.textContent);
- // strengths and notes are dropped whole (not arrays); checks render in the
- // rail's CHECKS card, not the main column, so they never add a label here.
- expect(labels).toEqual(['depth']);
+ // strengths and notes are dropped whole (not arrays); the checks show in
+ // the Report tab's card as well as the rail's.
+ expect(labels).toEqual(['depth', 'checks']);
// The one malformed check entry (missing `text`) is dropped, the
// well-typed one stays and shows up in the rail card.
expect(container.textContent).toContain('real check');
@@ -795,11 +791,9 @@ test('the decision card reads readiness, summary, counts, and the re-review line
'renee · round 2 · 3 addressed, 1 waiting on author'
);
const railPills = [
- ...container.querySelectorAll(
- '.tui-sheet-context-card .tui-review-tier-pill'
- ),
+ ...container.querySelectorAll('.tui-sheet-context-card .tui-review-sev'),
].map(p => p.textContent);
- expect(railPills).toEqual(['Important (1)', 'Minor (2)']);
+ expect(railPills).toEqual(['Important1', 'Minor2']);
});
test('a first-round review has no meta line beyond the reviewer', async () => {
@@ -828,6 +822,7 @@ test("report.json's summary never reaches the decision card", async () => {
await React.act(async () => {
await new Promise(resolve => setTimeout(resolve, 0));
});
+ await openReportTab();
expect(container.querySelector('.tui-sheet-context-lead')!.textContent).toBe(
'Ready to merge: with fixes'
);
@@ -1293,21 +1288,36 @@ describe('a gate whose poster honors edited drafts', () => {
};
async function edit(scope: Element, text: string) {
- const box = scope.querySelector(
+ let box = scope.querySelector(
'textarea.tui-composer-input'
- )!;
+ );
+ if (!box) {
+ await React.act(async () => {
+ scope.querySelector('.tui-cte-view')!.click();
+ });
+ box = scope.querySelector(
+ 'textarea.tui-composer-input'
+ );
+ }
await React.act(async () => {
Object.getOwnPropertyDescriptor(
HTMLTextAreaElement.prototype,
'value'
- )!.set!.call(box, text);
- box.dispatchEvent(new Event('input', { bubbles: true }));
+ )!.set!.call(box!, text);
+ box!.dispatchEvent(new Event('input', { bubbles: true }));
});
}
+ /** What each comment field in `scope` holds: the raw text while it is
+ open, the rendered text at rest. */
const valueOf = (scope: Element | null | undefined) =>
- [...(scope?.querySelectorAll('textarea') ?? [])]
- .map(t => (t as HTMLTextAreaElement).value)
+ [...(scope?.querySelectorAll('.tui-cte') ?? [])]
+ .map(
+ f =>
+ f.querySelector('textarea')?.value ??
+ f.querySelector('.tui-cte-view')?.textContent ??
+ ''
+ )
.join('\n');
const answers = () =>
@@ -1323,22 +1333,25 @@ describe('a gate whose poster honors edited drafts', () => {
const sectionOf = (item: Element, name: string) =>
item.querySelector(`.tui-review-section[aria-label="${name}"]`);
- test('a ticked finding is one card: header, then The Code, Agent Finding and Comment', async () => {
+ test('a ticked finding is one card: head, code, then the comment, with no section heads', async () => {
await render(draftsGate());
const item = itemFor('SQL built from unsanitized input');
expect(item.tagName).toBe('ARTICLE');
- expect(
- [...item.querySelectorAll('.tui-review-section-name')].map(
- n => n.textContent
- )
- ).toEqual(['The Code', 'Agent Finding', 'Comment']);
+ const head = item.querySelector('.tui-review-card-head')!;
+ expect(head.tagName).toBe('LABEL');
+ expect(head.classList.contains('tui-review-finding-row')).toBe(true);
+ expect(head.querySelector('input[type="checkbox"]')).not.toBeNull();
+ expect(head.querySelector('.tui-review-sev')!.textContent).toBe('Critical');
+ expect(item.querySelector('.tui-review-section-name')).toBeNull();
+ expect(sectionOf(item, 'Agent Finding')).toBeNull();
expect(
sectionOf(item, 'The Code')!.querySelector('.tui-review-code-path')!
.textContent
).toBe('lib/db/query.ts:42');
- expect(sectionOf(item, 'Agent Finding')!.textContent).toContain(
- 'SQL built from unsanitized input: the full finding text, never truncated.'
- );
+ expect(
+ sectionOf(item, 'The Code')!.querySelector('.tui-review-code-fold')
+ ).not.toBeNull();
+ expect(sectionOf(item, 'Comment')).not.toBeNull();
expect(item.querySelector('.tui-review-finding-anchor')).toBeNull();
});
@@ -1351,38 +1364,53 @@ describe('a gate whose poster honors edited drafts', () => {
expect(item.querySelector('.tui-review-card-head')).not.toBeNull();
});
- test('the cards sit indented under their severity heading', async () => {
+ test('drafted cards form one flat list in severity order, with no tier heads', async () => {
await render(draftsGate());
- const group = container.querySelector('.tui-review-tier-group')!;
+ const list = container.querySelector('.tui-review-find-list')!;
expect(
- group.querySelector('.tui-review-tier-items > .tui-review-card')
- ).not.toBeNull();
- expect(group.querySelector('.tui-review-tier-head')!.textContent).toContain(
- 'all·none'
+ list.querySelectorAll('.tui-review-tier-items > .tui-review-card').length
+ ).toBe(4);
+ expect(container.querySelector('.tui-review-tier-head')).toBeNull();
+ expect(container.querySelector('.tui-review-allnone')).toBeNull();
+ expect(
+ [...list.querySelectorAll('.tui-review-card-head .tui-review-sev')].map(
+ n => n.textContent
+ )
+ ).toEqual(['Critical', 'Important', 'Important', 'Minor']);
+ expect(container.querySelector('.tui-sheet-list-tally')!.textContent).toBe(
+ 'Posting 4 of 4'
);
});
- test('each ticked anchored finding shows its whole draft as the comment, with no fix line', async () => {
+ test('each ticked anchored finding reads its whole draft as the comment, with no fix line', async () => {
await render(draftsGate());
const box = sectionOf(
itemFor('SQL built from unsanitized input'),
'Comment'
)!;
- expect(
- box.querySelector('.tui-review-comment-foot')!.textContent
- ).toContain('Markdown supported');
+ expect(box.querySelector('.tui-cte-view')).not.toBeNull();
+ expect(box.querySelector('textarea')).toBeNull();
+ expect(box.querySelector('.tui-cte-hint')!.textContent).toBe(
+ 'Click to edit'
+ );
expect(valueOf(box)).toContain('Could we bind it as a parameter instead?');
expect(valueOf(box)).toContain(
'A test with a quote in the name would pin it.'
);
+ await React.act(async () => {
+ box.querySelector('.tui-cte-view')!.click();
+ });
+ expect(box.querySelector('.tui-cte-hint')!.textContent).toBe(
+ 'Markdown supportedesc to finish'
+ );
expect(container.querySelector('.tui-review-finding-fix')).toBeNull();
});
- test('unticking hides the box, and re-ticking brings back the earlier edit', async () => {
+ test('unticking hides the comment, and re-ticking brings back the earlier edit', async () => {
await render(draftsGate());
await edit(itemFor('Unused import'), 'Drop this import, please.');
await click(checkboxForTitle('Unused import'));
- expect(itemFor('Unused import').querySelector('textarea')).toBeNull();
+ expect(itemFor('Unused import').querySelector('.tui-cte')).toBeNull();
expect(itemFor('Unused import').hasAttribute('data-off')).toBe(true);
await click(checkboxForTitle('Unused import'));
const item = itemFor('Unused import');
@@ -1407,10 +1435,7 @@ describe('a gate whose poster honors edited drafts', () => {
test('an edited summary line rides the outcome as text', async () => {
await render(draftsGate());
- await edit(
- container.querySelector('.tui-review-summary [data-section="summary"]')!,
- 'New summary.'
- );
+ await edit(summaryLine(), 'New summary.');
await click(submitButton());
expect(answers().outcome).toEqual({
value: 'approve',
@@ -1419,7 +1444,7 @@ describe('a gate whose poster honors edited drafts', () => {
});
const summaryLine = () =>
- container.querySelector('.tui-review-summary [data-section="summary"]')!;
+ container.querySelector('.tui-review-dock-summary')!;
const pickVerdict = async (value: string) =>
click(
@@ -1436,17 +1461,6 @@ describe('a gate whose poster honors edited drafts', () => {
expect(valueOf(summaryLine())).not.toContain(SUMMARY);
});
- test('the summary badge names the selected verdict in its colour and follows it', async () => {
- await render(draftsGate());
- const badge = () =>
- container.querySelector('.tui-review-summary [data-verdict]');
- expect(badge()?.textContent).toBe('for approve');
- expect(badge()?.getAttribute('data-intent')).toBe('ok');
- await pickVerdict('comment');
- expect(badge()?.textContent).toBe('for comment');
- expect(badge()?.getAttribute('data-intent')).toBe('accent');
- });
-
test('each verdict keeps its own edit: switching away and back restores it', async () => {
await render(draftsGate());
await edit(summaryLine(), 'Approve, edited.');
@@ -1454,16 +1468,12 @@ describe('a gate whose poster honors edited drafts', () => {
expect(valueOf(summaryLine())).toContain(SUMMARY_COMMENT);
expect(valueOf(summaryLine())).not.toContain('Approve, edited.');
expect(
- container.querySelector(
- '.tui-review-summary [data-section="summary"][data-edited]'
- )
+ container.querySelector('.tui-review-dock-summary[data-edited]')
).toBeNull();
await pickVerdict('approve');
expect(valueOf(summaryLine())).toContain('Approve, edited.');
expect(
- container.querySelector(
- '.tui-review-summary [data-section="summary"][data-edited]'
- )
+ container.querySelector('.tui-review-dock-summary[data-edited]')
).not.toBeNull();
});
@@ -1546,7 +1556,8 @@ describe('a gate whose poster honors edited drafts', () => {
test('a summary draft missing for a verdict leaves the sheet read-only', async () => {
await render(draftsGate({ summaryComments: { approve: SUMMARY } }));
- expect(container.querySelector('.tui-review-summary')).toBeNull();
+ expect(container.querySelector('.tui-review-dock-summary')).toBeNull();
+ expect(container.querySelector('.tui-cte')).toBeNull();
expect(container.querySelector('textarea')).toBeNull();
});
@@ -1556,73 +1567,90 @@ describe('a gate whose poster honors edited drafts', () => {
expect(submitButton().disabled).toBe(true);
});
- test('the summary comes first in the main column, with the line and each ticked no-diff-line finding', async () => {
+ test('the summary lives in the verdict dock, above submit, and not in the main column', async () => {
await render(draftsGate());
- const main = container.querySelector('.tui-sheet-main')!;
- const head = main.firstElementChild!;
- expect(head.querySelector('.tui-sheet-list-title')?.textContent).toBe(
- 'Summary comment'
- );
- expect(head.querySelector('.tui-sheet-list-tally')?.textContent).toBe(
+ const dock = container.querySelector('.tui-sheet-dock')!;
+ const card = dock.querySelector('.tui-review-dock-summary')!;
+ expect(card.tagName).toBe('SECTION');
+ expect(card.getAttribute('aria-label')).toBe('Review comment');
+ expect(
+ card.querySelector('.tui-review-dock-summary-title')!.textContent
+ ).toBe('Review comment');
+ expect(card.querySelector('.tui-review-section-meta')!.textContent).toBe(
'posts on !31'
);
- const card = main.querySelector('.tui-review-summary')!;
expect(
- card.compareDocumentPosition(
- main.querySelector('.tui-review-find-list')!
- ) & Node.DOCUMENT_POSITION_FOLLOWING
+ card.compareDocumentPosition(dock.querySelector('.tui-sheet-submit')!) &
+ Node.DOCUMENT_POSITION_FOLLOWING
).toBeTruthy();
expect(
- container.querySelector('.tui-sheet-rail .tui-review-summary')
+ container.querySelector('.tui-sheet-main .tui-review-dock-summary')
).toBeNull();
expect(
container.querySelector('.tui-sheet-dock-heading')!.textContent
).toBe('Verdict on !31');
- const parts = card.querySelectorAll('.tui-review-section');
- expect(parts.length).toBe(2);
- expect(parts[0]!.getAttribute('data-section')).toBe('summary');
- expect(valueOf(parts[0])).toContain(SUMMARY);
- expect(valueOf(parts[1])).toContain(COMMENT.f3);
+ expect(valueOf(card)).toBe(SUMMARY);
+ expect(container.querySelector('.tui-review-summary')).toBeNull();
});
- test('on a later round the round band stays first, the summary right under it', async () => {
+ test('on a later round the tabs lead, then the round band, then the findings list', async () => {
await render(draftsGate({ round: 2 }));
const main = container.querySelector('.tui-sheet-main')!;
- expect(main.firstElementChild?.className).toBe('tui-sheet-round');
+ expect(main.firstElementChild?.getAttribute('role')).toBe('tablist');
+ expect(main.children[1]?.className).toBe('tui-sheet-round');
expect(
- main.children[1]?.querySelector('.tui-sheet-list-title')?.textContent
- ).toBe('Summary comment');
+ main.children[2]?.querySelector('.tui-sheet-list-title')?.textContent
+ ).toBe('Post which findings to !31?');
});
- test('with no MR the headings name no target', async () => {
+ test('with no MR the dock heading names no target and the summary has no posting target', async () => {
await render(draftsGate(), { noMr: true });
expect(
container.querySelector('.tui-sheet-dock-heading')!.textContent
).toBe('Verdict');
expect(
- container
- .querySelector('.tui-sheet-main')!
- .firstElementChild!.querySelector('.tui-sheet-list-tally')
+ container.querySelector(
+ '.tui-review-dock-summary .tui-review-section-meta'
+ )
).toBeNull();
});
- test('a no-diff-line finding points at the summary instead of carrying a box', async () => {
+ test('a no-diff-line finding wears an in-summary badge in its head, with no code and a comment of its own', async () => {
await render(draftsGate());
const item = itemFor('Inconsistent error wording');
- expect(item.querySelector('textarea')).toBeNull();
expect(item.querySelector('[data-section="code"]')).toBeNull();
- expect(sectionOf(item, 'Comment')!.textContent).toContain(
- 'Posts in the summary (no diff line)'
- );
+ const badge = item.querySelector(
+ '.tui-review-card-head .tui-review-in-summary'
+ )!;
+ expect(badge.textContent).toBe('in summary');
+ expect(badge.getAttribute('title')).toBeTruthy();
+ expect(
+ badge.compareDocumentPosition(item.querySelector('.tui-review-sev')!) &
+ Node.DOCUMENT_POSITION_FOLLOWING
+ ).toBeTruthy();
+ expect(item.querySelector('.tui-review-code-file')).toBeNull();
+ expect(
+ itemFor('SQL built from unsanitized input').querySelector(
+ '.tui-review-in-summary'
+ )
+ ).toBeNull();
+ expect(valueOf(sectionOf(item, 'Comment'))).toContain(COMMENT.f3);
+ expect(
+ container.querySelector('.tui-review-dock-summary')!.textContent
+ ).not.toContain('Inconsistent error wording');
});
- test('unticking the no-diff-line finding drops it and the hint from the summary card', async () => {
+ test('a no-diff-line finding has no Remove button; unticking drops its comment', async () => {
await render(draftsGate());
+ expect(
+ container.querySelector('button[aria-label$=": remove"]')
+ ).toBeNull();
await click(checkboxForTitle('Inconsistent error wording'));
- const card = container.querySelector('.tui-review-summary')!;
- expect(card.querySelectorAll('textarea').length).toBe(1);
- expect(valueOf(card)).not.toContain(COMMENT.f3);
- expect(card.querySelector('[data-section="folded"]')).toBeNull();
+ const item = itemFor('Inconsistent error wording');
+ expect(item.querySelector('.tui-cte')).toBeNull();
+ expect(
+ container.querySelectorAll('.tui-review-dock-summary .tui-cte').length
+ ).toBe(1);
});
test('the submit label names the verdict alone, whatever is ticked', async () => {
@@ -1636,109 +1664,115 @@ describe('a gate whose poster honors edited drafts', () => {
const metaOf = (scope: Element) =>
scope.querySelector('.tui-review-section-meta')?.textContent;
- test('every comment is a framed text area ready to type into, named for what it edits', async () => {
+ test('every comment reads rendered at rest, a click-to-edit textbox named for what it edits', async () => {
await render(draftsGate());
- expect(
- container.querySelector('button[aria-label$="edit comment"]')
- ).toBeNull();
+ expect(container.querySelector('textarea')).toBeNull();
const labels = [
- ...container.querySelectorAll(
- 'textarea.tui-composer-input'
+ ...container.querySelectorAll(
+ '.tui-cte-view[role="textbox"]'
),
].map(t => t.getAttribute('aria-label'));
expect(labels).toEqual([
- 'Summary line',
- 'Summary comment: Inconsistent error wording',
'Comment on SQL built from unsanitized input',
'Comment on Missing null check on response',
+ 'Comment on Inconsistent error wording',
'Comment on Unused import',
+ 'Summary line',
]);
- expect(metaOf(itemFor('Unused import'))).toBe('drafted by the agent');
+ expect(metaOf(itemFor('Unused import'))).toBeUndefined();
+ });
+
+ test('a click opens a comment as a textarea holding the raw draft; blur renders it again', async () => {
+ await render(draftsGate());
+ const section = sectionOf(itemFor('Unused import'), 'Comment')!;
+ await React.act(async () => {
+ section.querySelector('.tui-cte-view')!.click();
+ });
+ const box = section.querySelector('textarea')!;
+ expect(box.value).toBe(COMMENT.f4);
+ expect(box.getAttribute('aria-label')).toBe('Comment on Unused import');
+ await React.act(async () => {
+ box.blur();
+ });
+ expect(
+ section.querySelector('.tui-cte')!.hasAttribute('data-editing')
+ ).toBe(false);
+ expect(section.querySelector('.tui-cte-view')).not.toBeNull();
});
- test('a changed comment says edited with a reset that restores the draft', async () => {
+ test('closing a changed comment flashes "Comment updated"; an unchanged one does not', async () => {
+ await render(draftsGate());
+ const section = sectionOf(itemFor('Unused import'), 'Comment')!;
+ const hint = () => section.querySelector('.tui-cte-hint')!;
+ await React.act(async () => {
+ section.querySelector('.tui-cte-view')!.click();
+ });
+ await React.act(async () => {
+ section.querySelector('textarea')!.blur();
+ });
+ expect(hint().hasAttribute('data-flash')).toBe(false);
+ expect(hint().textContent).toBe('Click to edit');
+
+ const changed = sectionOf(
+ itemFor('SQL built from unsanitized input'),
+ 'Comment'
+ )!;
+ await edit(changed, 'Bind q as a parameter.');
+ await React.act(async () => {
+ changed.querySelector('textarea')!.blur();
+ });
+ const flash = changed.querySelector('.tui-cte-hint')!;
+ expect(flash.getAttribute('data-flash')).toBe('shown');
+ expect(flash.textContent).toBe('Comment updated');
+ });
+
+ test('Tab onto a rendered comment opens it for typing', async () => {
+ await render(draftsGate());
+ const section = sectionOf(itemFor('Unused import'), 'Comment')!;
+ await React.act(async () => {
+ section.querySelector('.tui-cte-view')!.focus();
+ });
+ expect(section.querySelector('textarea')).not.toBeNull();
+ });
+
+ test('a changed comment offers a reset that restores the draft', async () => {
await render(draftsGate());
const item = () => itemFor('Unused import');
await edit(item(), 'Drop this import, please.');
- expect(metaOf(item())).toBe('edited·reset to draft');
+ expect(metaOf(item())).toBe('Reset to draft');
await click(
item().querySelector('button.tui-composer-act')!
);
expect(valueOf(sectionOf(item(), 'Comment'))).toBe(COMMENT.f4);
- expect(metaOf(item())).toBe('drafted by the agent');
+ expect(metaOf(item())).toBeUndefined();
expect(sectionOf(item(), 'Comment')!.hasAttribute('data-edited')).toBe(
false
);
- expect(document.activeElement).toBe(
- sectionOf(item(), 'Comment')!.querySelector('textarea')
- );
- });
-
- test('reset to draft from Preview goes back to Write and focuses the field', async () => {
- await render(draftsGate());
- const item = () => itemFor('Unused import');
- await edit(item(), 'Drop this import, please.');
- const tabOf = (name: string) =>
- [...item().querySelectorAll('.tui-field-tab')].find(
- t => t.textContent === name
- )!;
- await click(tabOf('Preview'));
- expect(item().querySelector('textarea')).toBeNull();
- await click(
- item().querySelector('button.tui-composer-act')!
- );
- const box = sectionOf(item(), 'Comment')!.querySelector('textarea')!;
- expect(box.value).toBe(COMMENT.f4);
- expect(tabOf('Write').getAttribute('aria-pressed')).toBe('true');
- expect(document.activeElement).toBe(box);
});
- test('reset on the summary line from Preview goes back to Write and focuses it', async () => {
+ test('an edited summary line offers a reset that restores the draft', async () => {
await render(draftsGate());
await edit(summaryLine(), 'Approve, edited.');
- const summary = () => container.querySelector('.tui-review-summary')!;
- const tabOf = (name: string) =>
- [...summary().querySelectorAll('.tui-field-tab')].find(
- t => t.textContent === name
- )!;
- await click(tabOf('Preview'));
+ expect(
+ summaryLine().querySelector('.tui-review-section-meta')!.textContent
+ ).toBe('Reset to draft');
await click(
- summary().querySelector(
+ summaryLine().querySelector(
'button[aria-label="Summary line: reset to draft"]'
)!
);
- expect(document.activeElement).toBe(
- summaryLine().querySelector('textarea')
- );
expect(valueOf(summaryLine())).toBe(SUMMARY);
+ expect(summaryLine().hasAttribute('data-edited')).toBe(false);
});
- test('a folded finding is its own section in the summary, and Remove unticks it', async () => {
- await render(draftsGate());
- const folded = () =>
- container.querySelector('.tui-review-summary [data-section="folded"]');
- expect(
- folded()!.querySelector('.tui-review-section-name')?.textContent
- ).toBe('Inconsistent error wording');
- await click(
- folded()!.querySelector(
- 'button[aria-label$=": remove"]'
- )!
- );
- expect(folded()).toBeNull();
- expect(
- (checkboxForTitle('Inconsistent error wording') as HTMLInputElement)
- .checked
- ).toBe(false);
- expect(document.activeElement).toBe(
- checkboxForTitle('Inconsistent error wording')
- );
- });
-
- test('Escape in a field leaves the field, not the sheet; a second Escape reaches the sheet', async () => {
+ test('Escape in a field stays out of the sheet; a second Escape outside a field reaches it', async () => {
await render(draftsGate());
sheetCloses = 0;
- const box = itemFor('Unused import').querySelector(
+ const section = sectionOf(itemFor('Unused import'), 'Comment')!;
+ await React.act(async () => {
+ section.querySelector('.tui-cte-view')!.click();
+ });
+ const box = section.querySelector(
'textarea.tui-composer-input'
)!;
const esc = (el: Element) =>
@@ -1757,13 +1791,6 @@ describe('a gate whose poster honors edited drafts', () => {
document.addEventListener('keydown', onDoc);
try {
await esc(box);
- expect(document.activeElement?.className).toBe('tui-field-tab');
- expect(document.activeElement?.textContent).toBe('Write');
- expect(
- box
- .closest('[data-section="comment"]')!
- .contains(document.activeElement)
- ).toBe(true);
expect(reached).toBe(0);
expect(sheetCloses).toBe(0);
await esc(document.body);
@@ -1773,9 +1800,35 @@ describe('a gate whose poster honors edited drafts', () => {
}
});
+ test('Escape in a field returns it to rendered text with focus on it, not the sheet', async () => {
+ await render(draftsGate());
+ sheetCloses = 0;
+ const section = sectionOf(itemFor('Unused import'), 'Comment')!;
+ await React.act(async () => {
+ section.querySelector('.tui-cte-view')!.click();
+ });
+ const box = section.querySelector(
+ 'textarea.tui-composer-input'
+ )!;
+ const esc = (el: Element) =>
+ React.act(async () => {
+ el.dispatchEvent(
+ new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })
+ );
+ });
+ box.focus();
+ await esc(box);
+ expect(
+ section.querySelector('.tui-cte')!.hasAttribute('data-editing')
+ ).toBe(false);
+ expect(document.activeElement).toBe(
+ [...section.querySelectorAll('.tui-cte-view')].at(-1) ?? null
+ );
+ });
+
test('without editable the sheet is the one it was: fix lines, no boxes, no summary card', async () => {
await render(draftsGate({ editable: false }));
- expect(container.querySelector('.tui-review-summary')).toBeNull();
+ expect(container.querySelector('.tui-review-dock-summary')).toBeNull();
expect(container.querySelector('textarea')).toBeNull();
expect(container.querySelector('.tui-review-card')).toBeNull();
expect(
@@ -1815,13 +1868,6 @@ describe('keyboard', () => {
expect(body.answers['findings-1']).toEqual(['f1', 'f2', 'f3', 'f4']);
});
- test('Ctrl+Enter in the verdict note still posts', async () => {
- await render();
- const note = container.querySelector('.tui-sheet-dock .tui-gate-note')!;
- await press(note, 'Enter', { ctrlKey: true });
- expect(answerPosts().length).toBe(1);
- });
-
test('a number key picks that verdict, and the caps number each verdict', async () => {
await render();
const caps = [
@@ -1841,16 +1887,6 @@ describe('keyboard', () => {
);
});
- test('a number typed into the verdict note never changes the verdict', async () => {
- await render();
- const note = container.querySelector('.tui-sheet-dock .tui-gate-note')!;
- await press(note, '2');
- const radios = [
- ...container.querySelectorAll('.tui-sheet-rail input[type=radio]'),
- ] as HTMLInputElement[];
- expect(radios.find(r => r.value === 'approve')?.checked).toBe(true);
- });
-
test('the submit button shows the chord without changing its label', async () => {
await render();
const submit = container.querySelector('.tui-sheet-submit')!;
diff --git a/apps/board/src/client/board/caret-map.ts b/apps/board/src/client/board/caret-map.ts
new file mode 100644
index 0000000000..4dc194165d
--- /dev/null
+++ b/apps/board/src/client/board/caret-map.ts
@@ -0,0 +1,33 @@
+/** A link's destination never renders as text, so a rendered character
+ must not match inside one. */
+function linkDestinations(source: string): boolean[] {
+ const hidden = new Array(source.length).fill(false);
+ for (const m of source.matchAll(/\]\(([^)]*)\)/g))
+ for (let i = m.index; i < m.index + m[0].length; i++) hidden[i] = true;
+ return hidden;
+}
+
+/** Where a caret at `offset` in `rendered` (the Markdown as it reads) sits
+ in `source`: the rendered characters before it, whitespace aside, are
+ matched in order through the source, so markers the render dropped
+ (`**`, backticks, link syntax) fall behind the caret. A click past the
+ rendered text, or text the source cannot match, lands at the end. */
+export function sourceOffset(
+ source: string,
+ rendered: string,
+ offset: number
+): number {
+ if (offset >= rendered.length) return source.length;
+ const hidden = linkDestinations(source);
+ const before = rendered.slice(0, Math.max(0, offset));
+ let at = 0;
+ for (const ch of before) {
+ if (/\s/.test(ch)) continue;
+ while (at < source.length && (hidden[at] || source[at] !== ch)) at++;
+ if (at >= source.length) return source.length;
+ at++;
+ }
+ const trailing = before.length - before.trimEnd().length;
+ for (let n = 0; n < trailing && /\s/.test(source[at] ?? ''); n++) at++;
+ return at;
+}
diff --git a/apps/board/src/client/board/icons.tsx b/apps/board/src/client/board/icons.tsx
index ea04f69b19..9d5100dbe8 100644
--- a/apps/board/src/client/board/icons.tsx
+++ b/apps/board/src/client/board/icons.tsx
@@ -401,6 +401,36 @@ export function PencilLineIcon() {
);
}
+/** Back to the draft (lucide `undo-2`, ISC licensed). */
+export function UndoGlyph() {
+ return (
+
+
+
+
+ );
+}
+
+/** More about this (lucide `info`, ISC licensed). */
+export function InfoGlyph() {
+ return (
+
+
+
+
+
+ );
+}
+
+/** A done mark (lucide `check`, ISC licensed). */
+export function CheckGlyph() {
+ return (
+
+
+
+ );
+}
+
/** The Code section's mark (lucide `code`, ISC licensed). */
export function CodeGlyph() {
return (
@@ -411,6 +441,16 @@ export function CodeGlyph() {
);
}
+/** A file header's fold control (lucide `chevron-down`, ISC licensed);
+ CSS turns it to point right while the code is folded. */
+export function ChevronGlyph() {
+ return (
+
+
+
+ );
+}
+
/** A file header's mark (lucide `file`, ISC licensed). */
export function FileGlyph() {
return (
diff --git a/apps/board/src/style.css b/apps/board/src/style.css
index 3a023dcce8..5b808e7d6f 100644
--- a/apps/board/src/style.css
+++ b/apps/board/src/style.css
@@ -2453,18 +2453,27 @@ body {
outline-offset: 2px;
border-radius: 3px;
}
+/* The re-review ask sits under the replies it follows, in the dock: what
+ happens after posting, listed with what posts. */
.tui-respond-rereview {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- gap: 8px;
- margin-top: 18px;
+ padding-top: 8px;
+ border-top: 1px solid var(--border-soft);
}
-.tui-respond-rereview-heading {
- margin: 0;
- font-size: 13px;
- font-weight: 500;
- color: var(--text-2);
+.tui-respond-rereview-row {
+ align-items: center;
+ cursor: pointer;
+}
+.tui-respond-rereview-row .tui-sheet-card-text {
+ flex: 1;
+}
+.tui-respond-rereview-lead {
+ display: inline-flex;
+ flex-shrink: 0;
+}
+/* Spans the post chip, its gap and the resolve slot, so the ask's text
+ starts where the replies' paths do. */
+.tui-respond-rereview[data-resolve-slot] .tui-respond-rereview-lead {
+ width: 120px;
}
.tui-post-tick .tui-gate-choice-input {
width: 14px;
@@ -4089,20 +4098,82 @@ a.tui-id-card-ref:focus-visible {
.tui-review-finding[data-off] .tui-review-finding-title {
color: var(--text-3);
}
-.tui-review-finding-row.tui-review-card-head {
+/* A drafted finding is one box: the title strip, the file bar, the diff,
+ then the comment, each divided by a hairline. */
+.tui-review-card-head {
+ display: flex;
align-items: center;
- margin: 0;
- padding: 12px 16px;
+ gap: 10px;
+ padding: 8px 14px;
border-radius: 7px;
}
.tui-review-card:not([data-off]) .tui-review-card-head {
border-radius: 7px 7px 0 0;
+ border-bottom: 1px solid var(--border-soft);
+}
+/* The whole strip is the tickbox's label, and the finding rows' blue
+ hover wash spans the strip edge to edge, following the card's corners,
+ so it reads as one clickable header. The severity takes the far end. */
+.tui-review-card-head.tui-review-finding-row {
+ margin: 0;
+ padding: 10px 14px;
+}
+.tui-review-card-head.tui-review-finding-row:focus-within {
+ background: none;
+ outline: none;
+}
+.tui-review-card-head.tui-review-finding-row:hover {
+ background: color-mix(in srgb, var(--fill-accent-hover) 6%, transparent);
+}
+.tui-review-card-head.tui-review-finding-row:active {
+ background: color-mix(in srgb, var(--fill-accent) 11%, transparent);
+}
+.tui-review-card-head > .tui-review-sev {
+ margin-left: auto;
}
.tui-review-card-head .tui-gate-choice-input {
margin-top: 0;
}
.tui-review-card-head .tui-review-finding-title {
font-size: 14px;
+ font-weight: 600;
+}
+.tui-review-sev {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ flex-shrink: 0;
+ font-size: 12px;
+ font-weight: 500;
+ color: var(--text-3);
+}
+.tui-review-sev::before {
+ content: '';
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--text-4);
+}
+.tui-review-sev[data-sev='critical'] {
+ color: var(--text-bad-small);
+}
+.tui-review-sev[data-sev='critical']::before {
+ background: var(--fill-bad);
+}
+.tui-review-sev[data-sev='important'] {
+ color: var(--text-gold-vivid);
+}
+/* Gold, not the warn orange: next to critical's crimson the orange reads
+ as the same alarm. */
+.tui-review-sev[data-sev='important']::before {
+ background: var(--gold);
+}
+/* No severity headings in a drafted review, so nothing to indent under. */
+.tui-review-find-list[data-drafts] > .tui-review-tier-items {
+ padding-left: 0;
+}
+.tui-review-finding[data-off] .tui-review-sev {
+ opacity: 0.6;
}
.tui-review-section {
display: flex;
@@ -4115,6 +4186,10 @@ a.tui-id-card-ref:focus-visible {
padding-top: 2px;
border-top: none;
}
+/* The card's own border already closes the top. */
+.tui-review-card > .tui-review-section:first-child {
+ border-top: none;
+}
.tui-review-section-head {
display: flex;
align-items: center;
@@ -4273,6 +4348,66 @@ a.tui-id-card-ref:focus-visible {
opacity: 1;
}
}
+/* Inside a drafted card the card is the box: the code loses its own frame
+ and its file bar spans the card. The snippet, not the whole block, opens
+ the full diff. */
+.tui-review-finding .tui-review-section[data-section='code'] {
+ padding: 0;
+ border-top: none;
+}
+.tui-review-finding .tui-review-code,
+.tui-review-finding .tui-review-code:hover {
+ border: none;
+ border-radius: 0;
+ cursor: default;
+}
+.tui-review-finding .tui-review-code-file {
+ padding: 6px 14px;
+ background: var(--panel);
+}
+.tui-review-finding .tui-review-code[data-folded] .tui-review-code-file {
+ border-bottom: none;
+}
+.tui-review-code-snippet {
+ cursor: pointer;
+}
+.tui-review-code-fold {
+ display: inline-flex;
+ padding: 0;
+ border: none;
+ background: none;
+ color: var(--text-3);
+ cursor: pointer;
+ transition: transform 120ms;
+}
+.tui-review-code[data-folded] .tui-review-code-fold {
+ transform: rotate(-90deg);
+}
+.tui-review-code-fold:focus-visible {
+ outline: 2px solid var(--fill-accent);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+.tui-review-code-more {
+ margin-left: auto;
+}
+.tui-review-code-more[data-reveal] {
+ opacity: 0;
+ transition: opacity 120ms;
+}
+.tui-review-section[data-section='code']:hover
+ .tui-review-code-more[data-reveal],
+.tui-review-code-more[data-reveal]:focus-visible {
+ opacity: 1;
+}
+.tui-review-finding .tui-review-section[data-section='comment'] {
+ position: relative;
+ padding: 16px 14px 14px;
+ background: var(--panel);
+}
+.tui-review-finding .tui-review-section[data-section='comment']:last-child {
+ border-radius: 0 0 7px 7px;
+}
/* The diff draws in a shadow root; these reach it as inherited custom
properties. */
.tui-diff {
@@ -4382,6 +4517,22 @@ a.tui-id-card-ref:focus-visible {
.tui-review-summary {
margin-bottom: 4px;
}
+.tui-review-summary-tally {
+ display: inline-flex;
+ align-items: center;
+ gap: 10px;
+}
+.tui-review-summary-parts {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+.tui-review-summary-foot {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
/* Drops a folded finding from the summary: a quiet text control with its
own mark, brightening on hover like the section's other actions. */
.tui-review-remove {
@@ -4623,15 +4774,16 @@ a.tui-id-card-ref:focus-visible {
}
/* A comment as it reads on the MR: the Markdown subset review comments
use, at the field's own size, so switching tabs keeps the card still. */
+.tui-md-comment :is(p, ul, ol, blockquote, table, .tui-md-code) {
+ margin: 0 0 8px;
+}
+/* After the block margins above: same specificity, so order decides. */
.tui-md-comment > :first-child {
margin-top: 0;
}
.tui-md-comment > :last-child {
margin-bottom: 0;
}
-.tui-md-comment :is(p, ul, ol, blockquote, table, .tui-md-code) {
- margin: 0 0 8px;
-}
.tui-md-comment :is(h1, h2, h3, h4, h5, h6) {
margin: 12px 0 6px;
font-weight: 700;
@@ -4668,13 +4820,17 @@ a.tui-id-card-ref:focus-visible {
color: var(--text-accent);
text-underline-offset: 2px;
}
+/* Inline code: the code block's frameless wash. Wrapped across lines,
+ each piece closes its own corners and padding instead of one box
+ breaking open at the line end. */
.tui-md-comment :not(pre) > code {
padding: 1px 5px;
- border: 1px solid var(--border-soft);
border-radius: 4px;
- background: var(--surface-wash-fg-4-card);
+ background: color-mix(in srgb, var(--fg) 6%, var(--card));
font-family: var(--font-mono);
font-size: 0.88em;
+ -webkit-box-decoration-break: clone;
+ box-decoration-break: clone;
}
.tui-md-comment blockquote {
padding: 0 0 0 12px;
@@ -4701,48 +4857,62 @@ a.tui-id-card-ref:focus-visible {
border: none;
border-top: 1px solid var(--border-soft);
}
-/* A fenced block: its language over the code, on a quiet wash; a
+/* A fenced block: a grey wash with no frame, so a comment's code reads
+ as content, not a third box. The language floats top-right and the
+ code wraps around it, so only the first line gives up its width. A
suggestion reads as the change it proposes. */
.tui-md-code {
- border: 1px solid var(--border);
- border-radius: 6px;
+ padding: 8px 14px;
+ border-radius: 4px;
background: var(--surface-wash-fg-4-card);
- overflow: hidden;
+}
+.tui-md-code::after {
+ content: '';
+ display: block;
+ clear: both;
}
.tui-md-code-head {
- padding: 3px 10px;
- border-bottom: 1px solid var(--border-soft);
- font-family: var(--font-mono);
+ float: right;
+ margin: 1px 0 0 12px;
+ font-family: var(--font-sans);
font-size: 11px;
+ line-height: 1.6;
color: var(--text-3);
}
.tui-md-code-body {
margin: 0;
- padding: 8px 12px;
- background: var(--card);
+ padding: 0;
font-family: var(--font-mono);
font-size: 13px;
line-height: 1.6;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
+/* Highlighted code lays out as a grid that floats can't flow into, so
+ its label sits in the corner and the code keeps a gutter clear of it. */
+.tui-md-code:has(.tui-md-code-hl) {
+ position: relative;
+}
+.tui-md-code:has(.tui-md-code-hl) .tui-md-code-head {
+ position: absolute;
+ top: 8px;
+ right: 12px;
+ margin: 1px 0 0;
+}
.tui-md-code-hl {
- padding: 2px 0;
- background: var(--card);
+ padding: 0 76px 0 0;
+ background: none;
}
.tui-md-code[data-suggestion] {
- border-color: color-mix(in srgb, var(--fill-ok) 45%, var(--card));
- background: color-mix(in srgb, var(--fill-ok) 7%, var(--card));
+ background: color-mix(in srgb, var(--fill-ok) 8%, var(--card));
}
.tui-md-code[data-suggestion] .tui-md-code-head {
- font-family: var(--font-sans);
font-weight: 500;
color: var(--text-ok-small);
- border-bottom-color: color-mix(in srgb, var(--fill-ok) 30%, var(--card));
}
.tui-md-code[data-suggestion] .tui-md-code-body {
+ padding-left: 9px;
border-left: 3px solid var(--fill-ok);
- background: color-mix(in srgb, var(--fill-ok) 7%, var(--card));
}
.tui-field-preview-empty {
margin: 0;
@@ -4750,17 +4920,192 @@ a.tui-id-card-ref:focus-visible {
color: var(--text-3);
}
-/* Hairline above the record cluster, spanning the left column. */
-.tui-review-divider {
- margin: 22px 0 0;
- border: none;
- border-top: 1px solid var(--border-soft);
+/* A comment that reads rendered and edits raw (ClickToEditField). Boxed
+ sits in a finding or reply card; bare stacks inside the summary card so
+ its parts read as the one comment the forge shows. A stripe is a
+ left edge with square corners, never a rounded one. */
+/* motion owns the box's height and the faces' fade; CSS eases the rest. */
+.tui-cte {
+ overflow: hidden;
+ transition-property: border-color, background-color, box-shadow;
+ transition-duration: 150ms;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+}
+.tui-cte-faces {
+ position: relative;
+}
+.tui-cte-view {
+ box-sizing: border-box;
+ padding: 10px 14px;
+ font-size: 14px;
+ line-height: 1.5;
+ color: var(--text-1);
+ overflow-wrap: anywhere;
+ cursor: text;
+}
+.tui-cte-view:focus-visible {
+ outline: 2px solid var(--fill-accent);
+ outline-offset: -2px;
+}
+.tui-cte[data-variant='boxed'] {
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ background: var(--card);
+ overflow: hidden;
+}
+.tui-cte[data-variant='boxed'][data-editing] {
+ border-color: var(--fill-ok);
+ box-shadow: 0 0 0 1px var(--fill-ok);
+}
+.tui-cte[data-variant='bare'] .tui-cte-view {
+ padding: 8px 12px;
+}
+/* Write opens out from the text so the wash has room around it. */
+.tui-cte[data-variant='bare'] .tui-cte-input {
+ padding: 10px 12px;
+}
+.tui-cte[data-variant='bare'] {
+ border-left: 2px solid transparent;
+ border-radius: 0;
+}
+.tui-cte[data-variant='bare'][data-stripe='always'] {
+ border-left-color: var(--border);
+}
+.tui-cte[data-variant='bare'][data-editing] {
+ border-left-color: var(--fill-ok);
+ background: var(--surface-wash-fg-4-card);
+}
+/* Filled: a finding's own comment, a light well with no border at rest;
+ writing in it draws the border. */
+.tui-cte[data-variant='filled'] {
+ border: 1px solid transparent;
+ border-radius: 6px;
+ background: var(--surface-wash-fg-4-card);
+}
+.tui-cte[data-variant='filled'][data-editing] {
+ border-color: var(--fill-ok);
+}
+/* Plain: a drafted finding's comment, a white field on the card's grey
+ comment area so it reads as an input before the pointer arrives. Hover
+ shows the click-to-edit pill; writing draws the focus ring. The box keeps
+ one geometry in every state. */
+.tui-cte[data-variant='plain'] {
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ background: var(--card);
+ transition-duration: 200ms;
+}
+.tui-cte[data-variant='plain'] :is(.tui-cte-view, .tui-cte-input) {
+ padding: 10px 12px;
+}
+/* Keyboard focus on the rendered text (Escape lands there) rings the
+ field like Write does; an outline on the text would clip at its corners. */
+.tui-cte[data-variant='plain'][data-editing],
+.tui-cte[data-variant='plain']:has(.tui-cte-view:focus-visible) {
+ border-color: color-mix(in srgb, var(--fill-accent) 70%, var(--border));
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fill-accent) 15%, transparent);
+}
+.tui-cte[data-variant='plain'] .tui-cte-view:focus-visible {
+ outline: none;
+}
+/* At rest the hint is a pill riding the field's top border, in the
+ field's top padding, so it never covers the text; it eases in with the
+ pointer. The section it sits in is its positioning box. */
+.tui-cte[data-variant='plain']:not([data-editing]) + .tui-cte-hint {
+ position: absolute;
+ top: -10px;
+ right: 12px;
+ align-items: center;
+ gap: 5px;
+ height: 20px;
+ min-height: 0;
+ margin: 0;
+ padding: 0 9px 0 8px;
+ border-radius: 999px;
+ font-weight: 500;
+ line-height: 1;
+ color: var(--text-accent);
+ background: color-mix(in srgb, var(--fill-accent) 12%, var(--card));
+ box-shadow:
+ 0 0 0 1px color-mix(in srgb, var(--fill-accent) 14%, transparent),
+ 0 1px 3px color-mix(in srgb, var(--fg) 8%, transparent);
+ opacity: 0;
+ transform: translateY(3px) scale(0.94);
+ pointer-events: none;
+ transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+/* Write's hint tucks just under the field. */
+.tui-cte[data-variant='plain'][data-editing] + .tui-cte-hint {
+ margin-top: 5px;
+}
+.tui-cte-hint svg {
+ width: 12px;
+ height: 12px;
+ flex-shrink: 0;
+}
+@media (hover: hover) {
+ .tui-cte[data-variant='plain']:not([data-editing]):hover + .tui-cte-hint {
+ opacity: 1;
+ transform: none;
+ }
+}
+/* The flash mounts already shown, so it eases in from the hidden pose. */
+.tui-cte[data-variant='plain']:not([data-editing])
+ + .tui-cte-hint[data-flash='shown'] {
+ opacity: 1;
+ transform: none;
+ @starting-style {
+ opacity: 0;
+ transform: translateY(3px) scale(0.94);
+ }
+}
+/* "Comment updated" is a done state, so it takes the ok wash, not the
+ accent the edit cue wears; it keeps it through the fade. */
+.tui-cte[data-variant='plain']:not([data-editing]) + .tui-cte-hint[data-flash] {
+ color: var(--text-ok);
+ background: color-mix(in srgb, var(--fill-ok) 12%, var(--card));
+ box-shadow:
+ 0 0 0 1px color-mix(in srgb, var(--fill-ok) 18%, transparent),
+ 0 1px 3px color-mix(in srgb, var(--fg) 8%, transparent);
+}
+@media (hover: hover) {
+ .tui-cte[data-variant='filled']:not([data-editing]):hover {
+ background: color-mix(in srgb, var(--fg) 7%, var(--card));
+ }
+}
+@media (hover: hover) {
+ .tui-cte[data-variant='bare']:not([data-editing]):hover {
+ background: color-mix(in srgb, var(--fg) 2%, transparent);
+ }
+}
+.tui-cte[data-invalid] {
+ border-color: var(--fill-bad);
+}
+.tui-cte-hint {
+ display: flex;
+ justify-content: space-between;
+ min-height: 18px;
+ margin-top: 6px;
+ padding: 0 13px;
+ font-size: 12px;
+ color: var(--text-3);
}
/* review record cluster: STRENGTHS / DEPTH / NOTES sharing one right-aligned
label column and one text edge. */
+/* The Report tab's record: a white card like the findings, so it reads
+ as part of the review, not loose on the column. */
+/* Findings and Report share the main column as tabs, so neither
+ scrolls under the other. */
+.tui-review-tabs {
+ margin-bottom: 16px;
+}
.tui-review-record {
- margin: 16px 0 0;
+ margin: 0;
+ padding: 14px 16px;
+ border: 1px solid var(--border);
+ border-radius: 8px;
+ background: var(--card);
display: flex;
flex-direction: column;
gap: 12px;
@@ -6257,3 +6602,297 @@ a.tui-id-card-ref:focus-visible {
}
}
}
+
+/* The review sheet's main column sits a step lighter than the page, so its
+ white cards separate softly. */
+.tui-sheet-main[data-sheet='review'] {
+ background: var(--panel);
+}
+/* On a wide display the findings stop at a readable measure, centred in
+ the column, with the rail still pinned right; 1120px keeps a 12px mono
+ diff line near 150 characters. */
+.tui-sheet-main[data-sheet='review'] > * {
+ max-width: 1120px;
+ margin-inline: auto;
+}
+
+/* The summary comment in the dock: two lines at rest, whole when open. */
+.tui-review-dock-summary {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+.tui-review-dock-summary-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 10px;
+}
+.tui-review-dock-summary-title {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--text-1);
+}
+.tui-review-dock-summary .tui-cte:not([data-editing]) .tui-md-comment {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.tui-review-dock-summary .tui-cte[data-variant='filled']:not([data-editing]) {
+ border-color: var(--border-soft);
+ background: var(--card);
+}
+
+/* The rail's checks: a tally beside the title, then every check. */
+.tui-review-checks {
+ gap: 8px;
+}
+.tui-review-checks-head {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ color: var(--text-3);
+}
+.tui-review-checks-tally {
+ font-size: 12px;
+}
+
+/* The MR card's age, diff and branch share one line; a long branch clips
+ rather than taking a line of its own. */
+.tui-mr-card .tui-id-card-meta {
+ flex-wrap: nowrap;
+ min-width: 0;
+}
+.tui-mr-card .tui-id-card-branch {
+ flex: 1;
+ min-width: 0;
+}
+
+/* The decision context's severities as the cards show them: a dot, the
+ name, the count. */
+.tui-review-tier-pills:has(.tui-review-sev) {
+ gap: 14px;
+}
+.tui-review-sev-count {
+ margin-left: 2px;
+ font-weight: 400;
+ color: var(--text-3);
+}
+
+/* With the strip's own focus ring gone, the tickbox carries keyboard
+ focus. */
+.tui-review-card-head.tui-review-finding-row
+ .tui-gate-choice-input:focus-visible {
+ outline: 2px solid var(--fill-accent);
+ outline-offset: 2px;
+}
+
+/* A finding with no diff line says where its comment goes in the head;
+ its comment then follows the head straight on, under the head's line. */
+.tui-review-in-summary {
+ flex-shrink: 0;
+}
+.tui-review-card-head
+ + .tui-review-card-body
+ > .tui-review-section:first-child {
+ border-top: none;
+}
+
+/* An edited draft's one control: back to the agent's text. */
+.tui-review-reset {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+}
+.tui-review-reset svg {
+ width: 12px;
+ height: 12px;
+}
+
+/* The field and its hints; the click-to-edit pill rides the field's top
+ border, so the field's own box positions it. */
+.tui-cte-wrap {
+ position: relative;
+}
+/* Above a comment: what mode it is in on the left, its reset on the
+ right. Motion eases the row's height in and out. */
+.tui-cte-head {
+ overflow: hidden;
+}
+.tui-cte-head-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ min-height: 18px;
+ padding: 0 13px 6px;
+}
+.tui-cte-heading {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ font-size: 12px;
+ font-weight: 500;
+ color: var(--text-3);
+}
+.tui-cte-heading svg {
+ width: 12px;
+ height: 12px;
+ color: var(--text-accent);
+}
+
+/* At rest, an edited comment's pill on the field's top-left border: the
+ state, a hairline, then its reset. Interactive, unlike the click-to-edit
+ pill; the field's text drops a little to clear it. */
+.tui-cte-badge {
+ position: absolute;
+ top: -10px;
+ left: 12px;
+ z-index: 1;
+ display: inline-flex;
+ align-items: stretch;
+ height: 20px;
+ border-radius: 999px;
+ overflow: hidden;
+ font-size: 12px;
+ line-height: 1;
+ background: color-mix(in srgb, var(--fg) 5%, var(--card));
+ box-shadow:
+ 0 0 0 1px color-mix(in srgb, var(--fg) 10%, transparent),
+ 0 1px 2px color-mix(in srgb, var(--fg) 6%, transparent);
+ transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
+ @starting-style {
+ opacity: 0;
+ transform: translateY(3px) scale(0.94);
+ }
+}
+.tui-cte-badge-state {
+ display: inline-flex;
+ align-items: center;
+ padding: 0 8px 0 9px;
+ font-weight: 500;
+ color: var(--text-2);
+}
+.tui-cte-badge-sep {
+ align-self: center;
+ width: 1px;
+ height: 10px;
+ background: color-mix(in srgb, var(--fg) 14%, transparent);
+}
+.tui-cte-badge .tui-review-section-meta {
+ display: flex;
+}
+.tui-cte-badge .tui-review-reset {
+ padding: 0 9px 0 7px;
+ font-size: 12px;
+ color: var(--text-accent);
+ transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+/* Hover washes the reset's whole half of the pill, as a split button
+ does; the label keeps its blue and takes no underline. */
+.tui-cte-badge .tui-review-reset.tui-composer-act {
+ display: inline-flex;
+ align-items: center;
+ height: 100%;
+}
+.tui-cte-badge .tui-review-reset.tui-composer-act:hover {
+ text-decoration: none;
+ background: color-mix(in srgb, var(--fill-accent) 12%, transparent);
+}
+.tui-cte-badge + .tui-cte .tui-cte-view {
+ padding-top: 15px;
+}
+/* The wash already divides the halves; the hairline beside it would
+ double the edge. */
+.tui-cte-badge-sep {
+ transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+.tui-cte-badge:has(.tui-review-reset:hover) .tui-cte-badge-sep {
+ opacity: 0;
+}
+
+/* On the dock's grey wash an unpicked choice is a white card, so it
+ reads as something to press rather than a hole in the wash. */
+.tui-sheet-dock .tui-gate-choice:not([data-checked]) {
+ background: var(--card);
+}
+
+/* A finding with no diff line: its file bar, then the agent's finding in
+ the code's place, in a quieter hand than the comment under it. */
+.tui-review-finding .tui-review-section[data-section='finding'] {
+ gap: 0;
+ padding: 0;
+}
+.tui-review-section[data-section='finding'] .tui-review-code-file {
+ padding: 6px 14px;
+}
+.tui-review-finding-said {
+ padding: 12px 14px 14px;
+ background: color-mix(in srgb, var(--fill-accent) 5%, var(--card));
+ font-size: 14px;
+ line-height: 1.55;
+ color: var(--text-1);
+}
+
+/* The info mark beside a code file's path, and the agent's finding it
+ opens on a click. */
+.tui-review-info {
+ display: inline-flex;
+ align-items: center;
+ padding: 2px;
+ border: none;
+ border-radius: 4px;
+ background: none;
+ color: var(--text-3);
+ cursor: pointer;
+ transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+.tui-review-info:hover,
+.tui-review-info[data-popup-open] {
+ color: var(--text-accent);
+ background: color-mix(in srgb, var(--fill-accent) 10%, transparent);
+}
+.tui-review-info:focus-visible {
+ outline: 2px solid var(--fill-accent);
+ outline-offset: 1px;
+}
+.tui-review-info-card {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ max-width: 420px;
+ padding: 10px 12px;
+ font-size: 13px;
+ line-height: 1.5;
+ color: var(--text-1);
+}
+.tui-review-info-title {
+ font-size: 11px;
+ font-weight: 500;
+ color: var(--text-3);
+}
+
+/* The code under its file bar; motion eases its height on fold. */
+.tui-review-code-body {
+ overflow: hidden;
+}
+
+/* A dock taller than the rail allows (many response rows plus a
+ re-review row on a short screen) scrolls inside itself, and submit
+ sticks to its bottom so it never leaves the frame. */
+@media (min-width: 721px) {
+ .tui-sheet-dock {
+ flex-shrink: 0;
+ max-height: 75%;
+ overflow-y: auto;
+ }
+ /* Bands of the dock's ground above and below hide rows scrolling under
+ the stuck button. */
+ .tui-sheet-dock .tui-sheet-submit {
+ position: sticky;
+ bottom: 0;
+ box-shadow:
+ 0 -10px 0 0 var(--surface-wash-fg-4-card),
+ 0 18px 0 0 var(--surface-wash-fg-4-card);
+ }
+}
diff --git a/bun.lock b/bun.lock
index 82dea27fd0..ba7882e6b7 100644
--- a/bun.lock
+++ b/bun.lock
@@ -78,6 +78,7 @@
"@mattstack/tui-kit": "workspace:*",
"@pierre/diffs": "catalog:",
"invadrs": "^1.3.1",
+ "motion": "14.2.0",
"pngjs": "^7.0.0",
"react": "catalog:",
"react-dom": "catalog:",
@@ -2183,6 +2184,8 @@
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
+ "framer-motion": ["framer-motion@14.2.0", "", { "dependencies": { "motion-dom": "14.2.0", "motion-utils": "14.1.1", "tslib": "^2.4.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-cD2gfFujHt4r/+dZpcn5yziu7VRwQAQDakwIm/bICYXbafnpHCYokV+PnEXqErnSdv6Eh28a+SRF+f3ndGcMsQ=="],
+
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
@@ -2595,6 +2598,12 @@
"mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
+ "motion": ["motion@14.2.0", "", { "dependencies": { "framer-motion": "14.2.0", "tslib": "^2.4.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-45cDwjZh0yOMZtnX3hIFPIPmzCWz/RC2bD/niWVIssGBjJlMmosbDILG9a+ZyoP635Z5xrbKvuo10spv9dBdnw=="],
+
+ "motion-dom": ["motion-dom@14.2.0", "", { "dependencies": { "motion-utils": "14.1.1" } }, "sha512-TDdxnjAavh2Qm4lQCQI3uoTx9IR/Id2PI8JNEXW3AcwwV2yvhoimAX3/TnE+x82gDHfPq2yx/cJ58TTw5mMr0A=="],
+
+ "motion-utils": ["motion-utils@14.1.1", "", {}, "sha512-3VvN5Uvf8B6qG+OfOui6Nht5EWp+vLuU3IqcAj7ItZGKqtmTjCebl5sGZF7/08gEHRnEl1AP/fIwbcEyVrcQGQ=="],
+
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
diff --git a/docs/apps/design/board/board.pen b/docs/apps/design/board/board.pen
index f85fc2c611..f0cc830e4a 100644
--- a/docs/apps/design/board/board.pen
+++ b/docs/apps/design/board/board.pen
@@ -535632,7 +535632,8 @@
"fill": "#60646c",
"content": "Summary comment",
"fontFamily": "Roboto",
- "fontSize": 14
+ "fontSize": 14,
+ "fontWeight": "normal"
},
{
"type": "frame",
@@ -538688,7 +538689,8 @@
"fill": "#60646c",
"content": "Inline comments",
"fontFamily": "Roboto",
- "fontSize": 14
+ "fontSize": 14,
+ "fontWeight": "normal"
},
{
"type": "frame",
@@ -568754,7 +568756,8 @@
"fill": "#1F2328",
"content": "Comment",
"fontFamily": "Inter",
- "fontSize": 14
+ "fontSize": 14,
+ "fontWeight": "normal"
},
{
"type": "text",
@@ -570728,7 +570731,8 @@
"fill": "#1F2328",
"content": "Comment",
"fontFamily": "Inter",
- "fontSize": 14
+ "fontSize": 14,
+ "fontWeight": "normal"
},
{
"type": "text",
@@ -572918,7 +572922,8 @@
"fill": "#1F2328",
"content": "Comment",
"fontFamily": "Inter",
- "fontSize": 14
+ "fontSize": 14,
+ "fontWeight": "normal"
},
{
"type": "text",
@@ -586729,488 +586734,31812 @@
]
}
]
- }
- ],
- "themes": {
- "mode": [
- "light",
- "dark"
- ]
- },
- "variables": {
- "bg": {
- "type": "color",
- "value": [
- {
- "value": "#f7f8fa",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#16161e",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "inset": {
- "type": "color",
- "value": [
- {
- "value": "#ffffff",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#1c2136",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "panel": {
- "type": "color",
- "value": [
- {
- "value": "#fbfbfc",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#232a47",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "card": {
- "type": "color",
- "value": [
- {
- "value": "#ffffff",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#2c3352",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "hover": {
- "type": "color",
- "value": [
- {
- "value": "#f0f4fb",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#242b48",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "fg": {
- "type": "color",
- "value": [
- {
- "value": "#222222",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#e3e7f6",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "muted": {
- "type": "color",
- "value": [
- {
- "value": "#565d80",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#969ec2",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "dim": {
- "type": "color",
- "value": [
- {
- "value": "#8990b3",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#7e86ad",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "border": {
- "type": "color",
- "value": [
- {
- "value": "#c8cad6",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#3b4261",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "border-soft": {
- "type": "color",
- "value": [
- {
- "value": "#d5d7e2",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#313853",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "accent": {
- "type": "color",
- "value": [
- {
- "value": "#2e7de9",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#7aa2f7",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "accent-text": {
- "type": "color",
- "value": [
- {
- "value": "#1c5fbf",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#7aa2f7",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "green": {
- "type": "color",
- "value": [
- {
- "value": "#587539",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#9ece6a",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "red": {
- "type": "color",
- "value": [
- {
- "value": "#c8214f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#f7768e",
- "theme": {
- "mode": "dark"
- }
- }
- ]
},
- "amber": {
- "type": "color",
- "value": [
- {
- "value": "#8c6c3e",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#e0af68",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "purple": {
- "type": "color",
- "value": [
- {
- "value": "#7847bd",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#bb9af7",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "cyan": {
- "type": "color",
- "value": [
- {
- "value": "#007197",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#7dcfff",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "dot-ok": {
- "type": "color",
- "value": [
- {
- "value": "#1f9d3a",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#4ade5b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "dot-warn": {
- "type": "color",
- "value": [
- {
- "value": "#e08a00",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#ffbb3d",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "dot-bad": {
- "type": "color",
- "value": [
- {
- "value": "#e5153f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#ff5c72",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "green-soft": {
- "type": "color",
- "value": [
- {
- "value": "#5875391f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#9ece6a2b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "red-soft": {
- "type": "color",
- "value": [
- {
- "value": "#c8214f1f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#f7768e2b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "amber-soft": {
- "type": "color",
- "value": [
- {
- "value": "#8c6c3e1f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#e0af682b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "purple-soft": {
- "type": "color",
- "value": [
- {
- "value": "#7847bd1f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#bb9af72b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "accent-soft": {
- "type": "color",
- "value": [
- {
- "value": "#2e7de91f",
- "theme": {
- "mode": "light"
- }
- },
- {
- "value": "#7aa2f72b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "cyan-soft": {
- "type": "color",
- "value": [
+ {
+ "type": "frame",
+ "id": "DOs6B",
+ "x": 14040,
+ "y": 25238,
+ "name": "B23 · Summary comment, cleaned up",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$bg",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
{
- "value": "#0071971f",
- "theme": {
- "mode": "light"
- }
+ "type": "text",
+ "id": "MnxK9",
+ "name": "Title",
+ "fill": "$fg",
+ "content": "B23 · Summary comment, cleaned up",
+ "fontFamily": "$font-sans",
+ "fontSize": 20,
+ "fontWeight": "700"
},
{
- "value": "#7dcfff2b",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "muted-soft": {
- "type": "color",
- "value": [
- {
- "value": "#565d801a",
- "theme": {
- "mode": "light"
- }
+ "type": "text",
+ "id": "SN8DT",
+ "name": "Description",
+ "fill": "$muted",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Today repeats the same chrome on every folded finding: a bot mark, \"no diff line\", Remove, Markdown supported and Write/Preview, four times over. The card also draws a double line on top. Each option keeps every feature (edit, reset, remove, preview) and cuts the repeats.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
},
{
- "value": "#969ec226",
- "theme": {
- "mode": "dark"
- }
- }
- ]
- },
- "font-sans": {
- "type": "string",
- "value": "Inter"
- },
- "font-mono": {
- "type": "string",
- "value": "JetBrains Mono"
- },
- "orange": {
- "type": "color",
- "value": [
- {
- "value": "#b15c00",
- "theme": {
+ "type": "frame",
+ "id": "CCyc8",
+ "name": "Row 1",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "g8sZS",
+ "name": "Today",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "u2qtb",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "XgxeP",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "Today",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "mR3K2",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "As built",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bcCc5",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "imqgv",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "tCNgn",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Oj22D",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L3cENf",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ecag5",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "nubmZ",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "i32DU",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "HRjhP",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$green-text"
+ },
+ {
+ "type": "text",
+ "id": "RTvUS",
+ "name": "Section name",
+ "fill": "$green-text",
+ "content": "Summary",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wDQGY",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "iv8V2",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "fHY9z",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "PA3Lx",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "h7XHar",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ozqJ4",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ePOIa",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "T1yKZ",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "GZZju",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "aYG6e",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FIOKf",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "YGodo",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W9Rmzh",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "u3zJap",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "DceQn",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "OJxFj",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "XRXhQ",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "k77M2",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zJnwo",
+ "name": "No diff line",
+ "fill": "$dim",
+ "content": "no diff line",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "f8XES",
+ "name": "Remove",
+ "gap": 4,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "tE7lf",
+ "name": "x",
+ "width": 12,
+ "height": 12,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ },
+ {
+ "type": "text",
+ "id": "b8r39",
+ "name": "Remove",
+ "fill": "$dim",
+ "content": "Remove",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JcirF",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "X2Q6QX",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "l5bYW",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ec5fJ",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "wALy1",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "RRyn4",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "A0Aedk",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "z1x47",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "f5gRZd",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rJtIA",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "WTs4N",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "w0MFy",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "n2JOl",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "GA288",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bsege",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ccdPD",
+ "name": "No diff line",
+ "fill": "$dim",
+ "content": "no diff line",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "AQBlc",
+ "name": "Remove",
+ "gap": 4,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "X5382L",
+ "name": "x",
+ "width": 12,
+ "height": 12,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ },
+ {
+ "type": "text",
+ "id": "dq7ii",
+ "name": "Remove",
+ "fill": "$dim",
+ "content": "Remove",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fsx8L",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "IIKzp",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "lmQb3",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ui5vl",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "f3zp0j",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O39crv",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JML2W",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yY3bR",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "WCFmJ",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O3n01",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "dsFKm",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "KienP",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "T6vLdC",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "CwTxt",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "README is out of step with the script",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KqpTp",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "GmHkC",
+ "name": "No diff line",
+ "fill": "$dim",
+ "content": "no diff line",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "PdwMR",
+ "name": "Remove",
+ "gap": 4,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "JXoBd",
+ "name": "x",
+ "width": 12,
+ "height": 12,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ },
+ {
+ "type": "text",
+ "id": "cHT7I",
+ "name": "Remove",
+ "fill": "$dim",
+ "content": "Remove",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mAehT",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "gkKpW",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** the `README.md` still says the scanner reads `src/jobs` (:42). anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about both?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WYsa3",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Uu9g2",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "nMIkz",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Sppk4",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "qlRZl",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "xbmbU",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "wbxXE",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rzpfD",
+ "name": "A · One footer, quiet heads",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Hw3Nu",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vnCoq",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "A · One footer, quiet heads",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "Sk7YP",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Same fields, chrome once",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "MtzBt",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ft3mp",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "Ut851",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "RPpwI",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "RUuGc",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "qjChV",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hUWuo",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hQTGH",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "VlSH2",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "VvBf6",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "E3Lu8j",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "E2d4ar",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "rrhyN",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "k5M9qm",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "na4S8",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "D3k1C",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yzlmv",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "n5B4E0",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Q0vayY",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "OT92F",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "b2J8Xl",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "rqkCI",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "z42fD",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "qEN71",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KoTOY",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "K9txdG",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XYfVt",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "y6OsR",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "U76DJ",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Y4YJ3v",
+ "name": "Section name",
+ "fill": "$muted",
+ "content": "README is out of step with the script",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vdgx7",
+ "name": "Meta",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "d03Fi9",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Y5kOrp",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "m5xKj",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** the `README.md` still says the scanner reads `src/jobs` (:42). anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about both?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WVufT",
+ "name": "Foot",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 16,
+ 10,
+ 24
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ks70k",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "O94BDY",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UO7Kv",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XN1Go",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "oGbIi",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "klF2B",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "xhg7R",
+ "name": "Row 2",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ugpPg",
+ "name": "B · Reads like the post",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "duu5g",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CzKkh",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "B · Reads like the post",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "sGsxm",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Fields frame on hover",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AL3wm",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "US1tg",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "O7Z3aB",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "V44Hh6",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "l6mOR",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "N8M5Zi",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Vz1N5",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Q2Un5x",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 8,
+ 8,
+ 6,
+ 8
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "x116ZU",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "#00000000",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "iKyPp",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kcJph",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 6,
+ 8
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Y0HWgV",
+ "name": "Title row",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 14
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "n6ekSe",
+ "name": "Finding title",
+ "fill": "$dim",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "idp1n",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "#00000000",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "vmbXR",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "T7MYl",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 6,
+ 8
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "NEDJV",
+ "name": "Title row",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 14
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Mk639",
+ "name": "Finding title",
+ "fill": "$dim",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "NasLl",
+ "name": "Remove",
+ "gap": 4,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "OdbHo",
+ "name": "x",
+ "width": 12,
+ "height": 12,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "Q0u9A",
+ "name": "Remove",
+ "fill": "$muted",
+ "content": "Remove",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZhyAd",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$hover",
+ "cornerRadius": 6,
+ "stroke": "$border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Rvoma",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UjjpG",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 6,
+ 8
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "y2dbS",
+ "name": "Title row",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 14
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Y9dWF",
+ "name": "Finding title",
+ "fill": "$dim",
+ "content": "README is out of step with the script",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O5CgzE",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "#00000000",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "pDF0f",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** the `README.md` still says the scanner reads `src/jobs` (:42). anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about both?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "n6qRY",
+ "name": "Foot",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 16,
+ 10,
+ 24
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CPf66",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "M9UbQ",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "K5e6F",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "iq6sk",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dR3CQ",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JspMA",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NIqA3",
+ "name": "C · Findings fold into rows",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Cd5zD",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "erfsX",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "C · Findings fold into rows",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "VpKSa",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "One open at a time",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "r2qO8",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Z4WPJ",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "Job79",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "jndfC",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "qwqO0",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "viIFY",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "g3THE",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "TPKHv",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "qqCuj",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "MwklQ",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Kg9NV",
+ "name": "Folded",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QMwjq",
+ "name": "Row",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 10,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "XQXeH",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ynTL8",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "EUGj0",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "fU0jr",
+ "name": "Peek",
+ "clip": true,
+ "width": "fill_container",
+ "height": 18,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "aYX2O",
+ "name": "Peek text",
+ "fill": "$dim",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/... would you mind grabbing one quick run of that?",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "icon",
+ "id": "f9s0r",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yL073",
+ "name": "Row",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 10,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Zrgsd",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "IyHSm",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "QzlAr",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "pGipM",
+ "name": "Peek",
+ "clip": true,
+ "width": "fill_container",
+ "height": 18,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ULuOk",
+ "name": "Peek text",
+ "fill": "$dim",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "icon",
+ "id": "upSRa",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "K8yc0k",
+ "name": "Row",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 10,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "KJ8Af",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "jyhYw",
+ "name": "chevron-down",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$muted"
+ },
+ {
+ "type": "text",
+ "id": "AoNez",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "README is out of step with the script",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "rZ05J",
+ "name": "Peek",
+ "clip": true,
+ "width": "fill_container",
+ "height": 18,
+ "alignItems": "center"
+ },
+ {
+ "type": "icon",
+ "id": "Z53Dp",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vY504",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "dGrEi",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** the `README.md` still says the scanner reads `src/jobs` (:42). anyone with a local overlay keyed on the old paths will get `merged 0/N` with no hint why. could we add a line about both?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UMIVY",
+ "name": "Foot",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 16,
+ 10,
+ 24
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "S3Rx0T",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "s915q",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "SoBwb",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Hyq3z",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "jb6dr",
+ "name": "Preview",
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "uSmA3",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HPZSl",
+ "x": 14040,
+ "y": 26738,
+ "name": "B24 · No-diff-line findings stay inline",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$bg",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "ht39A",
+ "name": "Title",
+ "fill": "$fg",
+ "content": "B24 · No-diff-line findings stay inline",
+ "fontFamily": "$font-sans",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "aREum",
+ "name": "Description",
+ "fill": "$muted",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "A finding with no diff line keeps its comment in its own card, like every other finding, tagged \"posts in summary\". The summary card holds only the summary line. Preview shows the whole comment as it posts: the summary line, then each ticked no-diff-line comment.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "CcfqZ",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "aMW1g",
+ "name": "Write",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "WylIB",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Z2qjJf",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "vd2Eo",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Comments edit in their cards",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ici1V",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "MMUmR",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "J88JzX",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "abOWm",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Sg84G",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "RG5Nk",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FEuqh",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "rmy70",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "PwKfm",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "W3BGx",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Ukgbu",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "xWOvL",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "IkjXi",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Rwo9h",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "vCjco",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NgcCZ",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "QCRvT",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "jHAv6",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "g0hHl",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ckHRz",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Findings",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "NXt2u",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CdBmx",
+ "name": "Tally",
+ "fill": "$dim",
+ "content": "2 of 2 selected",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "uIKDp",
+ "name": "Tier head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "b6DVKE",
+ "name": "Tier pill",
+ "fill": "$muted-soft",
+ "cornerRadius": 10,
+ "padding": [
+ 2,
+ 8
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "QhcDJ",
+ "name": "Tier",
+ "fill": "$muted",
+ "content": "Minor (2)",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "600"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XT8Qr",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "o3huj",
+ "name": "all",
+ "fill": "$dim",
+ "content": "all",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "G7PC2",
+ "name": "sep",
+ "fill": "$dim",
+ "content": "·",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "y4r69f",
+ "name": "none",
+ "fill": "$fg",
+ "content": "none",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "u4UYCp",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "xC9KP",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Eu6V5",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Ge44l",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "YqQgD",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fubER",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Dnw1d",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "igL2g",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "BTCgP",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$accent-text"
+ },
+ {
+ "type": "text",
+ "id": "kDdRU",
+ "name": "Section name",
+ "fill": "$accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "DRsCn",
+ "name": "Body",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/ has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yUJLm",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "ITalX",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "mXkD9",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "lFvHD",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$green-text"
+ },
+ {
+ "type": "text",
+ "id": "S1XeWq",
+ "name": "Section name",
+ "fill": "$green-text",
+ "content": "Comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "B9Efq",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "r1cTVN",
+ "name": "Where",
+ "fill": "$dim",
+ "content": "posts in summary",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "aD5xs",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "yZjFt",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Sgafr",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "D9MTg",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "udjaA",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "s7DyX4",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "n0KIF",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "v77h9",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "I2r5U",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "BrfTK",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "S6z6L",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "XfTKf",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "XW458",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "O80It7",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "IZqrI",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "bfSgk",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "qNOuu",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "K9RvyM",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$accent-text"
+ },
+ {
+ "type": "text",
+ "id": "L74xc1",
+ "name": "Section name",
+ "fill": "$accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "O7Ro3y",
+ "name": "Body",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Comments in scan-jobs.ts still describe the old single folder, and stats.reachableInJobs now counts both.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "M2vz9",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Xb8j8",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "IKXAU",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Toaf4",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$green-text"
+ },
+ {
+ "type": "text",
+ "id": "br3MI",
+ "name": "Section name",
+ "fill": "$green-text",
+ "content": "Comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "v6iYZ",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "n2I8Wx",
+ "name": "Where",
+ "fill": "$dim",
+ "content": "posts in summary",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vZbc2",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XXJFH",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "odpYN",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "r3jOc",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "m7MNNi",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "k5aV0",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "czGGx",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qLhUw",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "MWgsS",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fti2z",
+ "name": "Summary in preview",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Zve9D",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "YMEE9",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "Summary in preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "P4yNMm",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "The whole comment as it posts",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "F7NbC",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "FxJ8g",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Summary comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "YSlyc",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "mr6lw",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "c6U2R",
+ "name": "Chip text",
+ "fill": "$accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "$font-sans",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "p3dwV",
+ "name": "Posts on",
+ "fill": "$dim",
+ "content": "posts on !1182",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZicbB",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "s0uzhR",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "h9bxzf",
+ "name": "Rendered",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Axe4W",
+ "name": "P summary",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "YspDl",
+ "name": "P folded",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "bywY2",
+ "name": "P folded",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "p7SZq",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "bQIGE",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "C7ga1r",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "nuIGm",
+ "name": "Write",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "cnLEC",
+ "name": "Write",
+ "fill": "$dim",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CODgS",
+ "name": "Preview",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "zv41E",
+ "name": "Preview",
+ "fill": "$fg",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KrdPq",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "FOeAT",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "f9k6zQ",
+ "name": "List title",
+ "fill": "$fg",
+ "content": "Findings",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "mvWYU",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "epf9G",
+ "name": "Tally",
+ "fill": "$dim",
+ "content": "2 of 2 selected",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eAEjJ",
+ "name": "Tier head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "uLb10",
+ "name": "Tier pill",
+ "fill": "$muted-soft",
+ "cornerRadius": 10,
+ "padding": [
+ 2,
+ 8
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Qiamx",
+ "name": "Tier",
+ "fill": "$muted",
+ "content": "Minor (2)",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "600"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "npuRp",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "ERPhZ",
+ "name": "all",
+ "fill": "$dim",
+ "content": "all",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "nhkln",
+ "name": "sep",
+ "fill": "$dim",
+ "content": "·",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "lWU3M",
+ "name": "none",
+ "fill": "$fg",
+ "content": "none",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Yt9YN",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ghPTe",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ZrtOF",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "H2dQVJ",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "KVa0C",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zJvtq",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "fjTd5",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "h7Q5kq",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "a1pdf",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$accent-text"
+ },
+ {
+ "type": "text",
+ "id": "bvLM2",
+ "name": "Section name",
+ "fill": "$accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Bn8pd",
+ "name": "Body",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/ has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "uRJqC",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "T8Fayr",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "x371D",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "mKG3o",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$green-text"
+ },
+ {
+ "type": "text",
+ "id": "nX5vt",
+ "name": "Section name",
+ "fill": "$green-text",
+ "content": "Comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ojQCp",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "DlH1F",
+ "name": "Where",
+ "fill": "$dim",
+ "content": "posts in summary",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "pbiLc",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XpYIb",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cj0Uf",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "UOF5w",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "o6zaZV",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "SIEL0",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "L392m0",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UezeH",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "bVGx4",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "x83DOX",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "rPJVu",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "nXSOZ",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ucMrW",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "zx3ZI",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LYiIX",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "dRPYr",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "gWX5u",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "g2CAQr",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$accent-text"
+ },
+ {
+ "type": "text",
+ "id": "UAHej",
+ "name": "Section name",
+ "fill": "$accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "oQ8OZ",
+ "name": "Body",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Comments in scan-jobs.ts still describe the old single folder, and stats.reachableInJobs now counts both.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "l9M81",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "q9EsX2",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "IfckX",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Mq8Eu",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$green-text"
+ },
+ {
+ "type": "text",
+ "id": "eBNey",
+ "name": "Section name",
+ "fill": "$green-text",
+ "content": "Comment",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SUgqq",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "F8hlT7",
+ "name": "Where",
+ "fill": "$dim",
+ "content": "posts in summary",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "piXpT",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 6,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "G2DgQS",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SmbFr",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "yOdqc",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "jBxR5",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "G6Na85",
+ "name": "Write",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "uqQiX",
+ "name": "Write",
+ "fill": "$fg",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Gp2JD",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "SeD2E",
+ "name": "Preview",
+ "fill": "$dim",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Vkp1N",
+ "x": 16000,
+ "y": 26738,
+ "name": "B25 · Summary preview, finding cues",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$bg",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "gdI4l",
+ "name": "Title",
+ "fill": "$fg",
+ "content": "B25 · Summary preview, finding cues",
+ "fontFamily": "$font-sans",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "JMtSt",
+ "name": "Description",
+ "fill": "$muted",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The summary in preview (B24), with a left-side cue on each paragraph that comes from a finding below. The summary line itself carries none. Hovering a cued paragraph could highlight its finding card.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "vP3se",
+ "name": "Row 1",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "i4HDaP",
+ "name": "1 · Stripe",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "QsrQh",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Va2Ke",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "1 · Stripe",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "Y9MYi",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Thin square bar",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zDlQN",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "z92Rs",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "R4Pu2",
+ "name": "Rendered",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 10,
+ 14,
+ 10,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "yMM9O",
+ "name": "Summary line",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "dpECQ",
+ "name": "Gutter",
+ "width": 28,
+ "height": 1,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center"
+ },
+ {
+ "type": "text",
+ "id": "ZOj63",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UyR9k",
+ "name": "Folded 1",
+ "width": "fill_container",
+ "stroke": "$border-on-card",
+ "strokeWidth": {
+ "left": 2
+ },
+ "children": [
+ {
+ "type": "frame",
+ "id": "EQAL6",
+ "name": "Gutter",
+ "width": 26,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "jLp05",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/**... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "as94h",
+ "name": "Folded 2",
+ "width": "fill_container",
+ "stroke": "$border-on-card",
+ "strokeWidth": {
+ "left": 2
+ },
+ "children": [
+ {
+ "type": "frame",
+ "id": "Oy7R9",
+ "name": "Gutter",
+ "width": 26,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "f1wPzb",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SK3sd",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "FgfkJ",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "B5nCR",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "pSYFr",
+ "name": "Write",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "A7Za8w",
+ "name": "Write",
+ "fill": "$dim",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yvOF5",
+ "name": "Preview",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "n0qmP2",
+ "name": "Preview",
+ "fill": "$fg",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FffAD",
+ "name": "2 · Agent glyph",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "VLHAa",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "s2DJy",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "2 · Agent glyph",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "dFT8i",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "The findings' own mark",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "jhj88",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hYxfL",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "JMoB2",
+ "name": "Rendered",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 10,
+ 14,
+ 10,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "fre78",
+ "name": "Summary line",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "m4Hnwm",
+ "name": "Gutter",
+ "width": 28,
+ "height": 1,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center"
+ },
+ {
+ "type": "text",
+ "id": "a7irvk",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "w4FMWg",
+ "name": "Folded 1",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "JsjYL",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "t2zOy",
+ "name": "bot",
+ "width": 13,
+ "height": 13,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "h6n9eh",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/**... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "N43EO",
+ "name": "Folded 2",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "P2BzKz",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "psTNt",
+ "name": "bot",
+ "width": 13,
+ "height": 13,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "yNOTq",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bWdYo",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "S1DHQD",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "st5Ff",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "E6ikJ",
+ "name": "Write",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Ain60",
+ "name": "Write",
+ "fill": "$dim",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GwO4A",
+ "name": "Preview",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Z8dE6",
+ "name": "Preview",
+ "fill": "$fg",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "knvlE",
+ "name": "Row 2",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "vVduX",
+ "name": "3 · Numbered",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "HXc37",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "OlxI2",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "3 · Numbered",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "scEhw",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Matches a number on the card",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JD0tZ",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "YbOAA",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "itRaL",
+ "name": "Rendered",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 10,
+ 14,
+ 10,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "gaeRn",
+ "name": "Summary line",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hWhrt",
+ "name": "Gutter",
+ "width": 28,
+ "height": 1,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center"
+ },
+ {
+ "type": "text",
+ "id": "WgmzG",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eLYux",
+ "name": "Folded 1",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UOPN0",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "c2dVW",
+ "name": "Badge",
+ "width": 18,
+ "height": 18,
+ "fill": "$muted-soft",
+ "cornerRadius": 9,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "gfJBN",
+ "name": "n",
+ "fill": "$muted",
+ "content": "1",
+ "fontFamily": "$font-sans",
+ "fontSize": 11,
+ "fontWeight": "600"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "BGbxI",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/**... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ymDhI",
+ "name": "Folded 2",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "jo61s",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "nDIaq",
+ "name": "Badge",
+ "width": 18,
+ "height": 18,
+ "fill": "$muted-soft",
+ "cornerRadius": 9,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "O2YVAh",
+ "name": "n",
+ "fill": "$muted",
+ "content": "2",
+ "fontFamily": "$font-sans",
+ "fontSize": 11,
+ "fontWeight": "600"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "g6vggG",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JP6g8",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "koZD4",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "GzxhJ",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Lgnko",
+ "name": "Write",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "DzeiL",
+ "name": "Write",
+ "fill": "$dim",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "I29UYp",
+ "name": "Preview",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "oDxN7",
+ "name": "Preview",
+ "fill": "$fg",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AZnIH",
+ "name": "Finding card heads",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Gb97G",
+ "name": "Card head",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "iBFrp",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ZW1mf",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "d6iEwz",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "hcgdU",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "cLCNx",
+ "name": "Badge",
+ "width": 18,
+ "height": 18,
+ "fill": "$muted-soft",
+ "cornerRadius": 9,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "FhtXA",
+ "name": "n",
+ "fill": "$muted",
+ "content": "1",
+ "fontFamily": "$font-sans",
+ "fontSize": 11,
+ "fontWeight": "600"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "sonIt",
+ "name": "Card head",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "J5vilI",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "KdtpE",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "ems7h",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "Stale comments and a stale stat name",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "D4NRm3",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "z6zBB",
+ "name": "Badge",
+ "width": 18,
+ "height": 18,
+ "fill": "$muted-soft",
+ "cornerRadius": 9,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "WRh6f",
+ "name": "n",
+ "fill": "$muted",
+ "content": "2",
+ "fontFamily": "$font-sans",
+ "fontSize": 11,
+ "fontWeight": "600"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Vajy3",
+ "name": "4 · Glyph + hover link",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Uvr70",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "lmMOv",
+ "name": "Label",
+ "fill": "$fg",
+ "content": "4 · Glyph + hover link",
+ "fontFamily": "$font-sans",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "ApAP7",
+ "name": "Note",
+ "fill": "$dim",
+ "content": "Hover finds the card",
+ "fontFamily": "$font-sans",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "uiakN",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "PAGbL",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "fy5V5",
+ "name": "Rendered",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 10,
+ 14,
+ 10,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "vqCaY",
+ "name": "Summary line",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "CLIrH",
+ "name": "Gutter",
+ "width": 28,
+ "height": 1,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center"
+ },
+ {
+ "type": "text",
+ "id": "NoO1S",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KOoFv",
+ "name": "Folded 1",
+ "width": "fill_container",
+ "fill": "$hover",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ToOiw",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "LBHcl",
+ "name": "bot",
+ "width": 13,
+ "height": 13,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "xfFmb",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/**... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JMMEP",
+ "name": "Folded 2",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "d35CUO",
+ "name": "Gutter",
+ "width": 28,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "HOrMv",
+ "name": "bot",
+ "width": 13,
+ "height": 13,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$dim"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "E5bEg",
+ "name": "Text",
+ "fill": "$fg",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EQlgU",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Hp2DB",
+ "name": "Md",
+ "fill": "$dim",
+ "content": "Markdown supported",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "JzaTQ",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "BCeFT",
+ "name": "Write",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "lN2G3",
+ "name": "Write",
+ "fill": "$dim",
+ "content": "Write",
+ "fontFamily": "$font-sans",
+ "fontSize": 12
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "VLPQ9",
+ "name": "Preview",
+ "fill": "$muted-soft",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "nwhen",
+ "name": "Preview",
+ "fill": "$fg",
+ "content": "Preview",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U562A",
+ "name": "Linked card head",
+ "width": "fill_container",
+ "fill": "$card",
+ "cornerRadius": 8,
+ "stroke": "$accent",
+ "strokeWidth": 1,
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "sEXps",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$accent",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "jK3CG",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "YoqKf",
+ "name": "Finding title",
+ "fill": "$fg",
+ "content": "No run for the --changed flag",
+ "fontFamily": "$font-sans",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "c9wXo",
+ "name": "Hover note",
+ "fill": "$dim",
+ "content": "Hover lights its card",
+ "fontFamily": "$font-sans",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "IDT2N",
+ "x": 17960,
+ "y": 26738,
+ "name": "B26 · Summary built from borderless fields",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$ui-page",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "ulO7q",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B26 · Summary built from borderless fields",
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "tnOQZ",
+ "name": "Description",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The summary card in Write: one borderless field per part, so it reads as the one comment GitLab will show. A comment from a finding keeps a left stripe that grows with its text and turns green while you edit. The same comment also edits in its finding card below; both stay in sync.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "R4uzb",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "IiRTC",
+ "name": "At rest",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Sggqm",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "f3lan",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "At rest",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "qFaiw",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Reads as one comment",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "m6CIaV",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "K49YOI",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "DoCSb",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "TILgB",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "mTclP",
+ "name": "Chip text",
+ "fill": "$ui-accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "CXtGc",
+ "name": "Posts on",
+ "fill": "$ui-text-3",
+ "content": "posts on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rfY8A",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ZcVr5",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "ELpUf",
+ "name": "Fields",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 4,
+ 0,
+ 6,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "JxK0V",
+ "name": "Summary field",
+ "width": "fill_container",
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12,
+ 2,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "g3Ng9",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "C5dib",
+ "name": "Folded field 1",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "E70Gj",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YZSfU",
+ "name": "Folded field 2",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Y0Xk4",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "p9DxsH",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "szq6q",
+ "name": "Md",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "pu6PZ",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "CdKux",
+ "name": "Write",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "RPU5J",
+ "name": "Write",
+ "fill": "$ui-text-1",
+ "content": "Write",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "p14oxL",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "b3Vemq",
+ "name": "Preview",
+ "fill": "$ui-text-3",
+ "content": "Preview",
+ "fontFamily": "Inter",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qbtFp",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "Bw5Uk",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "DTeCa",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Findings",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "zr7JM",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vlOlP",
+ "name": "Tally",
+ "fill": "$ui-text-3",
+ "content": "2 of 2 selected",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "g5XkrI",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QZ6HM",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "mCyOu",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "w35rYR",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "vHdGK",
+ "name": "Finding title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "sO7de",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "VVjTp",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ytXUi",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Mojee",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-accent-text"
+ },
+ {
+ "type": "text",
+ "id": "rh5CS",
+ "name": "Section name",
+ "fill": "$ui-accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "m6sRF",
+ "name": "Body",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/ has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CldR8",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "iu9zW",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "jJcuT",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "bO7Vg",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$ui-ok-text"
+ },
+ {
+ "type": "text",
+ "id": "WBABv",
+ "name": "Section name",
+ "fill": "$ui-ok-text",
+ "content": "Comment",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o1dAv",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "nRlBR",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "posts in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Gu307",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "PJmL6",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "aepqg",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "jBp1W",
+ "name": "Md",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "r8yjz",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "a9m6VP",
+ "name": "Write",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "eoYfP",
+ "name": "Write",
+ "fill": "$ui-text-1",
+ "content": "Write",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "G3Xq3",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "yrmWx",
+ "name": "Preview",
+ "fill": "$ui-text-3",
+ "content": "Preview",
+ "fontFamily": "Inter",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UdU5L",
+ "name": "Editing in the summary",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "l3LIv",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "xAQDe",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "Editing in the summary",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "H3VfYB",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Stripe turns green",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "j20MJn",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ex4gy",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "hXfVA",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "OFTNZ",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JTLOO",
+ "name": "Chip text",
+ "fill": "$ui-accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "BqLAn",
+ "name": "Posts on",
+ "fill": "$ui-text-3",
+ "content": "posts on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "akRME",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Qo3Z7",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "epZM2",
+ "name": "Fields",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 4,
+ 0,
+ 6,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "xCMf9",
+ "name": "Summary field",
+ "width": "fill_container",
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12,
+ 2,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "PwFkv",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "f55ZH",
+ "name": "Folded field 1",
+ "width": "fill_container",
+ "stroke": "$ui-ok-text",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "lYJ98",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dnXLa",
+ "name": "Folded field 2",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "j3zSF",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bIDbR",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Suuh6",
+ "name": "Md",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "TMZ5t",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UnyVe",
+ "name": "Write",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "d2wRlS",
+ "name": "Write",
+ "fill": "$ui-text-1",
+ "content": "Write",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L3HpQJ",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JKwFb",
+ "name": "Preview",
+ "fill": "$ui-text-3",
+ "content": "Preview",
+ "fontFamily": "Inter",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "l4wSyo",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "ijC6e",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "b5RFuB",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Findings",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "WBcVa",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Gm7fY",
+ "name": "Tally",
+ "fill": "$ui-text-3",
+ "content": "2 of 2 selected",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "VombD",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "U3q2a",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "MbFh1",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "wnVjZ",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "q5iCA",
+ "name": "Finding title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "G0qujZ",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "aOBW7",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "J0mvo",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ZdSuu",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-accent-text"
+ },
+ {
+ "type": "text",
+ "id": "N5IvU",
+ "name": "Section name",
+ "fill": "$ui-accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "R21sAm",
+ "name": "Body",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/ has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wCLwu",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "cAkEk",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "M3GKI",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "s2N8yl",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$ui-ok-text"
+ },
+ {
+ "type": "text",
+ "id": "hipwA",
+ "name": "Section name",
+ "fill": "$ui-ok-text",
+ "content": "Comment",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cwlZz",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "POKS4",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "editing in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eRsjE",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "vjZrt",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o8OEY",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "L9KPK",
+ "name": "Md",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "J6IJq",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "riHmA",
+ "name": "Write",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "k2zfMt",
+ "name": "Write",
+ "fill": "$ui-text-1",
+ "content": "Write",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Huap8",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "cMamj",
+ "name": "Preview",
+ "fill": "$ui-text-3",
+ "content": "Preview",
+ "fontFamily": "Inter",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LkE44",
+ "name": "Row 2",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "J7SzoV",
+ "name": "Editing the summary line",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "OlAFq",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "bVJMi",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "Editing the summary line",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "oTWL0",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Stripe shows on focus only",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D5TJhP",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "k605s",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "oYh9e",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "H6HNy6",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "N9vWpo",
+ "name": "Chip text",
+ "fill": "$ui-accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "KxXAx",
+ "name": "Posts on",
+ "fill": "$ui-text-3",
+ "content": "posts on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KB7rB",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "pjJuS",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "NnkXi",
+ "name": "Fields",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 4,
+ 0,
+ 6,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "a3hbr",
+ "name": "Summary field",
+ "width": "fill_container",
+ "stroke": "$ui-ok-text",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Tt3Ik",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the `retryPolicy` one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "F8EHh",
+ "name": "Folded field 1",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "KeB8j",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "a5KJB",
+ "name": "Folded field 2",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "lK0W8",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**nitpick:** a few comments in `scan-jobs.ts` still describe the old single folder: `JobRow.path` (:88) says it's relative to `src/jobs/`. `stats.reachableInJobs` (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "pu6Gx",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 8
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "cHSlq",
+ "name": "Md",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "gNoHG",
+ "name": "Tabs",
+ "gap": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Q4Y3bV",
+ "name": "Write",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "lHKFB",
+ "name": "Write",
+ "fill": "$ui-text-1",
+ "content": "Write",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "G6OtTx",
+ "name": "Preview",
+ "cornerRadius": 4,
+ "padding": [
+ 3,
+ 7
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Vhv30",
+ "name": "Preview",
+ "fill": "$ui-text-3",
+ "content": "Preview",
+ "fontFamily": "Inter",
+ "fontSize": 12
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "TNJ7P",
+ "x": 17960,
+ "y": 27896,
+ "name": "B27 · Preview at rest, click to edit",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$ui-page",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "jTl15",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B27 · Preview at rest, click to edit",
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "q9Vch",
+ "name": "Description",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "No Write/Preview toggle anywhere. Every comment shows rendered at rest; a click on its text opens the raw markdown with the caret where you clicked. Leaving the field, or Escape, renders it again. \"Markdown supported\" shows only while editing.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "bTDqo",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Q2PcM",
+ "name": "At rest",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "T6Z9X",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "dsOJV",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "At rest",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "sh7Xp",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Every comment rendered",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FNaa5",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "amcWM",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "Dir7u",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "LLiX2",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "feSXr",
+ "name": "Chip text",
+ "fill": "$ui-accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "OFFFZ",
+ "name": "Posts on",
+ "fill": "$ui-text-3",
+ "content": "posts on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zdwJI",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "GgKiK",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "gzfsb",
+ "name": "Fields",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 4,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "QVjug",
+ "name": "Summary field",
+ "width": "fill_container",
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12,
+ 2,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "vLyHb",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ar8wO",
+ "name": "Folded field 1",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "D9QIlW",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "w7dCAw",
+ "name": "Folded field 2",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "aDljT",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NsZVk",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "gxt5L",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vt6it",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Findings",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "eeoxT",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "k82rEl",
+ "name": "Tally",
+ "fill": "$ui-text-3",
+ "content": "2 of 2 selected",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mM3i8",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "G7y4Ic",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Llv72",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "XZo0I",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "bgCjC",
+ "name": "Finding title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dlEoz",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "a2UvpC",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "M61Ys",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "s2PFf",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-accent-text"
+ },
+ {
+ "type": "text",
+ "id": "MebxE",
+ "name": "Section name",
+ "fill": "$ui-accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "OshJv",
+ "name": "Body",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/** has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "S6e9RE",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "i5R06P",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hJFo8",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "EFi1A",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$ui-ok-text"
+ },
+ {
+ "type": "text",
+ "id": "HzwGU",
+ "name": "Section name",
+ "fill": "$ui-ok-text",
+ "content": "Comment",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vddpZ",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "A9rktl",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "posts in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Cbkf5",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "N7MxHv",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "R1d92",
+ "name": "Clicked into a comment",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "N7k6E",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "N2wuHp",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "Clicked into a comment",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "bfcXb",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Raw markdown, caret at the click",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EE0Dv",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Hp9vE",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "AifIc",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "lNg6o",
+ "name": "Verdict chip",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "padding": [
+ 2,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XrdVi",
+ "name": "Chip text",
+ "fill": "$ui-accent-text",
+ "content": "FOR COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "t7i4E",
+ "name": "Posts on",
+ "fill": "$ui-text-3",
+ "content": "posts on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "z8jYBg",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ljXib",
+ "name": "Section",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "YIWTt",
+ "name": "Fields",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 4,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "cKOv3",
+ "name": "Summary field",
+ "width": "fill_container",
+ "layout": "vertical",
+ "padding": [
+ 2,
+ 12,
+ 2,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "q0W2ej",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the retryPolicy one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "STb7O",
+ "name": "Folded field 1",
+ "width": "fill_container",
+ "stroke": "$ui-ok-text",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "KBaVQ",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "**suggestion:** thanks for the extra evidence, that covers it nicely. the one AC without a run is `--changed` picking up a file under `src/jobs/**`... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DOsm9",
+ "name": "Folded field 2",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 2
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 2,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "GQhKh",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "nitpick: a few comments in scan-jobs.ts still describe the old single folder: JobRow.path (:88) says it's relative to src/jobs/. stats.reachableInJobs (:140) counts both folders now too, so maybe rename it?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UHZQE",
+ "name": "Foot",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 0,
+ 0,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "U2b5o",
+ "name": "Md hint",
+ "fill": "$ui-text-3",
+ "content": "Markdown supported",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "V38cv",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": 6
+ },
+ {
+ "type": "frame",
+ "id": "lGCYH",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Y4Fqxj",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Findings",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "uM8Yy",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "N6djP",
+ "name": "Tally",
+ "fill": "$ui-text-3",
+ "content": "2 of 2 selected",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mQLDF",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "tTn6T",
+ "name": "Card head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Al7sX",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "SfJYf",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "n4x9nn",
+ "name": "Finding title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ecwlo",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "KimHn",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "a5NwUG",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "A3hnug",
+ "name": "bot",
+ "width": 14,
+ "height": 14,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-accent-text"
+ },
+ {
+ "type": "text",
+ "id": "GoyW3",
+ "name": "Section name",
+ "fill": "$ui-accent-text",
+ "content": "Agent Finding",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "CFkN9",
+ "name": "Body",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The AC for --changed on files under src/jobs/** has no run in the evidence.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YvOvl",
+ "name": "Section",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16,
+ 14,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Ttglk",
+ "name": "Section head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "fazrU",
+ "name": "Name",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "h96QvH",
+ "name": "message-square",
+ "width": 14,
+ "height": 14,
+ "icon": "message-square",
+ "library": "lucide",
+ "fill": "$ui-ok-text"
+ },
+ {
+ "type": "text",
+ "id": "jfusm",
+ "name": "Section name",
+ "fill": "$ui-ok-text",
+ "content": "Comment",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HI8hq",
+ "name": "Meta",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "hVoUG",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "editing in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "f7wZj",
+ "name": "Field",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "vYeMI",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: thanks for the extra evidence, that covers it nicely. the one AC without a run is --changed picking up a file under src/jobs/... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "I4qTC",
+ "x": 17960,
+ "y": 28728,
+ "name": "B28 · Where the re-review ask lives",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1840,
+ "fill": "$ui-page",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "VJwRC",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B28 · Where the re-review ask lives",
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "n2XDXz",
+ "name": "Description",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Today the re-review ask is a checkbox under the last thread card, below the fold and far from the post button. The ask happens after posting, so each option puts it beside what posts: in the dock's list, in the button, or on the reviewer's own thread.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "MWLWZ",
+ "name": "Row 1",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "G1c7n",
+ "name": "Today",
+ "width": 420,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "MrfsW",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "K91oQ",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "Today",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "XhFK6",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Under the last card",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vyRfm",
+ "name": "Main bottom",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 8,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 16
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "MwG29",
+ "name": "ctx",
+ "fill": "$ui-text-3",
+ "content": "…last thread card",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "jP0pm",
+ "name": "h",
+ "fill": "$ui-text-3",
+ "content": "Re-review",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "g2fBt",
+ "name": "Re-review tick",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "o1NwUi",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "BjfWg",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "GqfwH",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "content": "Ask Pat for a re-review once posting finishes",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Zbk5q",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 10,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "uMvA5",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "h9c0Mg",
+ "name": "Heading",
+ "fill": "$ui-text-1",
+ "content": "Replies on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "xVFz3",
+ "name": "reset",
+ "fill": "$ui-text-3",
+ "content": "reset",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U3TT4g",
+ "name": "Rows",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ZzlB1",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "KwKMs",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "F3GId",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZV90W",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "aRsS4",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "r5E4Hy",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:88",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ofbXX",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Qy8Tz",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "RTNIV",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EDXSM",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "AhYuG",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "y8l51Y",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:140",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Hdprn",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "lr5qG",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "hKxp1",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CsSrs",
+ "name": "slot",
+ "width": 58,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "qKi3q",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XlMKd",
+ "name": "Submit",
+ "width": "fill_container",
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 10,
+ 16
+ ],
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O3SylI",
+ "name": "Line",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "i6WpAB",
+ "name": "Label",
+ "fill": "#ffffff",
+ "content": "post 3 · resolve 2",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "RSP0B",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "NzVpW",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KS7sQ",
+ "name": "A · A row in the dock",
+ "width": 420,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "CplDU",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ftuf7",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "A · A row in the dock",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "wEVMW",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Listed with what posts",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "BEl7o",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 10,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "dJMo3",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "VAm8c",
+ "name": "Heading",
+ "fill": "$ui-text-1",
+ "content": "Replies on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "co3Le",
+ "name": "reset",
+ "fill": "$ui-text-3",
+ "content": "reset",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NspsT",
+ "name": "Rows",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "A2uwPP",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "THqlO",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "maP02",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NEgbV",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "F0Ib32",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Q6zmuu",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:88",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "IDxb9",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "L0jeZ",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "UlJGq",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "xg5uw",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "o03FAn",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "jrVx9",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:140",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rcvh0",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UHvIe",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "KBANw",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "odYCh",
+ "name": "slot",
+ "width": 58,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "gk37a",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SyDcL",
+ "name": "Re-review row",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 0,
+ 0,
+ 0
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "wyQ2R",
+ "name": "Chip re-review",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "TeNTb",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RE-REVIEW",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "gVpJU",
+ "name": "Who",
+ "fill": "$ui-text-3",
+ "content": "ask Pat after posting",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "IYW5d",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "MDWbf",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "bY6r2",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "l55e2",
+ "name": "Submit",
+ "width": "fill_container",
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 10,
+ 16
+ ],
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "XCHr0",
+ "name": "Line",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "KpBLR",
+ "name": "Label",
+ "fill": "#ffffff",
+ "content": "post 3 · resolve 2",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "ZKtKQ",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "NPjbU",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ypsEg",
+ "name": "B · Rides the button",
+ "width": 420,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Im5Z9",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "a1JTt",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "B · Rides the button",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "clnIk",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "One decision, one place",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o60eJ",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 10,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "S486Ij",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "wykYt",
+ "name": "Heading",
+ "fill": "$ui-text-1",
+ "content": "Replies on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "ZJuTh",
+ "name": "reset",
+ "fill": "$ui-text-3",
+ "content": "reset",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iMPQg",
+ "name": "Rows",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "vTvQ0",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "uQLU1",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "DAwA4",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qbyM5",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "I9qBL",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "CRWAp",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:88",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SVBlV",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "FH6Iq",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "q38pq",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "a39xn",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "SRrvJ",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "o4O6tB",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:140",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "g3cu7q",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "uIkGF",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "oiQcM",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "syoxv",
+ "name": "slot",
+ "width": 58,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "MBJU8",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "y2FBfD",
+ "name": "Re-review tick",
+ "gap": 8,
+ "padding": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "CUolo",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "zFYWQ",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "V3X73",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "content": "Ask Pat to re-review after posting",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Q8slf",
+ "name": "Submit",
+ "width": "fill_container",
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 10,
+ 16
+ ],
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "C2JWMj",
+ "name": "Line",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Rw1yT",
+ "name": "Label",
+ "fill": "#ffffff",
+ "content": "post 3 · resolve 2",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "x6NVI6",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "AWZ3J",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "EzIW0",
+ "name": "Sub",
+ "fill": "#ffffffcc",
+ "content": "then ask Pat to re-review",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o7NwR",
+ "name": "B2 · Split button",
+ "width": 420,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "LBOP2",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "yajJj",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "B2 · Split button",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "sn4ak",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Two ways to post",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "gLIsU",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 10,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "p3M4I",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "M1b1uT",
+ "name": "Heading",
+ "fill": "$ui-text-1",
+ "content": "Replies on !1182",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "qr5m6",
+ "name": "reset",
+ "fill": "$ui-text-3",
+ "content": "reset",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nLfsW",
+ "name": "Rows",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "tVu6a",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Phz3z",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "UqNFk",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "P0pmLo",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XaXpT",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "erGPp",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:88",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W0YZPQ",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "F2HmK9",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "pEecF",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WENCs",
+ "name": "Chip resolve",
+ "cornerRadius": 4,
+ "stroke": "$ui-accent-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "rZKWB",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "RESOLVE",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "i18cu",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:140",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qB4aO",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UPuKf",
+ "name": "Chip post",
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "T0Hb8",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "POST",
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "500",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HawQ2",
+ "name": "slot",
+ "width": 58,
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "xsDxq",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eLLhR",
+ "name": "Submit",
+ "width": "fill_container",
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "gap": 2,
+ "padding": [
+ 10,
+ 16
+ ],
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "LOCUW",
+ "name": "Line",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "PE903",
+ "name": "Label",
+ "fill": "#ffffff",
+ "content": "post 3 · ask Pat to re-review",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "m0pl2",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "D9dcFD",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "C33Bq",
+ "name": "Alt",
+ "fill": "$ui-accent-text",
+ "content": "or post without asking",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ids0h",
+ "name": "Row 2",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "v7tCw",
+ "name": "C · On Pat's thread",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "GkkOM",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "y2B4Y",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "C · On Pat's thread",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "U3Ih35",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Where the review came from",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HUrhx",
+ "name": "Thread card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Fo6lO",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 10,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HlSHk",
+ "name": "Who",
+ "fill": "$ui-text-1",
+ "content": "Pat",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "OGKoq",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "src/jobs/scan.ts:88",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "d0bAbL",
+ "name": "Reply",
+ "width": "fill_container",
+ "layout": "vertical",
+ "padding": [
+ 12,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "F1DxE",
+ "name": "Field",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "RVYSB",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "good catch, renamed it to stats.reachableInBoth and fixed the comments in a1b2c3.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "i3P0QE",
+ "name": "Foot",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "gap": 20,
+ "padding": [
+ 10,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "W48wX",
+ "name": "Re-review tick",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "VNy99",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "KnkLr",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "jRh3U",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "content": "Post reply",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cBHvR",
+ "name": "Re-review tick",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "F8IfO",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "T2Br1x",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "AprSc",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "content": "Ask Pat to re-review",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ehIvX",
+ "name": "D · Header line",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "F5rfi",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "N1ohOU",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "D · Header line",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "dOCus",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Stated before you read",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zEnVR",
+ "name": "List head",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 8,
+ "padding": [
+ 10,
+ 14
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "rBoMU",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "TAWEA",
+ "name": "refresh-cw",
+ "width": 14,
+ "height": 14,
+ "icon": "refresh-cw",
+ "library": "lucide",
+ "fill": "$ui-accent-text"
+ },
+ {
+ "type": "text",
+ "id": "Xxoe7",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Pat reviewed this MR",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DfSNL",
+ "name": "Re-review tick",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "AMtY6",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "U836z3",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "sY6Op",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "content": "Ask for a re-review after posting",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Zhruf",
+ "name": "ctx",
+ "fill": "$ui-text-3",
+ "content": "…thread cards follow",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vfFwl",
+ "x": 17960,
+ "y": 29505,
+ "name": "B29 · Review cards, calmer",
+ "theme": {
+ "mode": "light"
+ },
+ "width": 1960,
+ "fill": "$ui-page",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "Rseir",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B29 · Review cards, calmer",
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "GAbFL",
+ "name": "Description",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Same content in every card (code, finding, comment). Today each part gets an icon, a coloured label and a divider, inside a card, inside a tier pill, so the eye stops on chrome. Each option keeps every part and cuts the frames around them.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "riZNe",
+ "name": "Row 1",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "OKBo4",
+ "name": "A · Labelled rows",
+ "width": 920,
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "A1AO2q",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "fSZ8m",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "A · Labelled rows",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "kfJge",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Labels in a gutter, no dividers",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RLI53",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "t8F5X8",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "tUs0N",
+ "name": "Sev dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "TjPzD",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "IP2Oh",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "E2yOp",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "H7uxU",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "n0zHNg",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "akLZN",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YhR3a",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "xTTyF",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "yCvsm",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "mYZiw",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "jnvP1",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "FvSU8",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "Owrsn",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "lib/db/query.ts:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L2LMV",
+ "name": "Body",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 14,
+ "padding": [
+ 0,
+ 16,
+ 16,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "HIQN6",
+ "name": "Code",
+ "width": "fill_container",
+ "gap": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "SGGhk",
+ "name": "Gutter",
+ "width": 72,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "J3glS",
+ "name": "Lab",
+ "fill": "$ui-text-3",
+ "content": "CODE",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "600",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "gKTxz",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "t5ndQq",
+ "name": "Diff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "W1cUhc",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "yuDix",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "BIMir",
+ "name": "s",
+ "fill": "$ui-crit",
+ "content": "-",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "QBuRZ",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "d5ifc",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "VyczJ",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vmR3N",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "RiTop",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "QEQOE",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "M6OBm",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "MGIo1",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "aoHlU",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "tz2ff",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "l8DBIu",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Gu1OW",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "LgpQW",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qaDQd",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Q8H6x",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "K7Mn6q",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "wqs5T",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "TOeI9",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "jse8H",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "uNRE7",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "A4s8o",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "v4LRQ9",
+ "name": "Finding",
+ "width": "fill_container",
+ "gap": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "YpSLe",
+ "name": "Gutter",
+ "width": 72,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "s10i8P",
+ "name": "Lab",
+ "fill": "$ui-text-3",
+ "content": "FINDING",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "600",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "M2DdBn",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "text",
+ "id": "M5QsMj",
+ "name": "Finding",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The search handler interpolates the raw q parameter into the WHERE clause, so a crafted query string reaches the database as SQL.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "BHCq3",
+ "name": "Comment",
+ "width": "fill_container",
+ "gap": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "pURVq",
+ "name": "Gutter",
+ "width": 72,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "y2zeSV",
+ "name": "Lab",
+ "fill": "$ui-text-3",
+ "content": "COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "600",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cmCYU",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "V26em",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "TZwxU",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "issue: the search handler drops the raw q straight into the WHERE clause, so a crafted query string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "q6udG",
+ "name": "Meta",
+ "fill": "$ui-text-3",
+ "content": "drafted by the agent",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "VZCIC",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "gSqdq",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "MMcgx",
+ "name": "Sev dot",
+ "fill": "$ui-text-3",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "N9XPI",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "XKZ41",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zDzWJ",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "xKzDm",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "JPXoj",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Ao5tu",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qhrpk",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "IaO3U",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "S0ER8",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "PU9Vj",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "fk4TM",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "CU0i9",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "LLEnn",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "README.md",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HTtq3",
+ "name": "Body",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 14,
+ "padding": [
+ 0,
+ 16,
+ 16,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "vZbUw",
+ "name": "Finding",
+ "width": "fill_container",
+ "gap": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "TXmFB",
+ "name": "Gutter",
+ "width": 72,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "ios0w",
+ "name": "Lab",
+ "fill": "$ui-text-3",
+ "content": "FINDING",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "600",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DPVhp",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "text",
+ "id": "muzDZ",
+ "name": "Finding",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The README still says the scanner reads lib/jobs, and nothing mentions the move to lib/tasks.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O7bEvf",
+ "name": "Comment",
+ "width": "fill_container",
+ "gap": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "HquJR",
+ "name": "Gutter",
+ "width": 72,
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "wjKdy",
+ "name": "Lab",
+ "fill": "$ui-text-3",
+ "content": "COMMENT",
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "600",
+ "letterSpacing": 0.6
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KiG1S",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "QOSbs",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "D07CHm",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: the README.md still says the scanner reads lib/jobs. anyone with a local overlay keyed on the old paths will get merged 0/N with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "fdmWj",
+ "name": "Meta",
+ "fill": "$ui-text-3",
+ "content": "posts in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "s63bz",
+ "name": "B · Finding leads",
+ "width": 920,
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "haRZD",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Qs78g",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "B · Finding leads",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "OOciv",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Title and finding are one block",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RfkdO",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "bTaIm",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "Pj8FV",
+ "name": "Sev dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "T3TWn",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "T842h",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eBenK",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "a9gSa",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "z1gK89",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "T6Kd6",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "n59GG",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "h9iif",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 12,
+ "padding": [
+ 14,
+ 16,
+ 0,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "yDPom",
+ "name": "Tick col",
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "rPzYg",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ZwOSA",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "k5PDsJ",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "fNIwG",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "hoNam",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Lfaze",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "S2B5jA",
+ "name": "The search handler inter",
+ "fill": "$ui-text-1",
+ "content": "The search handler interpolates the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "TGIzB",
+ "name": "mono",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "G5zdL1",
+ "name": " parameter into the WHER",
+ "fill": "$ui-text-1",
+ "content": " parameter into the WHERE clause, so a crafted query string reaches the database as SQL.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W6tDd1",
+ "name": "Body",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16,
+ 16,
+ 43
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "O0jdB",
+ "name": "Path row",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "cMFmL",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "lib/db/query.ts:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "icon",
+ "id": "Dbd9Q",
+ "name": "Open on GitLab",
+ "width": 12,
+ "height": 12,
+ "icon": "arrow-up-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kIgth",
+ "name": "Diff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "BmKwI",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "j1PfeT",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "mTj6n",
+ "name": "s",
+ "fill": "$ui-del-sign",
+ "content": "-",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "p704OO",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fChhx",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "hJzJY",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "klmXf",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "m5BHao",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "m2bcG",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Z54HY",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Q7vz3",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "kMwRE",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "J6uSIB",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Ccv5S",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Xd2fo",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "t8sYH",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "m43k3",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "CSddq",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "HWl3I",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "xzYI6",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rSJAn",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "LBa5G",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "uRfKc",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Qr4Qq",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iOFcK",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "aII37",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "a8eVx",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O23Fo",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "IXVT0",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "px9Gm",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "UGxO6",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "TNaOp",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "tdaAO",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "dSZAW",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "SQpxK",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "uKHWt",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YL26K",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ixGHw",
+ "name": "SQL. could this use a bo",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "p8uuCR",
+ "name": "Code block",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "gIWDk",
+ "name": "Lang",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 4,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Rmuol",
+ "name": "lang",
+ "fill": "$ui-text-3",
+ "content": "TypeScript",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YbXL6",
+ "name": "Code",
+ "width": "fill_container",
+ "padding": [
+ 10,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "seUKA",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "db",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "J5Mut",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ".",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "fFyKS",
+ "name": "tok",
+ "fill": "$ui-accent-text",
+ "content": "query",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "P4Ehx",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "m7KQD",
+ "name": "tok",
+ "fill": "$ui-ok-text",
+ "content": "\"SELECT * FROM items WHERE name = $1\"",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "l1dFck",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ", [q]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "acZnG",
+ "name": "Edit",
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "xiDmI",
+ "name": "Edit",
+ "width": 12,
+ "height": 12,
+ "icon": "pencil",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L8blS",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "MTq4s",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "ZKCx8",
+ "name": "Sev dot",
+ "fill": "$ui-text-3",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "wOecQ",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "X8yw6n",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RMsdh",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "KIdXT",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "zGKBL",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "JCkiD",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "gW6Lh",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "nDdgH",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 12,
+ "padding": [
+ 14,
+ 16,
+ 0,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "NAEsV",
+ "name": "Tick col",
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "BpYYy",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "W8oWkk",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yg4QQ",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "hBJCH",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "T7SdA",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O20YHe",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "BVV8X",
+ "name": "The README still says th",
+ "fill": "$ui-text-1",
+ "content": "The README still says the scanner reads ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Bmcou",
+ "name": "mono",
+ "fill": "$ui-text-1",
+ "content": "lib/jobs",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Kle5K",
+ "name": ", and nothing mentions t",
+ "fill": "$ui-text-1",
+ "content": ", and nothing mentions the move to ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "EwhyL",
+ "name": "mono",
+ "fill": "$ui-text-1",
+ "content": "lib/tasks",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "eMYQU",
+ "name": ".",
+ "fill": "$ui-text-1",
+ "content": ".",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "q6gyF9",
+ "name": "Body",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16,
+ 16,
+ 43
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "zAs3c",
+ "name": "Path row",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "IZ79c",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md · no diff line",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "icon",
+ "id": "f1sHS1",
+ "name": "Open on GitLab",
+ "width": 12,
+ "height": 12,
+ "icon": "arrow-up-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "z0o4Y",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "rl9nN",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "m3xJa",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "CvxWK",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "EKlRr",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "TPb8S",
+ "name": " the ",
+ "fill": "$ui-text-1",
+ "content": " the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "cKpJu",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "j6UcK",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "README.md",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "KRZ18",
+ "name": " still says the scanner ",
+ "fill": "$ui-text-1",
+ "content": " still says the scanner reads ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "SRG7J",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "FSfL7",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/jobs",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "HhXjy",
+ "name": ". anyone with a local ov",
+ "fill": "$ui-text-1",
+ "content": ". anyone with a local overlay keyed on the",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wjZYH",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "guu6C",
+ "name": "old paths",
+ "fill": "$ui-text-1",
+ "content": "old paths will get ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "u6nUT",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "IfQEs",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "merged 0/N",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "pFB74",
+ "name": "with no hint why. could ",
+ "fill": "$ui-text-1",
+ "content": " with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NV4RN",
+ "name": "Edit",
+ "padding": [
+ 3,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "D0YQh",
+ "name": "Edit",
+ "width": 12,
+ "height": 12,
+ "icon": "pencil",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U8teg",
+ "name": "Row 2",
+ "width": "fill_container",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "SrNmq",
+ "name": "C · Code beside the words",
+ "width": 920,
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "QTUWP",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "d7zEz",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "C · Code beside the words",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "DDrQg",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Diff left, finding and comment right",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Mkx0a",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "IUZHv",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "zFnP5",
+ "name": "Sev dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "ej1wT",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "gniF2",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kkTzW",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "QnQE3",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XI7MH",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "wQVnj",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "h1EIP",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "e4vT7B",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "OM7la",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "dFYWo",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "lDiLd",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "ZXG4r",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "i6GvZG",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "lib/db/query.ts:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DeOPE",
+ "name": "Body",
+ "width": "fill_container",
+ "gap": 16,
+ "padding": [
+ 0,
+ 16,
+ 16,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Znn6k",
+ "name": "Left",
+ "width": 440,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "xn6zn",
+ "name": "Diff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "g5tL4",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "dbEp7",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "tqkIm",
+ "name": "s",
+ "fill": "$ui-crit",
+ "content": "-",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "CWJKx",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "a46Qy9",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "LenzO",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "hZlUQ",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "lLlwg",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GWBot",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "uxZey",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vyj3b",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "S5Yetk",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W5f9Rz",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "PqSHh",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "aszpT",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "DRh8t",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "j5d3L",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "jjCyS",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "dBfjt",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "bsjrH",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "QdpD1",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "HR0vv",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "gEaPK",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "BmuLe",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AWPpu",
+ "name": "Right",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "children": [
+ {
+ "type": "text",
+ "id": "xgvn7",
+ "name": "Finding",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The search handler interpolates the raw q parameter into the WHERE clause, so a crafted query string reaches the database as SQL.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "A2pK4T",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "rb626",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "issue: the search handler drops the raw q straight into the WHERE clause, so a crafted query string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Ibg8o",
+ "name": "Meta",
+ "fill": "$ui-text-3",
+ "content": "drafted by the agent",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "N1fYM",
+ "name": "Tier",
+ "width": "fill_container",
+ "padding": [
+ 4,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "W3Ify",
+ "name": "L",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "UjCl6",
+ "name": "Sev dot",
+ "fill": "$ui-text-3",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "ZKBOs",
+ "name": "Tier name",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "R5hzNc",
+ "name": "Count",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "MbVay",
+ "name": "All none",
+ "gap": 4,
+ "children": [
+ {
+ "type": "text",
+ "id": "Z0DHIy",
+ "name": "all",
+ "fill": "$ui-text-3",
+ "content": "all",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XbN72",
+ "name": "sep",
+ "fill": "$ui-text-3",
+ "content": "·",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "N5mlT",
+ "name": "none",
+ "fill": "$ui-text-1",
+ "content": "none",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "tDeQh",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "AckZi",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 12,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Z1WQi",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "MwmVj",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "lHf28",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "Ucl9y",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "oK7tE",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "README.md",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "BkrIP",
+ "name": "Body",
+ "width": "fill_container",
+ "gap": 16,
+ "padding": [
+ 0,
+ 16,
+ 16,
+ 16
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "DZaVQ",
+ "name": "Right",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 10,
+ "children": [
+ {
+ "type": "text",
+ "id": "BMpR1",
+ "name": "Finding",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The README still says the scanner reads lib/jobs, and nothing mentions the move to lib/tasks.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "zKemM",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "NEaBp",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "suggestion: the README.md still says the scanner reads lib/jobs. anyone with a local overlay keyed on the old paths will get merged 0/N with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "vCAxe",
+ "name": "Meta",
+ "fill": "$ui-text-3",
+ "content": "no diff line · posts in summary",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "H0CInD",
+ "name": "D · One open at a time",
+ "width": 920,
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "P0lETW",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "k0SPt",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "D · One open at a time",
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "pZgwe",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Rows, the one you're on expands",
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cb4ns",
+ "name": "Card",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "P1DWCh",
+ "name": "Row",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Uu2kB",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "G8U8h",
+ "name": "chevron-down",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "frame",
+ "id": "pRF3e",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "eNLuG",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "ellipse",
+ "id": "aKPT1",
+ "name": "Sev dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "XAmak",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "RdP32",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "YID19",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "lib/db/query.ts:42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "j0VBU",
+ "name": "Open body",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 0,
+ 16,
+ 16,
+ 62
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "B2Aptz",
+ "name": "Finding",
+ "fill": "$ui-text-3",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The search handler interpolates the raw q parameter into the WHERE clause, so a crafted query string reaches the database as SQL.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "HPDYI",
+ "name": "Diff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "i8P7K",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "NxQXn",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "JyraI",
+ "name": "s",
+ "fill": "$ui-crit",
+ "content": "-",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "PyZgR",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nUvVA",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "O7lUD",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "s9RXu",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "h2R7H",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "c0iuYS",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "i3Yovk",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Z9mSN0",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "C8bIff",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Pfba1",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "oZw6W",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "TyHzs",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "B0Iv0o",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SaQQU",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "k88NZF",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "V6U39",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "jCf6C",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kXNaM",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "r2JJ9k",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "zgUet",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vxQMq",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "s4e6TY",
+ "name": "Reply",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "c4yUx",
+ "name": "Reply head",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "J60vtg",
+ "name": "corner-down-right",
+ "width": 13,
+ "height": 13,
+ "icon": "corner-down-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "TuWko",
+ "name": "Who",
+ "fill": "$ui-text-3",
+ "content": "your comment on line 42",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Bgn1x",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "nh9Px",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "issue: the search handler drops the raw q straight into the WHERE clause, so a crafted query string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rEB2u",
+ "name": "Row",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "X58Ph",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "WRUjf",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "frame",
+ "id": "j5OcBi",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "lzx1o",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "ellipse",
+ "id": "PJM9n",
+ "name": "Sev dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "u94fJ",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "frame",
+ "id": "RCRrb",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "khjvn",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "lib/retry.ts:41",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "p8i9rM",
+ "name": "Row",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "apNQS",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "sg425",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "frame",
+ "id": "ZweCj",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "xIT8s",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "ellipse",
+ "id": "YllKB",
+ "name": "Sev dot",
+ "fill": "$ui-text-3",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "yVVYN",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "frame",
+ "id": "PHfmb",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "ULgGs",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "README.md",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "f5wBhM",
+ "name": "Row",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "skbV6",
+ "name": "Row head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 16
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "X9DnO",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "frame",
+ "id": "lnLEZ",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "S9eYc",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "ellipse",
+ "id": "q9D8z2",
+ "name": "Sev dot",
+ "fill": "$ui-text-3",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "u2jlb7",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "frame",
+ "id": "muynv",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "text",
+ "id": "neE5y",
+ "name": "Where",
+ "fill": "$ui-text-3",
+ "content": "evidence",
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RE9SM",
+ "name": "Keys",
+ "gap": 8,
+ "padding": [
+ 0,
+ 2
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ABhNk",
+ "name": "Keys",
+ "fill": "$ui-text-3",
+ "content": "j / k to move, space to tick",
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Kxu5D",
+ "x": 20040,
+ "y": 29505,
+ "name": "B30 · Review gate, finding leads",
+ "theme": {
+ "mode": "light"
+ },
+ "clip": true,
+ "width": 1440,
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "FYuvn",
+ "name": "Header",
+ "width": "fill_container",
+ "height": 58,
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 0,
+ 20
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "X7RUFo",
+ "name": "L",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "cuEwW",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "decision queue",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "zIaCg",
+ "name": "focus pane",
+ "fill": "#e6ebfa",
+ "cornerRadius": 6,
+ "padding": [
+ 3,
+ 8
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "twkk4",
+ "name": "t",
+ "fill": "$ui-link",
+ "content": "focus pane",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EMAFY",
+ "name": "Pager",
+ "gap": 20,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "kK5BG",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Cjlrx",
+ "name": "chevron-left",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-left",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "oPPZL",
+ "name": "of",
+ "fill": "$ui-text-3",
+ "content": "2 of 3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "jDyS1",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "zKXZB",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "TUgcs",
+ "name": "R",
+ "gap": 16,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "rOAl5",
+ "name": "tag",
+ "fill": "$ui-text-3",
+ "content": "REVIEW GATE !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal",
+ "letterSpacing": 1
+ },
+ {
+ "type": "icon",
+ "id": "WNaBA",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ROykQ",
+ "name": "Body",
+ "width": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "c3bBah",
+ "name": "Main",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 28,
+ 28,
+ 40,
+ 28
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "aK0uj",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 6,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "opJk3",
+ "name": "Left",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Bvy8x",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Post which findings to !31?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FnA2f",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ay2xh",
+ "name": "tally",
+ "fill": "$ui-text-3",
+ "content": "5 of 6",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GiChe",
+ "name": "Card · SQL built from unsanitized input",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "KRAI1",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Gu14S",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Dv18k",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "oxmN9",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vVCUw",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "DSdpi",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Hhy9E",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "x4pznU",
+ "name": "Finding glyph",
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "CxITs",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "oo6xw",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "AUrC8",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "NbprR",
+ "name": "sev",
+ "fill": "$ui-crit-label",
+ "content": "Critical",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D0jkn0",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "i7Uxy",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "KZ7fc",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "VRlXs",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/db/query.ts:42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "BW62u",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "BigON",
+ "name": "Full diff",
+ "gap": 4,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "u1hOD",
+ "name": "t",
+ "fill": "$ui-link",
+ "content": "full diff",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "icon",
+ "id": "zwlWg",
+ "name": "arrow-up-right",
+ "width": 12,
+ "height": 12,
+ "icon": "arrow-up-right",
+ "library": "lucide",
+ "fill": "$ui-link"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WJAbe",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "tw4Uo",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "GTmhD",
+ "name": "s",
+ "fill": "$ui-del-sign",
+ "content": "-",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "l0Aka",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mIk30",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XdRsK",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vwlbt",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "U4udsn",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iQWz3",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "SYzl3",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "FZqjD",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Pkxv2",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "byzwX",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Vb7Ly",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Br1rk",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "BoMxP",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YyUfi",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "qykLB",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XEMZt",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "MFJvM",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hsI3N",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XHG6Q",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "gwa7j",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "ANmRS",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "tXwRX",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Seh1W",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "jWW3U",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "vB5hq",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "jO5CG",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "palDg",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "Ct6Ux",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "tKALj",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "a48dv",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "f6ihC",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "n04vF",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "A8uMRG",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "VJPDT",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "r2XmDN",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "TZAAd",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XhkP4",
+ "name": "Code block",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "gL91b",
+ "name": "Lang",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 4,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "VCHdJ",
+ "name": "lang",
+ "fill": "$ui-text-3",
+ "content": "TypeScript",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "jd9cu",
+ "name": "Code",
+ "width": "fill_container",
+ "padding": [
+ 10,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "BFire",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "db",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "OwGfm",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ".",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "cR1Ia",
+ "name": "tok",
+ "fill": "$ui-accent-text",
+ "content": "query",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "z6Qh2",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "leuJF",
+ "name": "tok",
+ "fill": "$ui-ok-text",
+ "content": "\"SELECT * FROM items WHERE name = $1\"",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "U1R38Q",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ", [q]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "T5916",
+ "name": "State tag",
+ "padding": [
+ 4,
+ 16,
+ 10,
+ 16
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "D0OSZ",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "HOVER ON THE CODE",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal",
+ "letterSpacing": 0.4
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "s2BzKo",
+ "layoutPosition": "absolute",
+ "x": 256,
+ "y": 39,
+ "name": "Finding hovercard",
+ "width": 380,
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "effect": {
+ "type": "shadow",
+ "shadowType": "outer",
+ "color": "#0000001f",
+ "offset": {
+ "x": 0,
+ "y": 6
+ },
+ "blur": 18
+ },
+ "layout": "vertical",
+ "gap": 8,
+ "padding": [
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "VzcLt",
+ "name": "Head",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "y41zO",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "Agent finding",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "twl3s",
+ "name": "Body",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "The search handler interpolates the raw q parameter into the WHERE clause, so a crafted query string reaches the database as SQL.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "td5fF",
+ "name": "Card · Retry loop lacks backoff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "l2OIe",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "l37jkk",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "xWzDX",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "w4A7mX",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "evvyX",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "voAcM",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zv2CZ",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "PxrKk",
+ "x": 172,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "drBBD",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qwoXJ",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "NZSLo",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "V7XAEc",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nVOl8",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "bywIC",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "xLL10",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "SF2PU",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/retry.ts:41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "b7H8v7",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dY2UL",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "ta6w1",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "38",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "ZGsNz",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "zd1wO",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " try {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "xOW2V",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "TvvEZ",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "39",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "OnvJZ",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "ixaLd",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " return await job();",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fTwio",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "oPU3e",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "b4R5EJ",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "EhGLE",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " } catch (err) {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ewePS",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "U2YkJM",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "dWPka",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "a91yp4",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " if (attempt >= attempts) throw err;",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FiqSK",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "ZEgji",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "z2hu5",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "z9MOW",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " log.warn('retrying', { attempt });",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wf6eb",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Ussuh",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "c5oQFQ",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vmDta",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " }",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iviK7",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "AjjMa",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "NjkzX",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "lWUVO",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "D7HAQA",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HQxKb",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "Xu08j",
+ "name": " the loop retries immedi",
+ "fill": "$ui-text-1",
+ "content": " the loop retries immediately up to five times, so one upstream blip turns into",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "f6sg8P",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "EuxeU",
+ "name": "something like ",
+ "fill": "$ui-text-1",
+ "content": "six requests. something like ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "qt9Sh",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "sXuYm",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "Math.min(200 * 2 ** attempt, 5000)",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "w8U7G",
+ "name": " would back it off.",
+ "fill": "$ui-text-1",
+ "content": " would back it off.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rbgYN",
+ "name": "Hover hint",
+ "padding": [
+ 2,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Vl2gv",
+ "name": "t",
+ "fill": "$ui-text-3",
+ "content": "click to edit",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W7lwz",
+ "name": "State tag",
+ "padding": [
+ 4,
+ 16,
+ 10,
+ 16
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Tva0T",
+ "name": "t",
+ "fill": "$ui-accent-text",
+ "content": "HOVER ON THE COMMENT",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal",
+ "letterSpacing": 0.4
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FoX3I",
+ "name": "Card · Missing null check on response",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "L6gGZQ",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "TYQyO",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "a0SARu",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "LX3yM",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iRsaV",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "EHmta",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "U4jo2",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Missing null check on response",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "NoWbV",
+ "x": 221,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "gH5SK",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GOzFG",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "h6tYNq",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "v0XFxf",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bc66O",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "VBlwR",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "M8Xch3",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "yWQB4",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/api/client.ts:88",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "zTKSh",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DOuwc",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Iv6m9",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "W9aoH",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "g6iTT",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "c5FIl",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "lCbN7",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "r3DTkF",
+ "name": " a 204 from upstream has",
+ "fill": "$ui-text-1",
+ "content": " a 204 from upstream has no body, so ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "C5GMy",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "WaSiM",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.json()",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "gjJKU",
+ "name": " throws before ",
+ "fill": "$ui-text-1",
+ "content": " throws before ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "gtwuw",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Zuxhj",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "data.items",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Naa4w",
+ "name": " is ever read. could thi",
+ "fill": "$ui-text-1",
+ "content": " is ever read.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vYfZQ",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "mhvkp",
+ "name": "check ",
+ "fill": "$ui-text-1",
+ "content": "could this check ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "f5XGlY",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ylrsd",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.status",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "c4w8yo",
+ "name": " first and return an emp",
+ "fill": "$ui-text-1",
+ "content": " first and return an empty list?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "y4XvRR",
+ "name": "Card · README still names the old folder",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "wlAgV",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Byhyl",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "sp3T3",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "D0mIZ5",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "gBnXq",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "lGRsL",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "t0eI4",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "P5mNQL",
+ "x": 237,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "dFUMl",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "bsYIz",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "JhMIS",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "SP0Mw",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "C6y1pU",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "XKd5f",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md · no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Nt449",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "GHmAa",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "rAPqJ",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "JnNde",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "HWzoU",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ka1X5",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "hts3u",
+ "name": " the ",
+ "fill": "$ui-text-1",
+ "content": " the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "AGruc",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "rPLF6",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "README.md",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Xf7Wp",
+ "name": " still says the scanner ",
+ "fill": "$ui-text-1",
+ "content": " still says the scanner reads ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "xNXPl",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "M3tEB",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/jobs",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "O1xnXj",
+ "name": ". anyone with a local ov",
+ "fill": "$ui-text-1",
+ "content": ". anyone with a local overlay keyed on the",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hJhVx",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "v35mGp",
+ "name": "old paths will get ",
+ "fill": "$ui-text-1",
+ "content": "old paths will get ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "u42eqd",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "E87Uaw",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "merged 0/N",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "W6fKe",
+ "name": " with no hint why. could",
+ "fill": "$ui-text-1",
+ "content": " with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mrRhK",
+ "name": "Card · No run for the --changed flag",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UXGx7",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "uIXTv",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "FMv3B",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "l6zZJE",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RPEVZ",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ZKrBM",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "K1pvDi",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "OJgk1",
+ "x": 207,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "OjUZG",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Jguc8",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "wWrDh",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "lWJoa",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "e5WRF",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "d0wUkv",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NMAzE",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "FmS7G",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "v8Be66",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "FGs19",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "vRcU1",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "W9aUt9",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "UvFvM",
+ "name": " thanks for the extra ev",
+ "fill": "$ui-text-1",
+ "content": " thanks for the extra evidence, that covers it nicely. the one AC without a run is ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "aflTs",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "u6Q7J",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "--changed",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rzYoU",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "jhflA",
+ "name": "picking up a file under ",
+ "fill": "$ui-text-1",
+ "content": "picking up a file under ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "vexY9",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zP6o7",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/tasks/**",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "RQWBn",
+ "name": "... would you mind grabb",
+ "fill": "$ui-text-1",
+ "content": "... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "oyEVG",
+ "name": "Card · Unused import",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "zXsKE",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "PWuaP",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "zvGMc",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "y3ZKf",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "s6fTA",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ulwhT",
+ "name": "Title",
+ "fill": "$ui-text-3",
+ "content": "Unused import",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "AWX0O",
+ "x": 108,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "wxZoa",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GcK7X",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "I9IZZ",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "Qfrdq",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "J3lgx",
+ "name": "Rail",
+ "width": 470,
+ "height": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 1
+ },
+ "layout": "vertical",
+ "gap": 14,
+ "padding": [
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "yHoGz",
+ "name": "MR card",
+ "width": "fill_container",
+ "fill": "#fbfbfc",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 6,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ItVii",
+ "name": "Who",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "dnSkY",
+ "name": "Avatar",
+ "fill": "#d6409f",
+ "width": 16,
+ "height": 16
+ },
+ {
+ "type": "text",
+ "id": "WhCTV",
+ "name": "Name",
+ "fill": "#8e4ec6",
+ "content": "Paul",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "CI19A",
+ "name": "v",
+ "fill": "$ui-text-1",
+ "content": "opened",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "NCfzz",
+ "name": "ref",
+ "fill": "$ui-accent-text",
+ "content": "!31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "coMZM",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "into main",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "hMxce",
+ "name": "MR title",
+ "fill": "$ui-text-1",
+ "content": "themed gate controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "I4SmQv",
+ "name": "Stats",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "B93q4T",
+ "name": "age",
+ "fill": "$ui-text-3",
+ "content": "41d ·",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "oF5nq",
+ "name": "add",
+ "fill": "$ui-ok-text",
+ "content": "+84",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "D0yBW",
+ "name": "del",
+ "fill": "$ui-del-sign",
+ "content": "-21",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "s7P7E",
+ "name": "branch",
+ "fill": "$ui-text-3",
+ "content": "board-28-themed-gate-controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "PQYby",
+ "name": "Decision context",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 8,
+ "padding": 16,
+ "children": [
+ {
+ "type": "text",
+ "id": "exYvX",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "DECISION CONTEXT",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal",
+ "letterSpacing": 0.8
+ },
+ {
+ "type": "text",
+ "id": "VgbbK",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Ready to merge: with fixes",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "dizVS",
+ "name": "s",
+ "fill": "$ui-text-1",
+ "content": "One critical injection risk; everything else is polish.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "zAta3",
+ "name": "who",
+ "fill": "$ui-text-3",
+ "content": "renee",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "SYmKE",
+ "name": "Tiers",
+ "gap": 14,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "WROeS",
+ "name": "Critical",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "SgXDU",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "tscnq",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "XfGN8",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "mydq4",
+ "name": "Important",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "OBZvW",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "G2HBG",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Important",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "iU02l",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AD8I2",
+ "name": "Minor",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "by1tz",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "WLRCK",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "CWQLe",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D4dGCO",
+ "name": "Spacer",
+ "width": "fill_container",
+ "height": "fill_container"
+ },
+ {
+ "type": "frame",
+ "id": "K2zg4I",
+ "name": "Dock",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 16,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "mMVzu",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "msDEt",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JGCmG",
+ "name": "Option comment",
+ "width": "fill_container",
+ "fill": "#eef2fd",
+ "cornerRadius": 8,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "gap": 12,
+ "padding": [
+ 12,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "o8D8p4",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "czorq",
+ "name": "Dot",
+ "fill": "$ui-accent-fill",
+ "width": 7,
+ "height": 7
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "APmWb",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "children": [
+ {
+ "type": "frame",
+ "id": "HC5uc",
+ "name": "Line",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "x83hfu",
+ "name": "label",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "W4rxr",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "M5ce2",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "y2hs4",
+ "name": "desc",
+ "fill": "$ui-text-3",
+ "content": "Post the selected findings without a verdict.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "e72CMG",
+ "name": "Key",
+ "width": 18,
+ "height": 18,
+ "cornerRadius": 4,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "hNXRv",
+ "name": "k",
+ "fill": "$ui-text-1",
+ "content": "1",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KGKJF",
+ "name": "Option approve",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "gap": 12,
+ "padding": [
+ 12,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "bMvhr",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "#b9bbc6",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ {
+ "type": "frame",
+ "id": "FD8oT",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "children": [
+ {
+ "type": "frame",
+ "id": "cwxyx",
+ "name": "Line",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Ws4uv",
+ "name": "label",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "t87x3x",
+ "name": "desc",
+ "fill": "$ui-text-3",
+ "content": "Approve !31 and post the selected findings.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EtVbP",
+ "name": "Key",
+ "width": 18,
+ "height": 18,
+ "cornerRadius": 4,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Kqpry",
+ "name": "k",
+ "fill": "$ui-text-1",
+ "content": "2",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wBy19",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "NGOoJ",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "tL8Rl",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "Bmcmb",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "R9cMre",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "EdDkg",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the injection one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LDJI9",
+ "name": "Note",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "padding": [
+ 9,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "bYNec",
+ "name": "ph",
+ "fill": "$ui-text-3",
+ "content": "Add a note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "K9TDxt",
+ "name": "Submit",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 8,
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "AYlrJ",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "GdOdb",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "mzlcw",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "j3v3LV",
+ "x": 21600,
+ "y": 29505,
+ "name": "B31 · 14-inch laptop (1512×860)",
+ "theme": {
+ "mode": "light"
+ },
+ "clip": true,
+ "width": 1512,
+ "height": 860,
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "dUDXe",
+ "name": "Header",
+ "width": "fill_container",
+ "height": 58,
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 0,
+ 20
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "R9zeE9",
+ "name": "L",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "J0Fcz",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "decision queue",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "uXe2X",
+ "name": "focus pane",
+ "fill": "#e6ebfa",
+ "cornerRadius": 6,
+ "padding": [
+ 3,
+ 8
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "ITPJL",
+ "name": "t",
+ "fill": "$ui-link",
+ "content": "focus pane",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O8j5w",
+ "name": "Pager",
+ "gap": 20,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QejTW",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "F91ae",
+ "name": "chevron-left",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-left",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "LrldO",
+ "name": "of",
+ "fill": "$ui-text-3",
+ "content": "2 of 3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "JlEyn",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Q4ols",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "M0x8V",
+ "name": "R",
+ "gap": 16,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "qk2VL",
+ "name": "tag",
+ "fill": "$ui-text-3",
+ "content": "REVIEW GATE !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal",
+ "letterSpacing": 1
+ },
+ {
+ "type": "icon",
+ "id": "T6yKRk",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HLbqf",
+ "name": "Body",
+ "width": "fill_container",
+ "height": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "iNNLB",
+ "name": "Main",
+ "clip": true,
+ "width": "fill_container",
+ "height": "fill_container",
+ "fill": "$ui-panel",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 28,
+ 28,
+ 40,
+ 28
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "vMMLj",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 6,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Mri3x",
+ "name": "Left",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "D6M1T",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Post which findings to !31?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "or2BW",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "dY2O7",
+ "name": "tally",
+ "fill": "$ui-text-3",
+ "content": "5 of 6",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GEoEm",
+ "name": "Card · SQL built from unsanitized input",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "x9BjBh",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "atbB3",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ssxYO",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "iu4Hp",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eMhcF",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "rgCya",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "QLEwz",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "lqW4a",
+ "x": 225,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "wNG6w",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "myyrP",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "Pm40V",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "tHrJV",
+ "name": "sev",
+ "fill": "$ui-crit-label",
+ "content": "Critical",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "h9hHe",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "shlod",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "n6ue1",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "dXk0O",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/db/query.ts:42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "vjBZ9",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JxJ2g",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "qNUuh",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "fE0g6",
+ "name": "s",
+ "fill": "$ui-del-sign",
+ "content": "-",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "eB2W2",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GRlTX",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "pbTyq",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "hmCqL",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "KOAog",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hjnpQ",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "FxXtf",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "gn75L",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "E4vuXC",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "K5Fqv6",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "pMS1F",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "u9XCsR",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "e01q84",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "c6hbtI",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "v4Fe2",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "W8co4",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "CWkaG",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dnsyF",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Ym9Kj",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "FxUCF",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "sH1Bc",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rLOX8",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "iAG2G",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "X61Fi9",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "kfX7A",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "sSKcf",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "KI5Tt",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "YEP95",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "tlENM",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HfWq3",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "ZLpJf",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "huGb3",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Wqfkb",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "G620v",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "C6cpjd",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CACUi",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yevaK",
+ "name": "Code block",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "YFWos",
+ "name": "Lang",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 4,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "FnUiB",
+ "name": "lang",
+ "fill": "$ui-text-3",
+ "content": "TypeScript",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DGnXd",
+ "name": "Code",
+ "width": "fill_container",
+ "padding": [
+ 10,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "lLUir",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "db",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "aj0Js",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ".",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "xM2sD",
+ "name": "tok",
+ "fill": "$ui-accent-text",
+ "content": "query",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "FzS3v",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "F9P8aS",
+ "name": "tok",
+ "fill": "$ui-ok-text",
+ "content": "\"SELECT * FROM items WHERE name = $1\"",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "dAsXs",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ", [q]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Y3ULp",
+ "name": "Card · Retry loop lacks backoff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "VauZg",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "I78tF",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "OMjJ4",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "F0RXaA",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CV8sa",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Y5Uf6",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "r37fw",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "G5z2U8",
+ "x": 172,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "B6FuqA",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SoKw4",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "NZQmI",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "qRXjZ",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZShNZ",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "m7ML8b",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "i2q6O1",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "jqqai",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/retry.ts:41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "YR2E5",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "PRDj0",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XDNc2",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "38",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "e7mYmO",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "GKwGC",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " try {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L7Sob",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "BSfdR",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "39",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "SEmrc",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "UWNQM",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " return await job();",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "sPvNB",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "eg32u",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Flaw5",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "oxwjm",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " } catch (err) {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Bpa79",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "TfmWC",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "NZbps",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "k0f0Nw",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " if (attempt >= attempts) throw err;",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Mp742",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "QusYz",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "g6yoTW",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "fYir1",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " log.warn('retrying', { attempt });",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hfYli",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "LLrS4",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XcHqe",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "clIGt",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " }",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HYtn1",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Qhdwf",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "G3SJb",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "jl3vu",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ENLjk",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zMh0Y",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "f9sY2X",
+ "name": " the loop retries immedi",
+ "fill": "$ui-text-1",
+ "content": " the loop retries immediately up to five times, so one upstream blip turns into six requests.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CzJyy",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "wzp3F",
+ "name": "something like ",
+ "fill": "$ui-text-1",
+ "content": "something like ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "p26yGS",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "BRT9s",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "Math.min(200 * 2 ** attempt, 5000)",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "MBntY",
+ "name": " would back it off.",
+ "fill": "$ui-text-1",
+ "content": " would back it off.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "TZh4Q",
+ "name": "Card · Missing null check on response",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "BPGeu",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "z7gZLm",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "XKKpp",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "F1ZiL",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XULOS",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "D4J8Da",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "mC26s",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Missing null check on response",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "TzL5G",
+ "x": 221,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "SLQu2",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "lTPSu",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "zBxtZ",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "pxddl",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nWkOC",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "VGdvl",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "k4wvs",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "rJA9C",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/api/client.ts:88",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Zbv8S",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "smQsB",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "G3Nyq",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "U1N7SA",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "S4mhY",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "vnnC1",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "nHhIB",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "RMXtv",
+ "name": " a 204 from upstream has",
+ "fill": "$ui-text-1",
+ "content": " a 204 from upstream has no body, so ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "hKSwk",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "xwR3V",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.json()",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "wHiWq",
+ "name": " throws before ",
+ "fill": "$ui-text-1",
+ "content": " throws before ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "moBuN",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ABXA8",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "data.items",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "ZRFi2",
+ "name": " is ever read. could thi",
+ "fill": "$ui-text-1",
+ "content": " is ever read.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kbBEt",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "sGTUM",
+ "name": "check ",
+ "fill": "$ui-text-1",
+ "content": "could this check ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "kH4gg",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "f5ojwo",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.status",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "SyoOw",
+ "name": " first and return an emp",
+ "fill": "$ui-text-1",
+ "content": " first and return an empty list?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D1H1Dg",
+ "name": "Card · README still names the old folder",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hmOds",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "sit34",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QiPKI",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "PZE7I",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ETtN2",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "tVppL",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "gcZwM",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "FiFqZ",
+ "x": 237,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "MAmI6",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ktVD8",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "MVT9N",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "yrjBY",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ESB0z",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HUZdH",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md · no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WFm91",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "jA2XY",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "wMRgn",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "mPnGn",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "A5gaJD",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zwenL",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "NRP2Y",
+ "name": " the ",
+ "fill": "$ui-text-1",
+ "content": " the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Dv2cD",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "a8ZwV",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "README.md",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "QlJom",
+ "name": " still says the scanner ",
+ "fill": "$ui-text-1",
+ "content": " still says the scanner reads ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "LfkZU",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Qwle0",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/jobs",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "KVyJt",
+ "name": ". anyone with a local ov",
+ "fill": "$ui-text-1",
+ "content": ". anyone with a local overlay keyed on the",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YieHf",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "fW09W",
+ "name": "old paths will get ",
+ "fill": "$ui-text-1",
+ "content": "old paths will get ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "d9h4h",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "oIz0T",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "merged 0/N",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "gpoTN",
+ "name": " with no hint why. could",
+ "fill": "$ui-text-1",
+ "content": " with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U8DRy",
+ "name": "Card · No run for the --changed flag",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "s4APk",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "RAXny",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "V3Jkxq",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "xMjgk",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D7mq1",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ptfo8",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zQJPW",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "jxd4Z",
+ "x": 207,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "hMStU",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "onD4H",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "y62U9J",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "m1cGt9",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o70P4H",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "igNxA",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "e6FJMl",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "IFGpz",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "JRvv3",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "p7o18",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "XUlnF",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "H1LDdg",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "A5tiN4",
+ "name": " thanks for the extra ev",
+ "fill": "$ui-text-1",
+ "content": " thanks for the extra evidence, that covers it nicely. the one AC without a run is ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "yoTub",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zUwKr",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "--changed",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "J7rA3d",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "YzIm1",
+ "name": "picking up a file under ",
+ "fill": "$ui-text-1",
+ "content": "picking up a file under ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "SvqHq",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "mQZaP",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/tasks/**",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "l7Qmp",
+ "name": "... would you mind grabb",
+ "fill": "$ui-text-1",
+ "content": "... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "b95YhE",
+ "name": "Card · Unused import",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "J3TUD",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "D4jWDe",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "J3IDZz",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O8qG2Q",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "YlOBG",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "TuShN",
+ "name": "Title",
+ "fill": "$ui-text-3",
+ "content": "Unused import",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "J2BQK",
+ "x": 108,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "m5lZ7O",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "PMhG9",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "mQYuf",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "pfMQI",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "u9RoyE",
+ "name": "Rail",
+ "width": 470,
+ "height": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 1
+ },
+ "layout": "vertical",
+ "gap": 14,
+ "padding": [
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "LzZ5V",
+ "name": "Rail scroll",
+ "clip": true,
+ "width": "fill_container",
+ "height": "fill_container",
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "zMUFd",
+ "name": "MR card",
+ "width": "fill_container",
+ "fill": "#fbfbfc",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 6,
+ "padding": 16,
+ "children": [
+ {
+ "type": "frame",
+ "id": "H8Bqc",
+ "name": "Who",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "FNdXK",
+ "name": "Avatar",
+ "fill": "#d6409f",
+ "width": 16,
+ "height": 16
+ },
+ {
+ "type": "text",
+ "id": "a5BYla",
+ "name": "Name",
+ "fill": "#8e4ec6",
+ "content": "Paul",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "XwG6R",
+ "name": "v",
+ "fill": "$ui-text-1",
+ "content": "opened",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "RMLrM",
+ "name": "ref",
+ "fill": "$ui-accent-text",
+ "content": "!31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "y3tJQ9",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "into main",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "bEi2h",
+ "name": "MR title",
+ "fill": "$ui-text-1",
+ "content": "themed gate controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "M7Nzn",
+ "name": "Stats",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "omCZa",
+ "name": "age",
+ "fill": "$ui-text-3",
+ "content": "41d ·",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "JFuoe",
+ "name": "add",
+ "fill": "$ui-ok-text",
+ "content": "+84",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "OE4Y7",
+ "name": "del",
+ "fill": "$ui-del-sign",
+ "content": "-21",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "qS7JB",
+ "name": "branch",
+ "fill": "$ui-text-3",
+ "content": "board-28-themed-gate-controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Lpa0O",
+ "name": "Decision context",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 8,
+ "padding": 16,
+ "children": [
+ {
+ "type": "text",
+ "id": "dxWBG",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "DECISION CONTEXT",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal",
+ "letterSpacing": 0.8
+ },
+ {
+ "type": "text",
+ "id": "FcFpo",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Ready to merge: with fixes",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "b5qSjC",
+ "name": "Summary",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Clean, well-scoped fix for the search handler. Parameterizing the query closes the injection path, and the retry and null-check notes are small. The evidence covers every AC but --changed.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "S4uQL",
+ "name": "who",
+ "fill": "$ui-text-3",
+ "content": "renee",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "cSIR5",
+ "name": "Tiers",
+ "gap": 14,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "KeNlT",
+ "name": "Critical",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "U9xkKT",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "HTVci",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "K0QmIJ",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nNMBZ",
+ "name": "Important",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "E44Sl",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "lN6eZ",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Important",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "siFic",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CyGrH",
+ "name": "Minor",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "RKKEF",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "y9XWH",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "hgGA9",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zVgpc",
+ "name": "Checks",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 8,
+ "padding": 16,
+ "children": [
+ {
+ "type": "text",
+ "id": "VSVvP",
+ "name": "t",
+ "fill": "$ui-text-3",
+ "content": "checks",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "b9Tm6r",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "iouBW",
+ "name": "Chip",
+ "width": 46,
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HONA9",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "PASS",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "s7seQ",
+ "name": "txt",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "jest suite for lib/db and lib/api, 212 of 212 green after the parameterized query change",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "zyKsc",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "LacNa",
+ "name": "Chip",
+ "width": 46,
+ "cornerRadius": 4,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "kHeTz",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "PASS",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "pwIbp",
+ "name": "txt",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "typecheck and lint clean on the touched packages",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "fqMrJ",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "w6FPD4",
+ "name": "Chip",
+ "width": 46,
+ "cornerRadius": 4,
+ "stroke": "$ui-del-sign",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "e11tKa",
+ "name": "t",
+ "fill": "$ui-del-sign",
+ "content": "FAIL",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "to3wg",
+ "name": "txt",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "preview e2e search-flow spec times out on the empty-query case; looks unrelated, rerun before merge",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o69kP",
+ "name": "Row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "dVtgO",
+ "name": "Chip",
+ "width": 46,
+ "cornerRadius": 4,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "JYge7",
+ "name": "t",
+ "fill": "$ui-text-3",
+ "content": "N/A",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "C6dz4g",
+ "name": "txt",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "visual regression, no UI touched",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XbZXs",
+ "name": "Dock",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 16,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "DFkG1",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "JW2o4",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "cegbN",
+ "name": "Right",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vejYR",
+ "name": "note",
+ "fill": "$ui-accent-text",
+ "content": "add note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wjk7A",
+ "name": "Options",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Cwxke",
+ "name": "Opt comment",
+ "width": "fill_container",
+ "fill": "#eef2fd",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "YJRR0",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "nkKDx",
+ "name": "Dot",
+ "fill": "$ui-accent-fill",
+ "width": 7,
+ "height": 7
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "y4sMgO",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "P5ixCg",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "quKw1",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "D0or5",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "no verdict",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "ZXeR8",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "bfKGn",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "V9VrOR",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "jAxCQ",
+ "name": "Opt approve",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "cJUJW",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "#b9bbc6",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ {
+ "type": "text",
+ "id": "OTviV",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "text",
+ "id": "NQHpI",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "approves !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "J1sP9",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "nMv9o",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "eCacm",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W2ERjq",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "F7vNQ",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "h83iJo",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "z1I7IA",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JxAWF",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "n52eIv",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Thanks for the quick turnaround. The injection fix is the one to land first; the retry and README notes can follow in this MR or the next.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "MYr0M",
+ "name": "Submit",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 8,
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "W8GgOi",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "gbXvs",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "tdjZY",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LPpDO",
+ "x": 21600,
+ "y": 31465,
+ "name": "B32 · Verdict picker, compact",
+ "theme": {
+ "mode": "light"
+ },
+ "fill": "$ui-page",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "PHSy8",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B32 · Verdict picker, compact",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "IgHXm",
+ "name": "Row",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "XAetm",
+ "name": "A · Plain radio rows",
+ "width": 470,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "WLsHr",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zXw6m",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "A · Plain radio rows",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "u4g6Zf",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "No boxes, one line each",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZWv8X",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 16,
+ 26,
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Q5Iv3F",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "rGvDt",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "za0Dm",
+ "name": "R",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "n4BVsK",
+ "name": "n",
+ "fill": "$ui-accent-text",
+ "content": "add note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UG39d",
+ "name": "Options",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "children": [
+ {
+ "type": "frame",
+ "id": "YtM5C",
+ "name": "Opt comment",
+ "width": "fill_container",
+ "fill": "#eef2fd",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "wGY2Y",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "aWQK8",
+ "name": "Dot",
+ "fill": "$ui-accent-fill",
+ "width": 7,
+ "height": 7
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "feTg1",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "dwZoF",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "N07Ng",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "MKZWA",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "no verdict",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "eTRWu",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "hwbUV",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "LmMPR",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Rh7sH",
+ "name": "Opt approve",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hVbr9",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "#b9bbc6",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ {
+ "type": "text",
+ "id": "WvxpA",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "text",
+ "id": "s7fpO",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "approves !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "dOy4Y",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "bSnul",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "r9S0q",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "K2YW6d",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "VegPb",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "wkAck",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "kDLU3",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hBxC3",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XFSkt",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the injection one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "fuQin",
+ "name": "Edit",
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "fUd4B",
+ "name": "pencil",
+ "width": 12,
+ "height": 12,
+ "icon": "pencil",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "z9qIh3",
+ "name": "Submit",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 8,
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "xCMn5",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "mVa5P",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "G475H",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "S96g8H",
+ "name": "B · The button is the verdict",
+ "width": 470,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "qAOBR",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "sAd5V",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "B · The button is the verdict",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "GZ5yT",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Pick from the button's menu",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eB1tb",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 16,
+ 26,
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "dewf9",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "dXkN3",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "bafU2",
+ "name": "R",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "UbeUe",
+ "name": "n",
+ "fill": "$ui-accent-text",
+ "content": "add note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "QlrCl",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "wW4AI",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "is7dS",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "BdKbF",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HkgLW",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "B6zC6",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the injection one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Z1e1M",
+ "name": "Edit",
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "Oza75",
+ "name": "pencil",
+ "width": 12,
+ "height": 12,
+ "icon": "pencil",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "oCIu9",
+ "name": "Split button",
+ "width": "fill_container",
+ "height": 44,
+ "gap": 1,
+ "children": [
+ {
+ "type": "frame",
+ "id": "se4uQ",
+ "name": "Main",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": [
+ 8,
+ 0,
+ 0,
+ 8
+ ],
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "H8pYv",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "mogAb",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Yvgc1",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qF8ef",
+ "name": "Caret",
+ "width": 44,
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": [
+ 0,
+ 8,
+ 8,
+ 0
+ ],
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "PuG7L",
+ "name": "chevron-down",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ivPrU",
+ "name": "Menu (open)",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "effect": {
+ "type": "shadow",
+ "shadowType": "outer",
+ "color": "#0000001a",
+ "offset": {
+ "x": 0,
+ "y": 4
+ },
+ "blur": 12
+ },
+ "layout": "vertical",
+ "padding": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "hDfud",
+ "name": "Item comment",
+ "width": "fill_container",
+ "fill": "#eef2fd",
+ "cornerRadius": 6,
+ "gap": 8,
+ "padding": [
+ 8,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ky64k",
+ "name": "check",
+ "width": 13,
+ "height": 13,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "$ui-accent-fill"
+ },
+ {
+ "type": "text",
+ "id": "Zvp8C",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "Jqzv4",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "M6WAw",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "m28z0",
+ "name": "Item approve",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "gap": 8,
+ "padding": [
+ 8,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "cT4wF",
+ "name": "check",
+ "width": 13,
+ "height": 13,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#00000000"
+ },
+ {
+ "type": "text",
+ "id": "ol3tI",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "dCmpR",
+ "name": "C · Inline choice",
+ "width": 470,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "HIddK",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ZkK2m",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "C · Inline choice",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "wxlC3",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "One row, label and two radios",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "S8Q67Z",
+ "name": "Dock",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 12,
+ "padding": [
+ 16,
+ 26,
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "TF65z",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "paf3Q",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "hZpYm",
+ "name": "R",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "xOXUw",
+ "name": "n",
+ "fill": "$ui-accent-text",
+ "content": "add note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vrkmL",
+ "name": "Inline",
+ "width": "fill_container",
+ "gap": 18,
+ "padding": [
+ 2,
+ 0
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "DxU8w",
+ "name": "Opt comment",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "IQNw1",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "x1JbHy",
+ "name": "Dot",
+ "fill": "$ui-accent-fill",
+ "width": 7,
+ "height": 7
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "PZoDX",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "UWZew",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CTX8x",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "VRyd5",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "no verdict",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZfY7A",
+ "name": "Opt approve",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QIKlF",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "#b9bbc6",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ {
+ "type": "text",
+ "id": "O9P8sE",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "frame",
+ "id": "bAvEy",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "l3vrf",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "D1802x",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "approves !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "CreHZ",
+ "name": "Rec line",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "YwgB9",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "jexND",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "scOc8",
+ "name": "d",
+ "fill": "$ui-text-3",
+ "content": "no verdict, findings only",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Bxi4V",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "children": [
+ {
+ "type": "frame",
+ "id": "N7Mtx",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zutiX",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "gP6v3",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "O4IPO",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "nYZrG",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Left a few comments, the injection one is the main one.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "m3gQ8",
+ "name": "Edit",
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "gbHSO",
+ "name": "pencil",
+ "width": 12,
+ "height": 12,
+ "icon": "pencil",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "gkIXv",
+ "name": "Submit",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 8,
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HuZae",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "Kxjyq",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "LLf6V",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "n4ZIJI",
+ "x": 21600,
+ "y": 30485,
+ "name": "B31b · 14-inch, condensed rail",
+ "theme": {
+ "mode": "light"
+ },
+ "clip": true,
+ "width": 1512,
+ "height": 860,
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "f3sfF",
+ "name": "Header",
+ "width": "fill_container",
+ "height": 58,
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 0,
+ 20
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "h2MCAS",
+ "name": "L",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "JHrel",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "decision queue",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "QQr1W",
+ "name": "focus pane",
+ "fill": "#e6ebfa",
+ "cornerRadius": 6,
+ "padding": [
+ 3,
+ 8
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "T7778I",
+ "name": "t",
+ "fill": "$ui-link",
+ "content": "focus pane",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "I0SBO",
+ "name": "Pager",
+ "gap": 20,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "hx5G5",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "X74km",
+ "name": "chevron-left",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-left",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "LuDcm",
+ "name": "of",
+ "fill": "$ui-text-3",
+ "content": "2 of 3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "xxrS8",
+ "name": "Btn",
+ "width": 28,
+ "height": 28,
+ "cornerRadius": 6,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "qmCpC",
+ "name": "chevron-right",
+ "width": 14,
+ "height": 14,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "OujnT",
+ "name": "R",
+ "gap": 16,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "G4SR62",
+ "name": "tag",
+ "fill": "$ui-text-3",
+ "content": "REVIEW GATE !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal",
+ "letterSpacing": 1
+ },
+ {
+ "type": "icon",
+ "id": "F07o1J",
+ "name": "x",
+ "width": 14,
+ "height": 14,
+ "icon": "x",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "v3tCK",
+ "name": "Body",
+ "width": "fill_container",
+ "height": "fill_container",
+ "children": [
+ {
+ "type": "frame",
+ "id": "TBFqy",
+ "name": "Main",
+ "clip": true,
+ "width": "fill_container",
+ "height": "fill_container",
+ "fill": "$ui-panel",
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 28,
+ 28,
+ 40,
+ 28
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "eQkcL",
+ "name": "List head",
+ "width": "fill_container",
+ "padding": [
+ 6,
+ 2,
+ 0,
+ 2
+ ],
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "lMohm",
+ "name": "Left",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "BMarr",
+ "name": "List title",
+ "fill": "$ui-text-1",
+ "content": "Post which findings to !31?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "biCbW",
+ "name": "Right",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "tFMji",
+ "name": "tally",
+ "fill": "$ui-text-3",
+ "content": "5 of 6",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nt7cl",
+ "name": "Card · SQL built from unsanitized input",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O0AvjT",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "gHrYb",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "KRYbB",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "ztFpI",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "N6DxfU",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "ZUP7b",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "g0eUNc",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "SQL built from unsanitized input",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "tfGSj",
+ "x": 225,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "jwU4P",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "TZ0de",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "zqoZb",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "ltbgQ",
+ "name": "sev",
+ "fill": "$ui-crit-label",
+ "content": "Critical",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "igxxs",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Jh5WT",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "xqD2t",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "QzY59",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/db/query.ts:42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "P0Aoaj",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Gk8vU",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-del",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "DPNdL",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "F1jjBQ",
+ "name": "s",
+ "fill": "$ui-del-sign",
+ "content": "-",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "xnJba",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query('SELECT * FROM items LIMIT $1', [limit]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Q4SePP",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "J26srh",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "uHekR",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "NtLp0",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "const rows = await db.query(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Y5Eevm",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JLoNh",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "yAfP2",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "gTiyO",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " `SELECT * FROM items",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RytI0",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "xM9Ec",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "KLE4v",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "jccSI",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " WHERE name LIKE '%${q}%'",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "RwLqE",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "JVVrj",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Wsyra",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "lNUD3",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "OJgNN",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "d7RGII",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "VJKmk",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "UCrho",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LQ8zZ",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "f1kKY3",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "cEX8Q",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "s6M47r",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "qllHE",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "WgLLK",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "veiSK",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "XgEcJ",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "I3w1m",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "qMXJI",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "h744I",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "d5YHh",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "emft7",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "T7IrB",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "StzKf",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Olgra",
+ "name": "Code block",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 6,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QDPH3",
+ "name": "Lang",
+ "width": "fill_container",
+ "fill": "$ui-wash",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "padding": [
+ 4,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "b5tXS",
+ "name": "lang",
+ "fill": "$ui-text-3",
+ "content": "TypeScript",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "MLY8a",
+ "name": "Code",
+ "width": "fill_container",
+ "padding": [
+ 10,
+ 12
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "X0giQ9",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "db",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "DUagj",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ".",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "FpFDw",
+ "name": "tok",
+ "fill": "$ui-accent-text",
+ "content": "query",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "S8bD1",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": "(",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "g3znh",
+ "name": "tok",
+ "fill": "$ui-ok-text",
+ "content": "\"SELECT * FROM items WHERE name = $1\"",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "irCmb",
+ "name": "tok",
+ "fill": "$ui-text-1",
+ "content": ", [q]);",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.5,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "X0XhCo",
+ "name": "Card · Retry loop lacks backoff",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Qzjha",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "EGCrH",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "JtYVE",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "zFr6x",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W6pvW",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "Fv8jT",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "hI7wB",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "n40ZV6",
+ "x": 172,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "Q84mN",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "SpXQy",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "wENQH",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "d7z6v",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "vFYWD",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Qm8af",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "EvdZp",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "m2XFJ",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/retry.ts:41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "RsbQe",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "n18Ku",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "A97Mn",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "38",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "xmkg8",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "BkEHz",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " try {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "o3J1AN",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "O49XLD",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "39",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "zlZDX",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "CBCWG",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " return await job();",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "h0hPc",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "XiCXn",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "wbO7E",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "K5Sm7",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " } catch (err) {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "hKRJ6",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Cr362",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Q6HZ0",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "r3ChwP",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " if (attempt >= attempts) throw err;",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yyv1P",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "q2CSoi",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "ocLxm",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "uTIlj",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " log.warn('retrying', { attempt });",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "i6AWp",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "IfuJ2",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "w2sCd",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XdJNv",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " }",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "yOKku",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Nq0yD",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "bcGOn",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "xZJ9n",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "fwvCV",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "cGMjO",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "GmjsZ",
+ "name": " the loop retries immedi",
+ "fill": "$ui-text-1",
+ "content": " the loop retries immediately up to five times, so one upstream blip turns into six requests.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "idtMw",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "iOK4r",
+ "name": "something like ",
+ "fill": "$ui-text-1",
+ "content": "something like ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "tIrI7",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "XW3NC",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "Math.min(200 * 2 ** attempt, 5000)",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "ArTOD",
+ "name": " would back it off.",
+ "fill": "$ui-text-1",
+ "content": " would back it off.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "kq1SI",
+ "name": "Card · Missing null check on response",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ejrCU",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "r6iaS",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "cKFIz",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "N9hkoH",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "D9MK0j",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "zyJ3M",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "W8k29",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Missing null check on response",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "VfoN0",
+ "x": 221,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "UqxOp",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Wged4",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "K2mrCb",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "zsJbu",
+ "name": "sev",
+ "fill": "$ui-imp-label",
+ "content": "Important",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "usxQm",
+ "name": "File header",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "lInw0",
+ "name": "Toggle",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-right",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "bVHqK",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "zXXFf",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/api/client.ts:88",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Y2RN3N",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "OQw3g",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "I1NNfd",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "F4wiAl",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "W4P9Ge",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "uXyYp",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "oQSkj",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "DfXWp",
+ "name": " a 204 from upstream has",
+ "fill": "$ui-text-1",
+ "content": " a 204 from upstream has no body, so ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "iXoZc",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "f6Ikk",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.json()",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "n2hHkC",
+ "name": " throws before ",
+ "fill": "$ui-text-1",
+ "content": " throws before ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "rSJkO",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "pDD29",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "data.items",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "gdNxb",
+ "name": " is ever read. could thi",
+ "fill": "$ui-text-1",
+ "content": " is ever read.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "MdX3d",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "k28tO",
+ "name": "check ",
+ "fill": "$ui-text-1",
+ "content": "could this check ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "JO9EE",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "AS4AZ",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "res.status",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "oKguj",
+ "name": " first and return an emp",
+ "fill": "$ui-text-1",
+ "content": " first and return an empty list?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "S2qzo",
+ "name": "Card · README still names the old folder",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "vBWJZ",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "MWPhr",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ELKc4",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "XyAPO",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "FKdo2",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "joUGI",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "v6xYWY",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "README still names the old folder",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "W5Gjxm",
+ "x": 237,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "UJhgR",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "W7eic",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "m2Ail",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "YnMK2",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JjGec",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "VbIn6",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "README.md · no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "VENBD",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Xq4fB",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "X0kZC",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "t9Aucn",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "lWkkb",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HFRfR",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "JotmS",
+ "name": " the ",
+ "fill": "$ui-text-1",
+ "content": " the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "f1ksle",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "HkJVQ",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "README.md",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "j5AHn",
+ "name": " still says the scanner ",
+ "fill": "$ui-text-1",
+ "content": " still says the scanner reads ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "TbkTm",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ltJKi",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/jobs",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "pcIei",
+ "name": ". anyone with a local ov",
+ "fill": "$ui-text-1",
+ "content": ". anyone with a local overlay keyed on the",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "OVofR",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "UL9HV",
+ "name": "old paths will get ",
+ "fill": "$ui-text-1",
+ "content": "old paths will get ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "t2HGX1",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "il4rh",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "merged 0/N",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "zUOCz",
+ "name": " with no hint why. could",
+ "fill": "$ui-text-1",
+ "content": " with no hint why. could we add a line about the move?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "NtxS5",
+ "name": "Card · No run for the --changed flag",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "aO3m4",
+ "name": "Head",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "JhhrH",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "UO1HM",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Wvi3b",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "BS87Z",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "lyusQ",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "otnNz",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "No run for the --changed flag",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "siYwW",
+ "x": 207,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "ygEiM",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "wys4A",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "a3jZt0",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "RB1lI",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "UpXNa",
+ "name": "Path row",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 6,
+ "padding": [
+ 6,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "DjTKj",
+ "name": "Path",
+ "fill": "$ui-text-3",
+ "content": "no diff line",
+ "lineHeight": 1.5,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "pMF0C",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "#00000000",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "y0eV6c",
+ "name": "Body row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "nHr7c",
+ "name": "Content",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 8,
+ "children": [
+ {
+ "type": "frame",
+ "id": "kwMWP",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ECH4j",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ROCrq",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "C7RYUL",
+ "name": " thanks for the extra ev",
+ "fill": "$ui-text-1",
+ "content": " thanks for the extra evidence, that covers it nicely. the one AC without a run is ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "dxqTT",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "mNSN1",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "--changed",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GrWeH",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "c6zND6",
+ "name": "picking up a file under ",
+ "fill": "$ui-text-1",
+ "content": "picking up a file under ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "HniO7",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Q1uey",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "lib/tasks/**",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "HhWZI",
+ "name": "... would you mind grabb",
+ "fill": "$ui-text-1",
+ "content": "... would you mind grabbing one quick run of that?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ymPKZ",
+ "name": "Card · Unused import",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "DzLm0",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "kFAeN",
+ "name": "Tick col",
+ "children": [
+ {
+ "type": "frame",
+ "id": "QhWoA",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "c9aG2M",
+ "name": "Text",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 4,
+ "children": [
+ {
+ "type": "frame",
+ "id": "P4gyp",
+ "name": "Title row",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "dnXO3",
+ "name": "Title",
+ "fill": "$ui-text-3",
+ "content": "Unused import",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "LJYSQ",
+ "x": 108,
+ "y": 2.5,
+ "name": "Finding glyph",
+ "enabled": false,
+ "padding": [
+ 1,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "icon",
+ "id": "U6IZmM",
+ "name": "Agent glyph",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "QBWS5",
+ "name": "Severity",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "z2KyX",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "CM91J",
+ "name": "sev",
+ "fill": "$ui-text-3",
+ "content": "Minor",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GnPSI",
+ "name": "Rail",
+ "width": 470,
+ "height": "fill_container",
+ "fill": "$ui-card",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "left": 1
+ },
+ "layout": "vertical",
+ "gap": 14,
+ "padding": [
+ 22,
+ 26
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "ygAkt",
+ "name": "Rail scroll",
+ "clip": true,
+ "width": "fill_container",
+ "height": "fill_container",
+ "layout": "vertical",
+ "gap": 14,
+ "children": [
+ {
+ "type": "frame",
+ "id": "PLy5S",
+ "name": "MR card",
+ "width": "fill_container",
+ "fill": "#fbfbfc",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 4,
+ "padding": [
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "Vxgux",
+ "name": "Who",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "g3d8iv",
+ "name": "Avatar",
+ "fill": "#d6409f",
+ "width": 16,
+ "height": 16
+ },
+ {
+ "type": "text",
+ "id": "GdDZc",
+ "name": "Name",
+ "fill": "#8e4ec6",
+ "content": "Paul",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "xcP98",
+ "name": "v",
+ "fill": "$ui-text-1",
+ "content": "opened",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "YHMKF",
+ "name": "ref",
+ "fill": "$ui-accent-text",
+ "content": "!31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "dZ1RV",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "into main",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "a5L7Re",
+ "name": "MR title",
+ "fill": "$ui-text-1",
+ "content": "themed gate controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "yTRmg",
+ "name": "Sub",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "KuQ6P",
+ "name": "age",
+ "fill": "$ui-text-3",
+ "content": "41d",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "jeNa6",
+ "name": "add",
+ "fill": "$ui-ok-text",
+ "content": "+84",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "QnMIc",
+ "name": "del",
+ "fill": "$ui-del-sign",
+ "content": "-21",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "o4tkcB",
+ "name": "br",
+ "fill": "$ui-text-3",
+ "content": "· board-28-themed-gate-controls",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "euvLG",
+ "name": "Decision context",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "L46s1d",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "DECISION CONTEXT",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal",
+ "letterSpacing": 0.8
+ },
+ {
+ "type": "text",
+ "id": "bvE2H",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Ready to merge: with fixes",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "f048Y",
+ "name": "Summary",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Clean, well-scoped fix for the search handler. Parameterizing the query closes the injection path, and the retry and null-check notes are small. The evidence covers every AC but --changed.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "SPxI8",
+ "name": "who",
+ "fill": "$ui-text-3",
+ "content": "renee",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "yr00k",
+ "name": "Tiers",
+ "gap": 14,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "AYKF1",
+ "name": "Critical",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "J0ESS",
+ "name": "dot",
+ "fill": "$ui-crit",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "iAW07",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Critical",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "N77hKt",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qKFzL",
+ "name": "Important",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "ea9gf",
+ "name": "dot",
+ "fill": "$ui-imp",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "fbyGG",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Important",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "jrJ7O",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GcRck",
+ "name": "Minor",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "H1JtX",
+ "name": "dot",
+ "fill": "#8b8d98",
+ "width": 8,
+ "height": 8
+ },
+ {
+ "type": "text",
+ "id": "FQOdg",
+ "name": "n",
+ "fill": "$ui-text-1",
+ "content": "Minor",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "500"
+ },
+ {
+ "type": "text",
+ "id": "G9RmV",
+ "name": "c",
+ "fill": "$ui-text-3",
+ "content": "3",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "a9nYeq",
+ "name": "Checks",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "dOtGP",
+ "name": "Head",
+ "width": "fill_container",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "YqqyH",
+ "name": "t",
+ "fill": "$ui-text-3",
+ "content": "checks",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "b9Mxjw",
+ "name": "tally",
+ "fill": "$ui-text-3",
+ "content": "2 pass · 1 fail · 1 n/a",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "J67FD",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "icon",
+ "id": "xHsZc",
+ "name": "expand",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "B5DBYj",
+ "name": "Fail row",
+ "width": "fill_container",
+ "gap": 10,
+ "children": [
+ {
+ "type": "frame",
+ "id": "PgW5R",
+ "name": "Chip",
+ "width": 46,
+ "cornerRadius": 4,
+ "stroke": "$ui-del-sign",
+ "strokeWidth": 1,
+ "padding": [
+ 1,
+ 0
+ ],
+ "justifyContent": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "coeDy",
+ "name": "t",
+ "fill": "$ui-del-sign",
+ "content": "FAIL",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "p4VfPj",
+ "name": "txt",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "preview e2e search-flow spec times out on the empty-query case; looks unrelated, rerun before merge",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JIa0f",
+ "name": "Dock",
+ "width": "fill_container",
+ "stroke": "$ui-border",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 10,
+ "padding": [
+ 16,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "O00bf",
+ "name": "Dock head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "wmRc4",
+ "name": "h",
+ "fill": "$ui-text-1",
+ "content": "Verdict on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "UGACM",
+ "name": "Right",
+ "gap": 8,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "fZsxF",
+ "name": "note",
+ "fill": "$ui-accent-text",
+ "content": "add note",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "cU0SF",
+ "name": "Options",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 2,
+ "children": [
+ {
+ "type": "frame",
+ "id": "aY44N",
+ "name": "Opt comment",
+ "width": "fill_container",
+ "fill": "#eef2fd",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "y6L8D4",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "$ui-accent-fill",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "ellipse",
+ "id": "CEz5I",
+ "name": "Dot",
+ "fill": "$ui-accent-fill",
+ "width": 7,
+ "height": 7
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "I5JOJ",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "frame",
+ "id": "oL8nW",
+ "name": "Rec",
+ "cornerRadius": 3,
+ "stroke": "$ui-ok-text",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 5
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "Ff0nl",
+ "name": "t",
+ "fill": "$ui-ok-text",
+ "content": "RECOMMENDED",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 9.5,
+ "fontWeight": "normal",
+ "letterSpacing": 0.5
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "KHmRY",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "no verdict",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "qyoKp",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "w34Bk",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "w32Jx",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "1",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Je9Vd",
+ "name": "Opt approve",
+ "width": "fill_container",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 6,
+ 8
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "givCM",
+ "name": "Radio",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-card",
+ "cornerRadius": 7.5,
+ "stroke": "#b9bbc6",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ {
+ "type": "text",
+ "id": "x77BBq",
+ "name": "l",
+ "fill": "$ui-text-1",
+ "content": "approve",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14
+ },
+ {
+ "type": "text",
+ "id": "IkAH2",
+ "name": "d",
+ "fill": "#8b8d98",
+ "content": "approves !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "CcX4R",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "k7pTwy",
+ "name": "Key",
+ "width": 16,
+ "height": 16,
+ "cornerRadius": 3,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "fjYQd",
+ "name": "k",
+ "fill": "$ui-text-3",
+ "content": "2",
+ "lineHeight": 1.2,
+ "fontFamily": "Inter",
+ "fontSize": 10,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Oxq9U",
+ "name": "Summary",
+ "width": "fill_container",
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 4,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "BfT1m",
+ "name": "Head",
+ "width": "fill_container",
+ "justifyContent": "space_between",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "CtLwA",
+ "name": "t",
+ "fill": "$ui-text-1",
+ "content": "Summary comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "bAZ4c",
+ "name": "m",
+ "fill": "$ui-text-3",
+ "content": "posts on !31",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "k448bo",
+ "name": "Comment well",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "cornerRadius": 6,
+ "gap": 10,
+ "padding": [
+ 10,
+ 10,
+ 10,
+ 14
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "y6RJc",
+ "name": "Text",
+ "fill": "$ui-text-1",
+ "textGrowth": "fixed-width",
+ "width": "fill_container",
+ "content": "Thanks for the quick turnaround. The injection fix is the one to land first…",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XukJm",
+ "name": "Submit",
+ "width": "fill_container",
+ "height": 44,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 8,
+ "gap": 10,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "H9tIwe",
+ "name": "l",
+ "fill": "#ffffff",
+ "content": "comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "500"
+ },
+ {
+ "type": "frame",
+ "id": "cg7cl",
+ "name": "Keycap",
+ "fill": "#ffffff33",
+ "cornerRadius": 4,
+ "padding": [
+ 1,
+ 6
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "rb0vM",
+ "name": "k",
+ "fill": "#ffffff",
+ "content": "⌘↵",
+ "lineHeight": 1.3,
+ "fontFamily": "Inter",
+ "fontSize": 11,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HN5PV",
+ "x": 20040,
+ "y": 29089,
+ "name": "Invadr · renee",
+ "reusable": true,
+ "width": 16,
+ "height": 16,
+ "layout": "none",
+ "children": [
+ {
+ "type": "rectangle",
+ "id": "SHpPB",
+ "x": 6.153846153846154,
+ "y": 1.2307692307692308,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "i4uhxe",
+ "x": 8.615384615384617,
+ "y": 1.2307692307692308,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "Ox5Ms",
+ "x": 4.923076923076923,
+ "y": 2.4615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "iDs69",
+ "x": 6.153846153846154,
+ "y": 2.4615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "fzw5y",
+ "x": 7.384615384615385,
+ "y": 2.4615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "xMMtf",
+ "x": 8.615384615384617,
+ "y": 2.4615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "v4y8OI",
+ "x": 9.846153846153847,
+ "y": 2.4615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "Uc87c",
+ "x": 3.6923076923076925,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "iQDIS",
+ "x": 4.923076923076923,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "e43fdR",
+ "x": 6.153846153846154,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "Rz6Ti",
+ "x": 7.384615384615385,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "q3why",
+ "x": 8.615384615384617,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "FWUNE",
+ "x": 9.846153846153847,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "E44xaf",
+ "x": 11.076923076923077,
+ "y": 3.6923076923076925,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "xtHTn",
+ "x": 2.4615384615384617,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "DRdaI",
+ "x": 3.6923076923076925,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "zEWNo",
+ "x": 6.153846153846154,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "lnihX",
+ "x": 7.384615384615385,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "jTQAS",
+ "x": 8.615384615384617,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "fXjek",
+ "x": 11.076923076923077,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "FS0YS",
+ "x": 12.307692307692308,
+ "y": 4.923076923076923,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "sQGOh",
+ "x": 2.4615384615384617,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "VxmWF",
+ "x": 3.6923076923076925,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "ab1Yu",
+ "x": 4.923076923076923,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "sEcRb",
+ "x": 6.153846153846154,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "Y47pM",
+ "x": 7.384615384615385,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "lTLsR",
+ "x": 8.615384615384617,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "QrjlI",
+ "x": 9.846153846153847,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "UjO0e",
+ "x": 11.076923076923077,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "uV3CY",
+ "x": 12.307692307692308,
+ "y": 6.153846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "ZmKd7",
+ "x": 2.4615384615384617,
+ "y": 7.384615384615385,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "QcogS",
+ "x": 4.923076923076923,
+ "y": 7.384615384615385,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "t1nN5",
+ "x": 7.384615384615385,
+ "y": 7.384615384615385,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "aEuLw",
+ "x": 9.846153846153847,
+ "y": 7.384615384615385,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "B0qLE2",
+ "x": 12.307692307692308,
+ "y": 7.384615384615385,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "RShET",
+ "x": 2.4615384615384617,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "FFJVT",
+ "x": 3.6923076923076925,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "F2VLg2",
+ "x": 4.923076923076923,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "n9SSw",
+ "x": 6.153846153846154,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "hHATU",
+ "x": 7.384615384615385,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "i7LSx",
+ "x": 8.615384615384617,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "K0RqE6",
+ "x": 9.846153846153847,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "hQ5BD",
+ "x": 11.076923076923077,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "f7srs",
+ "x": 12.307692307692308,
+ "y": 8.615384615384617,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "HQPgn",
+ "x": 3.6923076923076925,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "RZSjd",
+ "x": 4.923076923076923,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "dE5J2",
+ "x": 6.153846153846154,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "U0MUv",
+ "x": 7.384615384615385,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "jFQ8t",
+ "x": 8.615384615384617,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "Y4RSQ",
+ "x": 9.846153846153847,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "K0gB2I",
+ "x": 11.076923076923077,
+ "y": 9.846153846153847,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "dIrZ7",
+ "x": 3.6923076923076925,
+ "y": 11.076923076923077,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "y90Xxy",
+ "x": 11.076923076923077,
+ "y": 11.076923076923077,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "hYnmU",
+ "x": 3.6923076923076925,
+ "y": 12.307692307692308,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "O384r",
+ "x": 11.076923076923077,
+ "y": 12.307692307692308,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "BFoU0",
+ "x": 2.4615384615384617,
+ "y": 13.53846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "h5mWSv",
+ "x": 3.6923076923076925,
+ "y": 13.53846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "H2OSQd",
+ "x": 11.076923076923077,
+ "y": 13.53846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ },
+ {
+ "type": "rectangle",
+ "id": "d1ZhoG",
+ "x": 12.307692307692308,
+ "y": 13.53846153846154,
+ "name": "px",
+ "fill": "#1d8fbf",
+ "width": 1.2807692307692309,
+ "height": 1.2807692307692309
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "A57gqY",
+ "x": 21600,
+ "y": 32042,
+ "name": "B33 · One box per finding",
+ "fill": "$ui-panel",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "cxHxr",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B33 · One box per finding",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "fsN92",
+ "name": "Row",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "PxZbx",
+ "name": "A · The title is the box's top row",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "N69kPw",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "n6UE4y",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "A · The title is the box's top row",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "g3GMt",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Card, file bar, diff, comment: one border",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AHct2",
+ "name": "Finding box",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "c8pHd",
+ "name": "Title row",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 10,
+ "padding": [
+ 11,
+ 14
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "CBIAp",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "zrKaE",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "uHnMr",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "icon",
+ "id": "dKKtq",
+ "name": "bot",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eWT5z",
+ "name": "File bar",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "MsdXX",
+ "name": "chevron-down",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "x9BYV",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "FHVIa",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/retry.ts:41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nxcTJ",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "S6nLz",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "38",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "V2PK2",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "GY9Er",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " try {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ORZ7j",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "U91FN",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "39",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "R0Cgod",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "PUThD",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " return await job();",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EWTaw",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "j4gHt",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "OUzcl",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Y7KC9r",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " } catch (err) {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "Arwvr",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "ioP6t",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "A9RbC",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Q9OBE",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " if (attempt >= attempts) throw err;",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L1vZrZ",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "gFnBY",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "OStvm",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "LoonQ",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " log.warn('retrying', { attempt });",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GT60w",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "rWYB2",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "GBLOh",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "R7XOe",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " }",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "ZsLbe",
+ "name": "Comment",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "w1dIkR",
+ "name": "Author",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "id": "C7eWh",
+ "type": "ref",
+ "ref": "HN5PV",
+ "name": "Avatar"
+ },
+ {
+ "type": "text",
+ "id": "m4qL0p",
+ "name": "u",
+ "fill": "$ui-text-1",
+ "content": "renee",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "600"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YnQdj",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "wUai7",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "K7QMC",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "POi95",
+ "name": " the loop retries immedi",
+ "fill": "$ui-text-1",
+ "content": " the loop retries immediately up to five times, so one upstream blip turns into six requests.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "VANNn",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "H6fzEu",
+ "name": "something like ",
+ "fill": "$ui-text-1",
+ "content": "something like ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "jSdM0",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "EFCFk",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "Math.min(200 * 2 ** attempt, 5000)",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "XBMiQ",
+ "name": " would back it off.",
+ "fill": "$ui-text-1",
+ "content": " would back it off.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "t57XF",
+ "name": "B · No card, just the box",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "JNmvq",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "UQnvH",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "B · No card, just the box",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "L3qsBE",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Title sits on the page, the box holds code and comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "YSRws",
+ "name": "Title row",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": 2,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "h8nbGI",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "giNd0",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "z5IxPZ",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Retry loop lacks backoff",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "icon",
+ "id": "O4W3e",
+ "name": "bot",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "WQV1R",
+ "name": "Code and comment",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "v2bQ4",
+ "name": "File bar",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "bottom": 1
+ },
+ "gap": 8,
+ "padding": [
+ 6,
+ 10
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Vspek",
+ "name": "chevron-down",
+ "width": 13,
+ "height": 13,
+ "icon": "chevron-down",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "icon",
+ "id": "S1R3Jb",
+ "name": "file",
+ "width": 12,
+ "height": 12,
+ "icon": "file",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ },
+ {
+ "type": "text",
+ "id": "GpMqS",
+ "name": "Path",
+ "fill": "$ui-text-1",
+ "content": "lib/retry.ts:41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XUI2q",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "UW9Mb",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "38",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "R3U7lX",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "R96fi",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " try {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "nxwuC",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "M6sJ5z",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "39",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "vn8lr",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "DFfxz",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " return await job();",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "l2m9uF",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "d4pNq",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "40",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "Zb4YY",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "tnjJN",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " } catch (err) {",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "KnhUi",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-anchor",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "azmns",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "41",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "U80wG5",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "lE90Y",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " if (attempt >= attempts) throw err;",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "d60OzS",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "AuWQT",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "42",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "oq0qV",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "g19Mv",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " log.warn('retrying', { attempt });",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "k0XGGm",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "rtw9V",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "XISHo",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "QW8IG",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " }",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "DkPUz",
+ "name": "Comment",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "gap": 6,
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "n50TGb",
+ "name": "Author",
+ "gap": 6,
+ "alignItems": "center",
+ "children": [
+ {
+ "id": "Y8oJ4H",
+ "type": "ref",
+ "ref": "HN5PV",
+ "name": "Avatar"
+ },
+ {
+ "type": "text",
+ "id": "ebJQw",
+ "name": "u",
+ "fill": "$ui-text-1",
+ "content": "renee",
+ "lineHeight": 1.4,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "600"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "S7498S",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "R9SDHs",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Hx4oj",
+ "name": "suggestion:",
+ "fill": "$ui-text-1",
+ "content": "suggestion:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "CNNsR",
+ "name": " the loop retries immedi",
+ "fill": "$ui-text-1",
+ "content": " the loop retries immediately up to five times, so one upstream blip turns into six requests.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "pw5Lv",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "nFCHl",
+ "name": "something like ",
+ "fill": "$ui-text-1",
+ "content": "something like ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "H3Zr2v",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "Q7hygb",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "Math.min(200 * 2 ** attempt, 5000)",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "hIK2r",
+ "name": " would back it off.",
+ "fill": "$ui-text-1",
+ "content": " would back it off.",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "iHbZ1",
+ "name": "Next title",
+ "width": "fill_container",
+ "gap": 10,
+ "padding": [
+ 14,
+ 2,
+ 2,
+ 2
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Ncx8N",
+ "name": "Tick",
+ "width": 15,
+ "height": 15,
+ "fill": "$ui-accent-fill",
+ "cornerRadius": 3,
+ "justifyContent": "center",
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "icon",
+ "id": "Ipdwb",
+ "name": "check",
+ "width": 11,
+ "height": 11,
+ "icon": "check",
+ "library": "lucide",
+ "fill": "#ffffff"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "MSP2u",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "Missing null check on response",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "600"
+ },
+ {
+ "type": "icon",
+ "id": "F9H2z",
+ "name": "bot",
+ "width": 15,
+ "height": 15,
+ "icon": "bot",
+ "library": "lucide",
+ "fill": "$ui-text-3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "y9FPZK",
+ "x": 21600,
+ "y": 32659,
+ "name": "B34 · Who wrote the comment",
+ "fill": "$ui-panel",
+ "layout": "vertical",
+ "gap": 24,
+ "padding": 40,
+ "children": [
+ {
+ "type": "text",
+ "id": "dyB9H",
+ "name": "Title",
+ "fill": "$ui-text-1",
+ "content": "B34 · Who wrote the comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 20,
+ "fontWeight": "700"
+ },
+ {
+ "type": "frame",
+ "id": "ehAID",
+ "name": "Row 1",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "sEl0l",
+ "name": "1 · Byline on the right",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "a2lC0",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "kg2x4",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "1 · Byline on the right",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "sX6Vb",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Like a timestamp, nothing above the text",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "pfgQG",
+ "name": "Box",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "M7gpM",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "S58IWQ",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "M5Du9R",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "ZrFyb",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "GwnRI",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "VPMg4",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "bD68W",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "R48Y5",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "eKJef",
+ "name": "Comment",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "JCd27",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "ulTdo",
+ "name": "Line",
+ "width": "fill_container",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "fRbLS",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "nU04p",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Zq2Jq",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "JdFpn",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "JiCPx",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "b4FzGv",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "M8wg2d",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "aFjYt",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "euSyM",
+ "name": "sp",
+ "width": "fill_container",
+ "height": 1
+ },
+ {
+ "type": "frame",
+ "id": "nL8K3",
+ "name": "Byline",
+ "fill": "$ui-panel",
+ "cornerRadius": 12,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "gap": 6,
+ "padding": [
+ 3,
+ 10,
+ 3,
+ 5
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "id": "EVvNN",
+ "type": "ref",
+ "ref": "HN5PV",
+ "name": "Avatar"
+ },
+ {
+ "type": "text",
+ "id": "koKz9",
+ "name": "u",
+ "fill": "$ui-text-1",
+ "content": "renee",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 12,
+ "fontWeight": "500"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "rcKu3",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "L7wpet",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "AsPTS",
+ "name": "2 · Avatar in the gutter",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "nfit2",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "G5626y",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "2 · Avatar in the gutter",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "Rdp10",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "Avatar beside the comment, no name",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "XiNDR",
+ "name": "Box",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "jjule",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "KVFJ6",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "C42HHY",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "USmSE",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "tQUTH",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "gOtGU",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "LgJch",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "xVefQ",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "LvERx",
+ "name": "Comment",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "gap": 12,
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "U2k0J",
+ "name": "Gutter",
+ "padding": [
+ 2,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "id": "XvAcN",
+ "type": "ref",
+ "ref": "HN5PV",
+ "name": "Avatar"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "lDDpC",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "Lmgud",
+ "name": "Line",
+ "width": "fill_container",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vn7Ox",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "lxw29",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "t7Pge",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "C1SPm5",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "SxKPG",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "UyNr0",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "S966N",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "VjD5J",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "HtcM2",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "lILV7",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U0An36",
+ "name": "Row 2",
+ "gap": 40,
+ "children": [
+ {
+ "type": "frame",
+ "id": "UOjoe",
+ "name": "3 · Speech bubble",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "M5npW",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "cVNlZ",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "3 · Speech bubble",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "Yvy4E",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "The comment is said by the avatar",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "U1HyB",
+ "name": "Box",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "I9KXE",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "v6F00S",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "yi14w",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "oyJl5",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "s0qFC",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "kFSzr",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "QDjMa",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "jDzAT",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "u8z0FU",
+ "name": "Comment",
+ "width": "fill_container",
+ "fill": "$ui-panel",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "gap": 10,
+ "padding": [
+ 12,
+ 14,
+ 14,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "ySVWC",
+ "name": "Gutter",
+ "padding": [
+ 8,
+ 0,
+ 0,
+ 0
+ ],
+ "children": [
+ {
+ "id": "fvqYv",
+ "type": "ref",
+ "ref": "HN5PV",
+ "name": "Avatar"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "qSHGb",
+ "name": "Bubble",
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "padding": [
+ 8,
+ 12
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "G1jQo",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "mFPx7",
+ "name": "Line",
+ "width": "fill_container",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "a8oWi",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "wUDQH",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "W3oSn",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "S3k90",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Y0Fncu",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "Cti79",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "trNFd",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "fP4sJ",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "EH8gS",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "DZZem",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "L6asC",
+ "name": "4 · No attribution",
+ "width": 860,
+ "layout": "vertical",
+ "gap": 12,
+ "children": [
+ {
+ "type": "frame",
+ "id": "dW58k",
+ "name": "Label",
+ "gap": 10,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "vFR7j",
+ "name": "Label",
+ "fill": "$ui-text-1",
+ "content": "4 · No attribution",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 15,
+ "fontWeight": "600"
+ },
+ {
+ "type": "text",
+ "id": "P4x3yA",
+ "name": "Note",
+ "fill": "$ui-text-3",
+ "content": "It's always your comment",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 13,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "JjYYZ",
+ "name": "Box",
+ "clip": true,
+ "width": "fill_container",
+ "fill": "$ui-card",
+ "cornerRadius": 8,
+ "stroke": "$ui-border",
+ "strokeWidth": 1,
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "LzZ4N",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "zu240",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "43",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "P8JX2",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "cCRo7",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": " LIMIT ${limit}`",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "OHzyY",
+ "name": "Line",
+ "width": "fill_container",
+ "fill": "$ui-add",
+ "gap": 10,
+ "padding": [
+ 2,
+ 10
+ ],
+ "children": [
+ {
+ "type": "text",
+ "id": "KCnZX",
+ "name": "n",
+ "fill": "$ui-text-3",
+ "content": "44",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "FbWjC",
+ "name": "s",
+ "fill": "$ui-add-sign",
+ "content": "+",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "text",
+ "id": "BuDw6",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": ");",
+ "lineHeight": 1.4,
+ "fontFamily": "$font-mono",
+ "fontSize": 12,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "QRkst",
+ "name": "Comment",
+ "width": "fill_container",
+ "stroke": "$ui-border-soft",
+ "strokeWidth": {
+ "top": 1
+ },
+ "layout": "vertical",
+ "padding": [
+ 10,
+ 14,
+ 12,
+ 14
+ ],
+ "children": [
+ {
+ "type": "frame",
+ "id": "MWkCg",
+ "name": "Rich",
+ "width": "fill_container",
+ "layout": "vertical",
+ "children": [
+ {
+ "type": "frame",
+ "id": "O1Zdo",
+ "name": "Line",
+ "width": "fill_container",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "ytflA",
+ "name": "issue:",
+ "fill": "$ui-text-1",
+ "content": "issue:",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "700"
+ },
+ {
+ "type": "text",
+ "id": "rq5bF",
+ "name": " the search handler drop",
+ "fill": "$ui-text-1",
+ "content": " the search handler drops the raw ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "fIqlP",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "AtE2j",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "q",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "yDDnj",
+ "name": " straight into the ",
+ "fill": "$ui-text-1",
+ "content": " straight into the ",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ },
+ {
+ "type": "frame",
+ "id": "lSCEV",
+ "name": "Code chip",
+ "fill": "$ui-wash",
+ "cornerRadius": 4,
+ "stroke": "$ui-border-soft",
+ "strokeWidth": 1,
+ "padding": [
+ 0,
+ 4
+ ],
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "qOJi4",
+ "name": "code",
+ "fill": "$ui-text-1",
+ "content": "WHERE",
+ "lineHeight": 1.3,
+ "fontFamily": "$font-mono",
+ "fontSize": 12.3,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "text",
+ "id": "Vn0Tt",
+ "name": " clause, so a crafted qu",
+ "fill": "$ui-text-1",
+ "content": " clause, so a crafted query",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ },
+ {
+ "type": "frame",
+ "id": "r8vT8l",
+ "name": "Line",
+ "height": 21,
+ "alignItems": "center",
+ "children": [
+ {
+ "type": "text",
+ "id": "zOenZ",
+ "name": "string reaches the datab",
+ "fill": "$ui-text-1",
+ "content": "string reaches the database as SQL. could this use a bound parameter?",
+ "lineHeight": 1.5,
+ "fontFamily": "Inter",
+ "fontSize": 14,
+ "fontWeight": "normal"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "themes": {
+ "mode": [
+ "light",
+ "dark"
+ ]
+ },
+ "variables": {
+ "bg": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#f7f8fa",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#16161e",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "inset": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#ffffff",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#1c2136",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "panel": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#fbfbfc",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#232a47",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "card": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#ffffff",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#2c3352",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "hover": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#f0f4fb",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#242b48",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "fg": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#222222",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#e3e7f6",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "muted": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#565d80",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#969ec2",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "dim": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#8990b3",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7e86ad",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "border": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#c8cad6",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#3b4261",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "border-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#d5d7e2",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#313853",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "accent": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#2e7de9",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7aa2f7",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "accent-text": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#1c5fbf",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7aa2f7",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "green": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#587539",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#9ece6a",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "red": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#c8214f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#f7768e",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "amber": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#8c6c3e",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#e0af68",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "purple": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#7847bd",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#bb9af7",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "cyan": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#007197",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7dcfff",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "dot-ok": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#1f9d3a",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#4ade5b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "dot-warn": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#e08a00",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#ffbb3d",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "dot-bad": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#e5153f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#ff5c72",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "green-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#5875391f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#9ece6a2b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "red-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#c8214f1f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#f7768e2b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "amber-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#8c6c3e1f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#e0af682b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "purple-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#7847bd1f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#bb9af72b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "accent-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#2e7de91f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7aa2f72b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "cyan-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#0071971f",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#7dcfff2b",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "muted-soft": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#565d801a",
+ "theme": {
+ "mode": "light"
+ }
+ },
+ {
+ "value": "#969ec226",
+ "theme": {
+ "mode": "dark"
+ }
+ }
+ ]
+ },
+ "font-sans": {
+ "type": "string",
+ "value": "Inter"
+ },
+ "font-mono": {
+ "type": "string",
+ "value": "JetBrains Mono"
+ },
+ "orange": {
+ "type": "color",
+ "value": [
+ {
+ "value": "#b15c00",
+ "theme": {
"mode": "light"
}
},
@@ -587323,6 +618652,110 @@
}
}
]
+ },
+ "ui-page": {
+ "type": "color",
+ "value": "#f0f0f3"
+ },
+ "ui-card": {
+ "type": "color",
+ "value": "#ffffff"
+ },
+ "ui-border": {
+ "type": "color",
+ "value": "#cdced6"
+ },
+ "ui-border-soft": {
+ "type": "color",
+ "value": "#d9d9e0"
+ },
+ "ui-text-1": {
+ "type": "color",
+ "value": "#1c2024"
+ },
+ "ui-text-3": {
+ "type": "color",
+ "value": "#60646c"
+ },
+ "ui-wash": {
+ "type": "color",
+ "value": "#f6f6f6"
+ },
+ "ui-accent-text": {
+ "type": "color",
+ "value": "#3a5bc7"
+ },
+ "ui-accent-fill": {
+ "type": "color",
+ "value": "#3e63dd"
+ },
+ "ui-link": {
+ "type": "color",
+ "value": "#1f2d5c"
+ },
+ "ui-ok-text": {
+ "type": "color",
+ "value": "#008573"
+ },
+ "ui-crit-bg": {
+ "type": "color",
+ "value": "#e93d8226"
+ },
+ "ui-crit-text": {
+ "type": "color",
+ "value": "#621639"
+ },
+ "ui-crit": {
+ "type": "color",
+ "value": "#e5484d"
+ },
+ "ui-imp-bg": {
+ "type": "color",
+ "value": "#ef5f0017"
+ },
+ "ui-imp-text": {
+ "type": "color",
+ "value": "#af4300"
+ },
+ "ui-imp": {
+ "type": "color",
+ "value": "#ffb224"
+ },
+ "ui-minor-bg": {
+ "type": "color",
+ "value": "#1c202412"
+ },
+ "ui-add": {
+ "type": "color",
+ "value": "#edf6f4"
+ },
+ "ui-del": {
+ "type": "color",
+ "value": "#ffeff3"
+ },
+ "ui-anchor": {
+ "type": "color",
+ "value": "#d8e0f8"
+ },
+ "ui-add-sign": {
+ "type": "color",
+ "value": "#008573"
+ },
+ "ui-del-sign": {
+ "type": "color",
+ "value": "#ce2c31"
+ },
+ "ui-panel": {
+ "type": "color",
+ "value": "#f9f9fb"
+ },
+ "ui-crit-label": {
+ "type": "color",
+ "value": "#ce2c31"
+ },
+ "ui-imp-label": {
+ "type": "color",
+ "value": "#ab6400"
}
},
"fileToken": "742ad691-e2f8-4a13-ad05-12d10ca28147"