agentgui 1.0.959 → 1.0.961

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ export const meta = {
2
+ name: 'gui-claude-code-parity',
3
+ description: 'Drive a maximum-effort DESIGN-LANGUAGE parity sweep of the agentgui GUI toward claude.ai/code (Claude Code web GUI), with cowork and Claude Desktop as secondary bars: per-lens designer agents benchmark the SHIPPED visual+layout+motion language against the real reference products, an adversarial verifier confirms each gap against the live source (kept-typography guard), a synthesizer orders them into a dependency-aware kit-vs-app-vs-server build plan. The user verdict driving this run: the UI is too primitive and the layout is jank - it must LOOK and FEEL like a chat agent / Claude Code web GUI.',
4
+ whenToUse: 'Run after the logic-predictability sweep (9th run) has landed. Distinct from all six prior workflows: gui-audit hunts JANK, gui-overhaul DESIGNS new surfaces, gui-predictability-polish polishes primitives, gui-cohesion hunts one-product feel, gui-completion hunts scoped-out coverage, gui-logic-predictability audits operating logic. This one hunts the VISUAL + LAYOUT + MOTION DESIGN-LANGUAGE PARITY gap - whether the calm desktop aesthetic, the column composition and density, the chat-thread craft, the file-browser fidelity, the live-session command-center feel, and the microinteraction polish read as a Claude-Code-web-class product rather than a primitive kit of parts. Reference bars: claude.ai/code (primary), cowork, Claude Desktop, c:\\dev\\fsbrowse (file view). All visual/component work lands in c:\\dev\\anentrypoint-design; the app keeps wiring; no new index.html !important overrides; server changes stay confineToRoots-confined.',
5
+ phases: [
6
+ { title: 'Hunt', detail: 'one designer agent per design-language lens benchmarks the shipped source against the Claude-Code-web bar' },
7
+ { title: 'Verify', detail: 'adversarially confirm each gap is real, unshipped, and soundly fixable (kept-typography guard)' },
8
+ { title: 'Plan', detail: 'synthesize confirmed gaps into a dependency-ordered kit-vs-app-vs-server build plan' },
9
+ ],
10
+ };
11
+
12
+ // Shared grounding. Nine sweeps have shipped; this one hunts whether what shipped LOOKS and FEELS like the Claude Code web GUI.
13
+ const GROUND =
14
+ ' GROUND IN REAL SOURCE (read, do not guess - nine sweeps HAVE shipped: jank audit, redesign, polish, cohesion, completion, logic-predictability; the app already has a three-column WorkspaceShell, a ConversationList rail, a full-CRUD Files manager, a SessionDashboard live view, a ContextPane, structured tool cards, per-block code copy, hash routing, edit/retry/export/followups): agentgui front-end c:\\dev\\agentgui\\site\\app\\js\\app.js + backend.js + index.html; kit c:\\dev\\anentrypoint-design\\src\\components\\{shell.js,sessions.js,agent-chat.js,chat.js,files.js,files-modals.js,context-pane.js,content.js,form-primitives.js,theme-toggle.js} + dist CSS {app-shell.css,chat.css}; server c:\\dev\\agentgui\\lib\\http-handler.js + server.js; the fsbrowse reference is c:\\dev\\fsbrowse. AGENTS.md + the PUNCHLIST-*.md files record what already landed - do NOT re-report it; hunt what still looks primitive or feels un-Claude-Code.' +
15
+ ' POLICY: fully-destructive run - reshape anything; ALL visual/component/layout work lands in the KIT as defaults/props/CSS; the app keeps state+callback wiring only; NEVER add new index.html !important overrides; use kit design tokens (CSS vars) not raw hex; NO decorative glyphs (ASCII words + CSS .status-dot-disc) but KEEP the typographic set middot/ellipsis/em-en-dash; any server mutation stays confineToRoots realpath-confined; every visual change must preserve a11y (roles/aria/focus rings/44x44 touch/keyboard), responsive behavior (420px to wide desktop, no h-scroll), reduced-motion guards on any new animation, and explicit empty/loading/error composition.';
16
+
17
+ const LENSES = [
18
+ { key: 'visual-language', prompt: 'DESIGN-LANGUAGE LENS - VISUAL SYSTEM. Benchmark the SHIPPED visual language against claude.ai/code (the Claude Code web GUI) as the primary bar. Audit the kit token system end to end: color (surface/background layering, border subtlety, accent restraint - Claude Code is calm and low-chroma, not a primitive high-contrast slab), elevation (are panels distinguished by subtle background + hairline borders, or by heavy shadows / no separation at all?), radius scale (consistent corner language across cards/buttons/inputs/dialogs?), typography (display vs body vs mono families, the TYPE SCALE - is there a real modular scale or arbitrary sizes? line-height for reading comfort? font-weight hierarchy for headings vs meta?), spacing rhythm (is there an 4/8px spacing system or ad-hoc margins? consistent padding inside cards/rows/panels?), and the status-disc/rail-tone color semantics. Hunt: places that read PRIMITIVE - unstyled-looking inputs, borders that are too heavy or missing, accent overused, type that is all one size, cramped or inconsistent padding, hardcoded hex instead of tokens. Name every gap with the concrete kit token/CSS fix and the claude.ai/code reference it matches.' + GROUND },
19
+ { key: 'layout-composition', prompt: 'DESIGN-LANGUAGE LENS - LAYOUT COMPOSITION (the user said the layout is JANK). Benchmark the three-column WorkspaceShell composition against claude.ai/code and Claude Desktop. Audit: column proportions (rail / sessions / main / pane widths - do they feel balanced and intentional, or arbitrary? does the chat thread get a comfortable reading measure, ~70ch, or sprawl edge to edge?), the grid track stability across tabs (does geometry jump when switching chat<->files<->live?), vertical rhythm (header/crumb/toolbar/content/composer stacking - aligned baselines? consistent gutters?), density (is whitespace generous and calm like Claude Code, or cramped/primitive?), the rail design (icon+label vs label-only, active-state treatment, footer), how empty and loading states COMPOSE within the grid (do they fill the space gracefully or leave a tiny widget floating in a void?), sticky headers/composers, and the responsive collapse choreography (rail->drawer, pane->hidden at breakpoints - smooth and predictable?). Hunt every place the layout reads jank: misaligned edges, inconsistent gutters, a pane that collapses to dead space, a thread that is too wide to read, a composer that floats. Name every gap with the concrete shell.js / app-shell.css fix and the reference layout it should match.' + GROUND },
20
+ { key: 'chat-thread-craft', prompt: 'DESIGN-LANGUAGE LENS - CHAT THREAD CRAFT (must read like a chat agent). Benchmark the AgentChat thread against claude.ai/code and Claude Desktop chat. Audit: turn presentation (full-width rows with a clear user-vs-assistant distinction via alignment/background/avatar, or undifferentiated blocks? is the user turn visually distinct from the assistant turn?), avatars/role labels, turn separators and spacing between turns (breathing room, not a wall of text), the streaming experience (caret, working tail, smooth append without reflow jank), code block craft (header with language + copy, syntax theme matching the calm aesthetic, horizontal scroll handling, NOT a primitive gray box), inline markdown polish (headings/lists/tables/blockquotes/links styled with care), tool-call cards (collapsible, scannable, status-clear - do they read as first-class or as raw dumps?), the composer presentation (rounded, elevated, context line, send/stop affordance placement matching Claude Code), and message actions (copy/retry/edit revealed on hover, consistently placed). Hunt everything that makes the thread read PRIMITIVE rather than like a polished chat agent. Name every gap with the concrete chat.js / agent-chat.js / chat.css fix and the reference it matches.' + GROUND },
21
+ { key: 'file-browser-fidelity', prompt: 'DESIGN-LANGUAGE LENS - FILE BROWSER FIDELITY. Benchmark the Files view against c:\\dev\\fsbrowse (read its server.js + public/) as the file-manager bar, and against Claude Code/Desktop file panes for chrome. Audit: the layout (grid vs list density, column headers, the breadcrumb design, the roots picker), the preview experience (split-view pane vs modal, syntax-highlighted file preview, image preview, prev/next stepping, large-file handling), affordance design (sort headers, filter input, action buttons on rows - revealed tastefully, not cluttered), iconography for file types (ASCII/CSS, no decorative glyphs), permissions/locked indicators, the show-more pattern for big dirs, drag-drop upload affordance, and empty/loading/error composition. Hunt where the file view reads PRIMITIVE vs fsbrowse-grade: cramped rows, weak breadcrumb, modal-only preview where a split pane belongs, no visual file-type distinction, clumsy sort/filter chrome. Name every gap with the concrete files.js / files-modals.js fix and the fsbrowse/Claude-Code reference it matches.' + GROUND },
22
+ { key: 'live-session-command', prompt: 'DESIGN-LANGUAGE LENS - LIVE SESSION COMMAND CENTER (view all live sessions, manage them simultaneously). Benchmark the SessionDashboard against the idea of a Claude-Code/cowork multi-session command center. Audit: card design (does a session card communicate at a glance - agent, model, cwd, status, last activity, current tool, elapsed, cost - without clutter? is the visual hierarchy right?), the grid/density for MANY sessions (does 12+ sessions read as a scannable command center or a messy stack? grouping by status/recency?), status legibility (running vs idle vs stale vs error - instantly distinguishable by the disc + word + accent, color-blind safe?), bulk management (select, stop-selected, stop-all - discoverable and safe with confirms?), the live stream/heartbeat indication (is the dashboard visibly LISTENING even at zero running?), per-card actions (open in live, resume in chat, stop, view events - consistently placed), sort/filter controls, and how a brand-new session appears (motion/placement). Hunt where managing many sessions feels primitive or where you cannot act on several at once gracefully. Name every gap with the concrete sessions.js fix and the command-center reference it matches.' + GROUND },
23
+ { key: 'motion-microinteraction', prompt: 'DESIGN-LANGUAGE LENS - MOTION + MICROINTERACTION POLISH (the difference between primitive and product). Benchmark the interaction polish against claude.ai/code and Claude Desktop. Audit (every new animation MUST be reduced-motion guarded): state transitions (tab switches, drawer open/close, pane collapse - do they animate smoothly or snap jarringly?), hover/focus feedback (rows, buttons, cards, file rows - is there a tasteful hover lift/tint and a visible focus ring, or nothing?), loading craft (skeletons that match the real content shape vs a bare spinner vs a frozen blank?), scroll behavior (smooth scroll-to on jump-to-latest / jump-to-error, scroll anchoring during streaming, sticky elements), button press feedback, the streaming caret and working-tail motion, toast/banner enter/exit, confirm-state arming feedback, copy->copied label flips, and dialog enter/exit. Hunt every place an interaction feels abrupt, dead, or primitive vs the smooth Claude Code feel - AND any animation missing a prefers-reduced-motion guard. Name every gap with the concrete kit CSS/component fix and the reference it matches.' + GROUND },
24
+ ];
25
+
26
+ const GAP_SCHEMA = {
27
+ type: 'object',
28
+ required: ['lens', 'gaps'],
29
+ properties: {
30
+ lens: { type: 'string' },
31
+ gaps: {
32
+ type: 'array',
33
+ items: {
34
+ type: 'object',
35
+ required: ['title', 'where', 'fixLocation', 'fix', 'severity'],
36
+ properties: {
37
+ title: { type: 'string', description: 'the primitive/jank/un-Claude-Code visual or interaction gap' },
38
+ where: { type: 'string', description: 'file:line or component (or "absent")' },
39
+ fixLocation: { type: 'string', enum: ['kit', 'app', 'server', 'kit+app', 'app+server', 'kit+app+server'] },
40
+ fix: { type: 'string', description: 'the concrete change: token/css/component/prop/wiring' },
41
+ benchmark: { type: 'string', description: 'which reference product sets the bar (claude.ai/code, cowork, Claude Desktop, fsbrowse)' },
42
+ severity: { type: 'string', enum: ['high', 'medium', 'low'] },
43
+ keptTypography: { type: 'boolean', description: 'true if this touches the middot/ellipsis/dash set - which must NOT be flagged as a glyph violation' },
44
+ },
45
+ },
46
+ },
47
+ },
48
+ };
49
+
50
+ const VERDICT_SCHEMA = {
51
+ type: 'object',
52
+ required: ['title', 'real', 'reason'],
53
+ properties: {
54
+ title: { type: 'string' },
55
+ real: { type: 'boolean', description: 'true if the gap genuinely exists in the shipped source, is not already shipped, and the fix is sound and lands in the right place' },
56
+ reason: { type: 'string', description: 'why - cite the source you read' },
57
+ },
58
+ };
59
+
60
+ phase('Hunt');
61
+ const verified = await pipeline(
62
+ LENSES,
63
+ (l) => agent(l.prompt, { label: 'hunt:' + l.key, phase: 'Hunt', schema: GAP_SCHEMA }),
64
+ (report, l) => parallel((report?.gaps || []).map((g) => () =>
65
+ agent(
66
+ 'Adversarially verify this Claude-Code-web design-language finding against the REAL source (read the cited files - do not trust the claim). '
67
+ + 'KEPT-TYPOGRAPHY GUARD: middot, ellipsis, em/en-dash are intentional product typography - flagging one of those as a decorative glyph is NOT a real finding (real=false). '
68
+ + 'A finding is real only if the gap genuinely exists in the shipped source AND was not already fixed by a prior sweep (check the PUNCHLIST-*.md files / AGENTS.md) AND the proposed fix is sound, lands in the right place (kit vs app vs server, visual work in the KIT not the app), uses tokens not hex, preserves a11y + reduced-motion + responsive, and any server mutation stays confinement-safe. '
69
+ + 'Reject vague taste-only findings with no concrete source-grounded fix. '
70
+ + 'Finding: ' + JSON.stringify(g),
71
+ { label: 'verify:' + (g.title || '').slice(0, 32), phase: 'Verify', schema: VERDICT_SCHEMA }
72
+ ).then((v) => ({ ...g, lens: report.lens, verdict: v }))
73
+ ))
74
+ );
75
+
76
+ const confirmed = verified.flat().filter(Boolean).filter((g) => g.verdict && g.verdict.real);
77
+ log('confirmed ' + confirmed.length + ' real Claude-Code-parity design-language gaps across ' + LENSES.length + ' lenses');
78
+
79
+ phase('Plan');
80
+ const plan = await agent(
81
+ 'Synthesize these adversarially-confirmed Claude-Code-web design-language gaps into a dependency-ordered build plan for the anentrypoint-design kit + agentgui app + server. '
82
+ + 'Order: server changes first (if any), then kit token/CSS foundations, then kit components (each edited ONCE with all its changes batched), then app wiring, then the single build->vendor->witness step. '
83
+ + 'Group by component so each kit file is touched once; call out which gaps share a component (batch), which are independent (parallelizable), which conflict, and the highest-leverage few that most close the too-primitive / layout-jank verdict. '
84
+ + 'Confirmed gaps: ' + JSON.stringify(confirmed),
85
+ { label: 'synthesize-plan', phase: 'Plan' }
86
+ );
87
+
88
+ return { confirmed, plan, lensCount: LENSES.length, confirmedCount: confirmed.length };
@@ -0,0 +1,88 @@
1
+ export const meta = {
2
+ name: 'gui-logic-predictability',
3
+ description: 'Drive a maximum-effort LOGIC + PREDICTABILITY sweep of the agentgui GUI: per-lens agents audit whether every element is presented and operates in the most logical, predictable way (interaction state machines, cross-surface consistency, information architecture, realtime truth, input ergonomics, scale robustness), an adversarial verifier confirms each finding against the live source (kept-typography guard), a synthesizer orders them into a kit-vs-app-vs-server build plan',
4
+ whenToUse: 'Run after the completion sweep (8th run) has landed. Distinct from all five prior workflows: gui-audit hunts JANK, gui-overhaul DESIGNS surfaces, gui-predictability-polish polishes primitives, gui-cohesion hunts one-product feel, gui-completion hunts scoped-out coverage. This one audits OPERATING LOGIC - whether each control behaves the way a user would predict (full lifecycle states, race/double-fire safety), whether the same fact reads the same on every surface, whether things live where a user would look, whether realtime counters agree across tabs, whether input ergonomics match a desktop-class chat agent, and whether the UI survives scale (huge transcripts, 1000-entry dirs, dozens of live sessions). Reference bars: claude.ai/code, cowork, Claude Desktop, fsbrowse. All visual/component work lands in c:\\dev\\anentrypoint-design; the app keeps wiring; server changes must be confineToRoots-confined.',
5
+ phases: [
6
+ { title: 'Hunt', detail: 'one agent per logic/predictability lens audits the shipped source against the reference bar' },
7
+ { title: 'Verify', detail: 'adversarially confirm each finding is real and soundly fixable (kept-typography guard)' },
8
+ { title: 'Plan', detail: 'synthesize confirmed findings into a dependency-ordered kit-vs-app-vs-server build plan' },
9
+ ],
10
+ };
11
+
12
+ // Shared grounding. Eight sweeps have shipped; this one audits whether what shipped OPERATES logically and predictably.
13
+ const GROUND =
14
+ ' GROUND IN REAL SOURCE (read, do not guess - eight sweeps HAVE shipped: jank audit, redesign, polish, cohesion, completion; the Files manager has full CRUD, hash routing carries tab/sid/dir/file/q/project/section, conversation has edit/retry/export/followups, resilience has ws-grace/health-reprobe/install-hints): agentgui front-end c:\\dev\\agentgui\\site\\app\\js\\app.js + backend.js + index.html; kit c:\\dev\\anentrypoint-design\\src\\components\\{shell.js,sessions.js,agent-chat.js,chat.js,files.js,files-modals.js,context-pane.js,content.js,forms.js} + {app-shell.css,chat.css}; server c:\\dev\\agentgui\\lib\\http-handler.js + lib\\ws-handlers-util.js + server.js. PUNCHLIST-COMPLETION.md + PUNCHLIST-COHESION.md + AGENTS.md record what already landed - do NOT re-report it; hunt what still operates illogically or unpredictably.' +
15
+ ' POLICY: fully-destructive run - reshape anything; ALL visual/component work lands in the KIT as defaults/props; app keeps state+callback wiring; NEVER new index.html !important overrides; kit tokens not hex; NO decorative glyphs (ASCII words + CSS .status-dot-disc) but KEEP middot/ellipsis/em-en-dash; any server mutation stays confineToRoots realpath-confined; every change needs a11y (roles/aria/focus/44x44/keyboard), responsive (420px), explicit empty/loading/error states, plain-language copy.';
16
+
17
+ const LENSES = [
18
+ { key: 'interaction-lifecycle', prompt: 'LOGIC LENS - INTERACTION STATE MACHINES. For EVERY actionable control in the GUI (send, stop, retry, edit-resend, followup chips, file rename/delete/mkdir/upload, download, stop-all/stop-selected, clear-data, export, copy buttons, theme toggle, drawer toggles, load-older), audit its FULL lifecycle: idle -> hover/focus -> pressed -> in-flight (busy/disabled? spinner? label change?) -> success feedback -> error recovery -> re-enabled. Hunt: double-click/double-submit races (can send fire twice? can delete fire while a delete is in flight? does retry during streaming corrupt state?), controls that stay enabled during an operation they invalidate, missing in-flight indication, success with no feedback, operations with no way to cancel, confirm steps that auto-reset at the wrong time, focus lost after an action completes (where does focus land after a dialog closes, a row deletes, a message sends?). Name every control whose lifecycle is incomplete or racy, with the concrete kit-vs-app fix.' + GROUND },
19
+ { key: 'cross-surface-consistency', prompt: 'PREDICTABILITY LENS - CROSS-SURFACE CONSISTENCY. The same fact must read the same everywhere. Audit: session identity (does the same session show the same title/label in chat rail, history rail, live dashboard, running panel?), timestamps (relative vs absolute, same format across chat/history/live/files?), cost/token figures (composer context line vs ContextPane vs history - same units, same rounding?), status vocabulary (connected/connecting/offline vs running/idle/stale vs healthy - one vocabulary per concept?), agent naming (id vs display name), cwd/project rendering (full path vs slug - consistent?), selection semantics (does clicking a session row do the same thing on chat tab vs history tab - and is that predictable?), icon/action placement (is copy always in the same corner? is destructive always rightmost?), empty-state copy tone, capitalization (sentence-case everywhere?). Name every divergence with which surface is canonical and the concrete fix.' + GROUND },
20
+ { key: 'information-architecture', prompt: 'LOGIC LENS - INFORMATION ARCHITECTURE + DISCOVERABILITY. Is everything where a user would look first? Audit: rail order (chat/history/files/live/settings - logical?), whether live-session management is discoverable from chat (a running chat is on the live tab - does chat say so?), whether settings panels are grouped logically (connection vs agents vs data vs keyboard vs server), whether the ?-overlay is discoverable without knowing ?, whether file actions are discoverable (hover-revealed actions on touch devices?), whether followup chips read as suggestions vs buttons, whether the composer context line communicates what will HAPPEN on send (which agent, which model, which cwd, resume vs fresh - is resume-vs-fresh visible ANYWHERE before sending?), whether history search scope is communicated (titles? bodies? all sessions?), whether export options are findable, whether the crumb communicates location. Hunt hidden functionality, mislabeled groups, and anything requiring tribal knowledge. Name every misplacement with the logical home and concrete fix.' + GROUND },
21
+ { key: 'realtime-truth', prompt: 'PREDICTABILITY LENS - REALTIME TRUTH + STATE SYNC. Counters and statuses must agree with reality and each other. Audit: the live dashboard tally vs history event counts vs chat turn count (can they disagree? when?), staleness derivation (45s idle -> stale: does it flap? does a slow tool wrongly read stale?), what happens when the SAME session is open on chat tab while events stream on live tab (do both update?), multi-browser-tab behavior (two GUI tabs open: do they fight over localStorage drafts/resumeSid? does one tab\'s stop kill the other\'s view?), ws reconnect vs SSE reconnect divergence (one recovers, one does not?), the 3s chat.active poll vs SSE push skew (running panel shows a session the dashboard does not?), cost accumulation across resume (does cumulative cost survive reload? double-count on retry?), event dedup on reconnect replay, clock skew in relative timestamps, and whether ANY surface can show stale data with no indication it is stale. Name every truth divergence with the concrete fix.' + GROUND },
22
+ { key: 'input-ergonomics', prompt: 'LOGIC LENS - INPUT ERGONOMICS + COMPOSER DEPTH. Benchmark the claude.ai/code / Claude Desktop composer. Audit: multiline behavior (Enter vs Shift+Enter - communicated?), composer autosize (grows with content? max height? scroll?), paste behavior (pasting a large block? pasting an image - handled or silently dropped?), drag-drop onto the composer (file path insertion? or lost?), IME composition safety (Enter during CJK composition must not send), undo history survival across draft restore, keyboard shortcut completeness (is there a shortcut to stop generation? to focus composer from anywhere? are they in the ? overlay?), Escape semantics (consistent close/cancel everywhere: dialogs, drawers, edit-mode, confirm-states?), Tab order across the shell (rail -> sessions -> main -> pane logical?), text selection inside streaming messages (does a render wipe selection?), form validation timing (cwd validation on blur vs save?), and search input ergonomics (clear button? Esc clears? result count announced?). Name every ergonomic gap with the concrete kit-vs-app fix.' + GROUND },
23
+ { key: 'scale-robustness', prompt: 'PREDICTABILITY LENS - SCALE + DEGENERATE STATES. The UI must stay logical at the extremes. Audit with the REAL rendering paths: a 500-message transcript (does the chat virtualize or render all? does jump-to-latest survive? does per-block code-copy injection rescan everything per token?), a 1000-entry directory (FILE_GRID_CAP=200 show-more: does sort/filter apply before or after the cap - is that predictable?), 20 simultaneous live sessions (dashboard sort stability while cards re-sort under the cursor mid-click?), a 100k-character single message (markdown render time? copy button on a giant block?), zero-state every tab (fresh install: chat/history/files/live/settings all have designed empty states - and do they explain the NEXT action?), an enormous event list in history (300-limit + load-older: predictable?), localStorage full/corrupt (restore path throws -> blank app or graceful?), offline boot (server up, network down for jsdelivr markdown stack - does chat degrade gracefully?), and extremely long session titles/cwd paths/agent names (truncation with title= everywhere?). Name every scale failure with the concrete fix.' + GROUND },
24
+ ];
25
+
26
+ const GAP_SCHEMA = {
27
+ type: 'object',
28
+ required: ['lens', 'gaps'],
29
+ properties: {
30
+ lens: { type: 'string' },
31
+ gaps: {
32
+ type: 'array',
33
+ items: {
34
+ type: 'object',
35
+ required: ['title', 'where', 'fixLocation', 'fix', 'severity'],
36
+ properties: {
37
+ title: { type: 'string', description: 'the illogical/unpredictable behavior' },
38
+ where: { type: 'string', description: 'file:line or component (or "absent")' },
39
+ fixLocation: { type: 'string', enum: ['kit', 'app', 'server', 'kit+app', 'app+server', 'kit+app+server'], description: 'where the fix lands' },
40
+ fix: { type: 'string', description: 'the concrete change: component/prop/css/wiring/endpoint' },
41
+ benchmark: { type: 'string', description: 'which reference product sets the bar' },
42
+ severity: { type: 'string', enum: ['high', 'medium', 'low'] },
43
+ keptTypography: { type: 'boolean', description: 'true if this touches the middot/ellipsis/dash set - which must NOT be flagged as a glyph violation' },
44
+ },
45
+ },
46
+ },
47
+ },
48
+ };
49
+
50
+ const VERDICT_SCHEMA = {
51
+ type: 'object',
52
+ required: ['title', 'real', 'reason'],
53
+ properties: {
54
+ title: { type: 'string' },
55
+ real: { type: 'boolean', description: 'true if the behavior is genuinely illogical/unpredictable in the shipped source and the fix is sound' },
56
+ reason: { type: 'string', description: 'why - cite the source you read' },
57
+ },
58
+ };
59
+
60
+ phase('Hunt');
61
+ const verified = await pipeline(
62
+ LENSES,
63
+ (l) => agent(l.prompt, { label: 'hunt:' + l.key, phase: 'Hunt', schema: GAP_SCHEMA }),
64
+ (report, l) => parallel((report?.gaps || []).map((g) => () =>
65
+ agent(
66
+ 'Adversarially verify this GUI logic/predictability finding against the REAL source (read the cited files - do not trust the claim). '
67
+ + 'KEPT-TYPOGRAPHY GUARD: middot, ellipsis, em/en-dash are intentional product typography - flagging one of those as a decorative glyph is NOT a real finding (real=false). '
68
+ + 'A finding is real only if the behavior genuinely exists in the shipped source AND was not already fixed by a prior sweep (check PUNCHLIST-COMPLETION.md / PUNCHLIST-COHESION.md / AGENTS.md) AND the proposed fix is sound, lands in the right place (kit vs app vs server), and any server mutation stays confinement-safe. '
69
+ + 'Reject vague findings with no concrete source-grounded fix. '
70
+ + 'Finding: ' + JSON.stringify(g),
71
+ { label: 'verify:' + (g.title || '').slice(0, 32), phase: 'Verify', schema: VERDICT_SCHEMA }
72
+ ).then((v) => ({ ...g, lens: report.lens, verdict: v }))
73
+ ))
74
+ );
75
+
76
+ const confirmed = verified.flat().filter(Boolean).filter((g) => g.verdict && g.verdict.real);
77
+ log('confirmed ' + confirmed.length + ' real logic/predictability findings across ' + LENSES.length + ' lenses');
78
+
79
+ phase('Plan');
80
+ const plan = await agent(
81
+ 'Synthesize these adversarially-confirmed GUI logic/predictability findings into a dependency-ordered build plan for agentgui + the anentrypoint-design kit + the server. '
82
+ + 'Order: server changes first, then kit components (each edited ONCE with all changes batched), then app wiring, then the single build->vendor->witness step. '
83
+ + 'Call out which findings share a component (batch), which are independent (parallelizable), which conflict, and the highest-leverage few. '
84
+ + 'Confirmed findings: ' + JSON.stringify(confirmed),
85
+ { label: 'synthesize-plan', phase: 'Plan' }
86
+ );
87
+
88
+ return { confirmed, plan, lensCount: LENSES.length, confirmedCount: confirmed.length };
package/AGENTS.md CHANGED
@@ -1,22 +1,40 @@
1
1
  # AgentGUI — Agent Notes
2
2
 
3
- ## GUI completion sweep (2026-06-10) — eighth maximum-effort run
3
+ ## GUI Claude-Code-web parity sweep (2026-06-11) — tenth maximum-effort run
4
+
5
+ Hunts the VISUAL + LAYOUT + MOTION design-language parity gap vs claude.ai/code (the user verdict: too primitive, layout jank). New workflow `.claude/workflows/gui-claude-code-parity.js` (6 design-language lenses: visual-language, layout-composition, chat-thread-craft, file-browser-fidelity, live-session-command, motion-microinteraction; hunt -> adversarial verify (kept-typography guard) -> plan). 66 agents -> 37 confirmed gaps (`PUNCHLIST-PARITY.md`). Pushed: kit `anentrypoint-design` 28387c3, agentgui 0a93fc6.
6
+
7
+ **Chat reads like Claude Code, not a messenger.** AgentChat passes `flat:true` + `aicat:false` to `ChatMessage`; flat turns are FULL-WIDTH, avatar-less, capped at `--measure`, led by a `.chat-role` label (You / agent name), the assistant turn carrying a faint `color-mix(--fg 3%)` background (`.chat-msg-flat` in chat.css). The bubble/avatar layout is kept ONLY for the messenger demo. Composer is ONE bordered rounded-rect shell (`.chat-composer` border `var(--rule)` + `--r-2`, `:focus-within` ring) with a borderless textarea and an inline `--r-1` send (was a `--r-pill` stadium + 50% round button); `flex-wrap` + `.chat-composer-hint{order:5}` lay context/input/hint as rows. Tool calls render as a bordered status-toned card (`.chat-tool` de-frames the inherited `.chat-bubble`, head=icon·name·label·status-pill, running->accent / error->flame); the bundle shipped ZERO `.chat-tool` CSS before. `injectCodeCopy` reads the `<code>` `language-*` class -> a `.chat-code-lang` header tab on every rendered block. `::selection` is accent-tint, not mascot pink.
8
+
9
+ **Layout has a real content gutter.** Kit `WorkspaceShell` gains `mainFlush`; `.ws-main` now has `padding: var(--space-4) var(--space-5)` (files/live/history/settings) and the chat tab opts out via `.ws-main--flush` (app sets `mainFlush: state.tab==='chat'` since the thread self-gutters at `--measure`). `.ws-crumb` gets `min-height:48px` + a matching left gutter so the top edge aligns with the rail head.
10
+
11
+ **Live dashboard is a command center.** `SessionDashboard`: status-bucketed grid (Errored/Running/Idle/External `role=group` sections when `sort==='status'`, flat otherwise); header status breakdown `N running · M idle · K errors` (toned `.ds-dash-breakdown .seg.is-*`); a `.ds-dash-stream-disc` heartbeat (pulsing `status-dot-live` when connected); tri-state `role=checkbox` select-all + clear (`onSelectAll`/`onClearSelection`, app toggles `state.live.selected`); `is-armed` one-shot pulse on the armed stop button. `SessionCard`: cost/token stat (`session.cost`/`tokens`, app feeds the in-page chat's `totalCost` onto its own card), `is-new` arrival cue (`session.isNew`, app sets it for <3s-old sids), icon-led actions (open=primary), `is-stale` amber inset bar (was opacity .92). Files: `TYPE_ICON.dir='folder'` + new `file-image`/`link`/`folder-open` icons (shell.js); ConversationList loading skeleton rows. File preview: Prism highlight hook (`highlightAllUnder` ref) + `.ds-preview-gutter` line numbers + image fit/actual toggle + checkerboard.
12
+
13
+ **Motion (all `prefers-reduced-motion: no-preference` guarded).** `.ws-shell` eases `grid-template-columns` (rail/pane collapse no longer snaps; track count stays stable); `.agentchat-thread` `scroll-behavior:smooth`; `.ds-session-row` hover transition; `.ws-scrim` opacity fade (was display toggle); `.ds-alert` enter; copy->copied color flip; `.ds-dash-card.is-new` fade-in.
4
14
 
5
- Coverage run: hunts what the seven prior sweeps scoped out or never examined. New workflow `.claude/workflows/gui-completion.js` (6 coverage lenses: file-management-crud, routing-deeplinks, conversation-control, history-settings-depth, onboarding-recovery, crosscut-new-surface; hunt -> adversarial verify (kept-typography guard) -> plan). Ran 75 agents -> 46 confirmed gaps (`PUNCHLIST-COMPLETION.md`). ALL implemented.
15
+ **Load-bearing webjsx fix (caught by the live witness).** SessionCard passed raw `null`s positionally in its head/meta/actions/top-level children arrays; webjsx `applyDiff` crashes (`reading 'key'`) on ANY null among VElement siblings (not just keyed ones). This was a PRE-EXISTING latent bug (the unmodified kit crashed identically on this env's external sessions) that this env's data now triggered. Fix: `.filter(Boolean)` EVERY children array in SessionCard + SessionDashboard header/body, and `Btn` now spreads array `children`. The kit-wide rule: never pass a conditional `x ? h() : null` positionally — build the array and `.filter(Boolean)` it (the same pattern ConversationList already uses). Witness localhost:3009/gm/ (port 3000 was owned by another app): 0 console/page errors across chat/files/live; composer 14px radius; ws-main flush=0 on chat, 32px on files; folder icon distinct; no h-scroll. First `/gm/` request triggers the 30-90s ccsniff walk -> poll until 200 before witnessing.
6
16
 
7
- **Files is a full manager now (the read-only scope cut is REVERSED).** Server `lib/http-handler.js`: shared `fsAllowRoots()` (one allowlist construction for list/file/download/mutations), `sanitizeEntryName()` (single path component; rejects separators, traversal, ADS colon, reserved Windows device names, trailing dot/space), `readBody()` (hard cap, 413), `isAllowRoot()` (roots are never mutation targets). New confined routes: `POST /api/rename` `{path,newName}`, `POST /api/delete` `{path,recursive}` (non-empty dir without recursive -> 409), `POST /api/mkdir` `{dir,name}`, `PUT /api/upload-file?dir&name[&overwrite=1]` (raw bytes, 50MB, no multipart dep), `GET /api/stat/<path>` (confined cwd validation). **CSRF guard on every POST/PUT/DELETE**: reject when Sec-Fetch-Site is cross-site AND body is a simple-form content type AND no Authorization header. `/health` gains `projectsDir` + `allowRoots`. All validated live by `scripts/validate-mutations.mjs` (17 checks: traversal/out-of-roots/root-refusal/reserved-names/ADS/CSRF/409 conflicts/round-trip) — run it after touching the mutation surface. App `filesMain`: rename/delete row actions -> kit `PromptDialog`/`ConfirmDialog` (destructive copy states recursion), `new folder` + `upload` toolbar buttons, `DropZone` wraps the grid (keyboard path = the upload button), `UploadProgress` per-file rows, one `loadDir` refresh per mutation, status->plain-copy map (403/404/409/413).
17
+ **Deferred (documented in `PUNCHLIST-PARITY.md`, rows pending):** Files multi-select + BulkBar + density-thumbnail grid (kit props + heavy app/server wiring), the `/api/move-confined` drag-to-move endpoint, a toolbar up-button + file-grid keys in the SHORTCUTS array, and F3 panel/card elevation unification. These are lower-leverage than the shipped visual/layout/motion/command-center batch.
8
18
 
9
- **Full hash routing (`HASH_KEYS = tab,sid,dir,file,q,project,section`).** `buildHash` reads all view state; `writeHash({push})`; user nav pushes, passive sync replaces; popstate diffs the full set (no more navTo side-effect clobber - `navTo(tab,{writeHash:false})` from popstate); chat+sid deep-links name `tab=chat` explicitly (bare sid historically meant history); Files dir/file round-trip (reload restores the dir + open preview, Back walks the tree - witnessed live); history q/project restore + re-search; settings `section=` scroll+focus.
19
+ ## GUI logic+predictability sweep (2026-06-10) ninth maximum-effort run
10
20
 
11
- **Conversation control.** `editAndResend` is two-step (`state.chat.confirmingEdit` banner) and **clears `resumeSid`** on truncation - never `--resume` a session whose tail diverged (retry of the last turn keeps it). Draft persists. Followups derive from the settled turn (tool error -> fix, code fence -> explain, file path -> open). `exportActions` (copy all / export md / export json) when messages exist; `transcriptToMarkdown`. Composer context appends `N turns`; cumulative cost feeds `ContextPane session:{turns,cost}`.
21
+ Audits whether everything OPERATES logically and predictably (not coverage, not cohesion). New workflow `.claude/workflows/gui-logic-predictability.js` (6 lenses: interaction-lifecycle, cross-surface-consistency, information-architecture, realtime-truth, input-ergonomics, scale-robustness; hunt -> adversarial verify (kept-typography guard) -> plan). 78 agents -> 67 confirmed findings (`PUNCHLIST-LOGIC.md`). ALL implemented across kit/app/server.
12
22
 
13
- **Resilience.** `backend.js streamChat` holds a 12s grace timer on ws closed (reconnect re-subscribes and the turn continues); stream-error banner gains `retry`; `/health` re-probe on ws drop + 10s poll while not-ok + `reconnected` announce + agents refetch; `loadAgents()` with boot backoff + error banner; `errText` plain-language map (raw kept in title); cwd validated via `/api/stat` before save; ccsniff warmup copy escalates after 5s (`loadingText`); `installHint` (npx commands + recheck) when zero agents are available.
23
+ **Interaction lifecycles.** Kit `ConfirmDialog`/`PromptDialog` gain `error` (inside `.ds-modal-body`, role=alert) + `busy`/`busyLabel` (disables actions AND Escape/backdrop close via `data-busy`); Backdrop's Escape listener is **document-level** (focus can sit outside the dialog) and focus-restore fires only on genuine close (queueMicrotask remount guard) - the app's global Escape ladder ALSO closes `state.files.dialog` as belt-and-braces (a witness caught Escape dead with focus on H1). Per-session stop: `state.live.stopping` Set + kit `session.stopping` ('stopping...', disabled); bulk stops await `Promise.allSettled`, announce 'stopped N of M', partial failures keep their selection. Upload: one drain loop, concurrent drops append, 409 rows get `replace` (overwrite=1) + dismiss (kit `UploadProgress {actions,onDismiss}`). new-chat/backend-change/stop confirms are arm-only with bound values + 4s reset; chips never clobber a typed draft.
14
24
 
15
- **History/settings depth.** Event rail finally honors tool_use=purple; `FilterPills` event-type filter (filtered BEFORE the eventsLimit slice); jump-to-first-error; copy-event-payload on expanded rows (kit `Row actions` slot, stopPropagation); per-session JSON export; `SessionMeta` header (cwd/duration/sid/events); search-hit `highlight` mark + title windowed around the first match + relative timestamps. Settings: `server` panel (version/uptime/ws/roots+copy/projectsDir), `keyboard` panel + ?-overlay fed by ONE `SHORTCUTS` array, export-chat + local-data size line; live sort/errorsOnly + files sort persist to localStorage (live selection Set deliberately NOT persisted - stale sids would arm stop-selected wrongly); two-step stop-all/stop-selected (`confirmingStop*` + 4s auto-reset).
25
+ **Realtime truth.** Dashboard joins on `realSid = claudeSessionId || sessionId` - server `chat.active` rows now carry `claudeSessionId`; `streaming_cancelled` is broadcast (an aborted turn never also completes; backend maps it to `{type:'cancelled'}`, app marks the turn 'stopped'); a 60s per-session terminal-frame buffer replays on re-subscribe (`replayedTerminal`) so a turn finishing during a ws drop cannot hang busy; `chat_active_changed` hints (started/ended/cancelled) trigger immediate refreshActive. Error status derives from recency (not cumulative count - a session is not 'error' forever); stale derivation honors any session's running tool (per-sid `toolRunning` off SSE); SSE counter increments dedup by `ev.i` maxI; counters take max(index,tally) and never move backwards; clock-skew clamps to 'just now'; external (non-owned) sessions render as read-only dashboard cards; sorts compare real timestamps with sid tiebreaker; tally pruned 24h/200-LRU. persistChat: 500ms debounce, 100-msg cap, >4KB tool payloads trimmed (`truncatedForStorage`), quota failure banners once, cross-tab `storage` listener with ts guard ('updated in another tab' banner instead of clobber).
16
26
 
17
- **Kit additions** (`anentrypoint-design`): files.js `FileRow {actions,busy}` + permission-disabled rename/delete + no download on dirs; content.js `Row {highlight,actions}` + `Panel/PageHeader {id}` + `FilterPills`; sessions.js `SessionMeta` + dashboard `confirmingStopAll/Selected + onArmStop*` + `ConversationList {loadingText}`; agent-chat.js `installHint/exportActions/confirmEdit+onArmEdit`; context-pane.js `session {turns,cost}`. NOTE: `.ds-session-meta` was already taken (ConversationList row meta) - the strip is `.ds-session-meta-strip`.
27
+ **Input ergonomics.** IME guards (composer, PromptDialog, SearchInput - `isComposing || keyCode===229` never sends). Escape ladder: shortcuts overlay > file dialog > confirmingEdit > new-chat arm > stop-arms > stop generation (and Esc in composer cancels while busy). Window-level dragover/drop preventDefault outside `.ds-dropzone` (a dropped file never navigates the page). Composer: `onPasteFiles`/`onDropFiles` kit props (image paste with no handler -> polite transient note), `.chat-composer-hint` 'Enter to send · Shift+Enter for a new line', context `bits` may carry per-bit `onClick` (cwd is its own target; agent/model inert). `Mod+Shift+L` focuses composer from anywhere (the one chord BEFORE the modifier early-return). cwd validates on blur (debounced `/api/stat` -> kit `cwdError`/`cwdChecking`). Streaming re-render pauses while a selection is held inside the thread (kit `hasSelectionInside` + autoscroll pause).
28
+
29
+ **Scale.** `AgentChat {shownMessages,onShowEarlier}` windowed thread (`MESSAGE_CAP=100`, keyed 'show N earlier turns' row); >20k streaming part renders a 4k tail window ('streaming · N KB so far'); history events sliced to last 5000 in-app (server adds a `?limit=N[&before=]` slicing shim in server.js - ccsniff itself has no limit support, do NOT edit node_modules); markdown loader failure no longer latches degraded (30s retry, cache never stores escaped fallback).
30
+
31
+ **Consistency/IA.** ONE `fmtDuration` (kit sessions.js) + ONE `fmtBytes` (= fmtFileSize, `0 B` not em-dash) kit-wide with app fallbacks; SessionCard `title` shares the rails' title expression; `session.external` + `session.elapsedMs`; STREAM_WORD `offline`; coarse-pointer always-visible file row actions; idle status never reads 'resuming...' (plain 'continues session <sid8>' in composer context); `/` focuses the files/live filter; running panel links 'open in live'; settings reordered backend -> server -> agents -> appearance -> keyboard -> data; crumb says 'settings' and Files crumb carries the parent trail.
32
+
33
+ **Witness.** localhost:3000/gm/ 0 console/page errors across chat/files/live/history/settings; composer hint renders; rename dialog opens + Escape closes + focus restores; 64-row files grid + crumb trail; 420px chat+live no h-scroll; decorative-glyph count 0 (kept middot/ellipsis/dash). Joint risk to re-check after parallel agent runs: prop-name contracts (this run caught app `onPasteImage` vs kit `onPasteFiles`, and backend missing the new `streaming_cancelled` type).
34
+
35
+ ## GUI completion sweep (2026-06-10) — eighth maximum-effort run
18
36
 
19
- **Witness.** localhost:3000/gm/ 0 console/page errors on chat/files/history/settings/live; files deep-link in+out+Back witnessed; FilterPills/SessionMeta/export/purple-rails(45) live; server+keyboard panels render; 420px live tab no h-scroll; decorative-glyph count 0. The stale scope-cut lines from the 7th run (read-only browser / upload not reusable / retry last-turn-only) are superseded by this section.
37
+ Coverage run reversing the prior scope cuts. Workflow `.claude/workflows/gui-completion.js` (6 lenses) -> 46 gaps (`PUNCHLIST-COMPLETION.md`), ALL implemented. Load-bearing remnants: Files is a FULL manager (confined `POST /api/rename,/api/delete,/api/mkdir`, `PUT /api/upload-file`, `GET /api/stat` via `fsAllowRoots()`/`sanitizeEntryName()`; CSRF guard on POST/PUT/DELETE; **run `scripts/validate-mutations.mjs` (17 checks) after touching the mutation surface**). Full hash routing `HASH_KEYS=[tab,sid,dir,file,q,project,section]` (popstate diffs the full set; `navTo(tab,{writeHash:false})`). `editAndResend` clears `resumeSid` on truncation (never --resume a diverged tail). `.ds-session-meta` was taken - the strip is `.ds-session-meta-strip`. One `SHORTCUTS` array feeds the ?-overlay + settings. Live selection Set deliberately NOT persisted (stale sids would arm stop-selected wrongly). Full detail in rs-learn (recall "agentgui GUI completion sweep").
20
38
 
21
39
  ## GUI cohesion sweep (2026-06-10) — seventh maximum-effort run
22
40