agentgui 1.0.953 → 1.0.955
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.
- package/.claude/workflows/gui-overhaul.js +114 -0
- package/.claude/workflows/gui-predictability-polish.js +90 -0
- package/AGENTS.md +34 -2
- package/PUNCHLIST-POLISH.md +329 -0
- package/lib/http-handler.js +147 -11
- package/package.json +1 -1
- package/site/app/js/app.js +527 -37
- package/site/app/js/backend.js +33 -0
- package/site/app/vendor/anentrypoint-design/247420.css +319 -0
- package/site/app/vendor/anentrypoint-design/247420.js +15 -15
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'gui-overhaul',
|
|
3
|
+
description: 'Drive the Claude-Desktop-style redesign of agentgui: per-surface designers produce concrete kit-vs-app build specs, verify feasibility, synthesize an ordered build plan',
|
|
4
|
+
whenToUse: 'Run a maximum-effort GUI REDESIGN of agentgui toward a claude.ai/code / Claude Desktop / cowork feel: a persistent left conversation/session rail, a polished chat thread, a Files/folder-browser view, and a multi-session live dashboard. Distinct from gui-audit (which hunts jank in the existing UI) - this one designs the NEW surfaces. Fans out one designer per surface, each emitting a concrete implementation spec (new kit components, props, CSS, app wiring, server endpoints) with the kit-vs-app split; an independent reviewer checks each spec against the real kit + app source for feasibility and override-elimination; a synthesizer orders them into a dependency-aware build plan. All GUI/component work lands in the c:\\dev\\anentrypoint-design kit; the app keeps only wiring; index.html gains no new !important overrides.',
|
|
5
|
+
phases: [
|
|
6
|
+
{ title: 'Design', detail: 'one designer agent per redesign surface emits a build spec' },
|
|
7
|
+
{ title: 'Review', detail: 'independent reviewer checks each spec for feasibility + override-elimination + glyph/a11y policy' },
|
|
8
|
+
{ title: 'Plan', detail: 'synthesize specs into a dependency-ordered, kit-vs-app build plan' },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Each redesign surface becomes one designer agent. The designer reads the real
|
|
13
|
+
// source (app.js, backend.js, the kit components + css, the server handler) and
|
|
14
|
+
// returns a concrete spec: what new kit component(s)/props/css to add, what app
|
|
15
|
+
// wiring changes, what server endpoints, and the kit-vs-app split. Add a row to
|
|
16
|
+
// widen coverage; the fan-out scales with it.
|
|
17
|
+
const GROUND =
|
|
18
|
+
' GROUND IN REAL SOURCE (read, do not guess): agentgui front-end c:\\dev\\agentgui\\site\\app\\js\\app.js (view/mainContent/navTo/state) + backend.js (WS/HTTP client) + index.html (shell/css). The design kit c:\\dev\\anentrypoint-design\\src\\components\\{shell.js,content.js,chat.js,agent-chat.js,files.js,files-modals.js} + its css (app-shell.css,chat.css,colors_and_type.css). Server c:\\dev\\agentgui\\lib\\http-handler.js. POLICY: ALL visual/component work lands in the KIT, the app keeps only state + callback wiring; ship correct KIT defaults, NEVER new index.html !important overrides; use kit color/type tokens not hardcoded hex; NO decorative glyphs (arrows/box-drawing/bullets/checks/status-dot chars/emoji) - use ASCII words + the CSS .status-dot-disc, but KEEP the typographic product set (middot, ellipsis, em/en-dash); every surface needs a11y (roles, aria, focus, 44x44 targets, keyboard), responsive (<640 collapse), and explicit empty/loading/error states.';
|
|
19
|
+
|
|
20
|
+
const SURFACES = [
|
|
21
|
+
{ key: 'shell-layout', prompt: 'Design the Claude-Desktop / cowork three-column APP SHELL for agentgui: a persistent collapsible LEFT RAIL (workspace nav: New chat, Chats/sessions, Files, Live, Settings), a primary CONTENT column, and an optional collapsible RIGHT CONTEXT pane. The current kit AppShell (shell.js) only has topbar/crumb/side/main/status with a single mobile drawer. Specify the kit change: either a new AppShell variant or new leftRail + rightPane slots, with collapse state, persistence, mobile behavior, and the app-shell.css needed. Specify the app.js view() rewrite to compose it and how navTo/readHash/buildHash/keyboard-shortcuts move from Topbar tabs to the rail.' + GROUND },
|
|
22
|
+
{ key: 'sessions-rail', prompt: 'Design the persistent CONVERSATION/SESSION list that lives in the left rail (Claude-Desktop "Chats"): per-row title/project + relative last-active + agent badge + running indicator + new-event dot; grouped (today/week/older or by project); inline search/filter + project pills; a prominent New chat button; click switches the active conversation (load its transcript + resumeSid + restoredAgent/model). Specify a new kit SessionList/ConversationList component (props, rail tones green/purple/flame, stable keys) + css, and the app wiring over ccsniff sessions (B.listSessions) + live chats (B.listActiveChats). Distinct from the History events view.' + GROUND },
|
|
23
|
+
{ key: 'chat-thread', prompt: 'Design the polished CHAT THREAD + composer to read like Claude Desktop: clear user-vs-assistant alignment, name/avatar row, per-message copy + per-code-block copy, comfortable centered reading column, timestamp/meta, structured collapsible tool cards (kind:tool ToolCallNode), interleaved md/text/tool parts in arrival order, streaming working-indicator, settled-markdown without reflow flash. Composer: auto-grow textarea, Enter-send / Shift+Enter newline, inline stop while streaming, caret-stable. Specify the kit changes in chat.js/agent-chat.js + chat.css and any app wiring.' + GROUND },
|
|
24
|
+
{ key: 'files-browser', prompt: 'Design the FILES / folder-browser view (mirroring c:\\dev\\fsbrowse which uses the SAME kit): a server filesystem-listing endpoint /api/list returning {path,segments,entries:[{name,type,size,modified}]} confined to an allowlist root (path.normalize + resolved-prefix check, mirroring the /api/image pattern in http-handler.js; gated by PASSWORD; no symlink/.. escape), and the view rendered with existing kit file components (BreadcrumbPath, FileGrid/FileRow, FileToolbar, EmptyState, FileViewer for preview). Click a dir to descend, a file to preview. ALSO a folder-picker mode usable from the chat CwdBar Browse affordance to set the agent cwd by browsing. Specify the server endpoint (lib/routes-fs.js), backend.js listDir(path), the app view, and any kit modal (files-modals.js FolderPicker).' + GROUND },
|
|
25
|
+
{ key: 'live-dashboard', prompt: 'Design the LIVE SESSION DASHBOARD to view ALL in-flight sessions and manage them simultaneously (claude.ai/code parallel-session feel): a cards grid, one card per running session (agent/model/cwd, elapsed, last activity, status dot, live token/event counter), with per-card controls that act on that sessionId independently - Stop (chat.cancel), Open/Switch (focus that conversation), Resume (claude-code --resume), View events (jump to history sid). Real-time via the existing startActivePolling (chat.active, ~3s) + the live stream; rAF-coalesced renders; stable per-session keys (no duplicate key:rd bug); empty + offline states. Specify a new kit SessionDashboard/SessionCard component + css and the app wiring.' + GROUND },
|
|
26
|
+
{ key: 'settings-context', prompt: 'Design the SETTINGS view + the optional RIGHT CONTEXT pane inside the new shell. Settings: agents/health status, backend/cwd config, clear-data, keyboard-shortcuts reference, theme toggle (kit theme-toggle.js). Context pane: per active conversation show cwd + a quick file browser, agent/model, running tool calls, session metadata; collapsible + responsive. Fix the prior dup key:bst on the 3 backend-status <p>. Specify kit components/props + css and app wiring.' + GROUND },
|
|
27
|
+
{ key: 'crosscut-a11y-responsive', prompt: 'Design the CROSS-CUTTING a11y + responsive + states layer for ALL new surfaces (rail, session list, chat, files, live dashboard, context pane, settings): role/aria-current nav, list semantics + focusable rows, modal focus-trap/Esc/aria-modal for the folder picker, skip-link still works, aria-live view-change announcements, visible focus rings, 44x44 targets; three-column shell collapse <640 (rail behind hamburger, right pane stacks/hides, files 1-col, dashboard cards stack, composer/breadcrumb usable); explicit empty/loading/error for every surface (distinguish loading from genuinely-empty). Specify the kit @media + a11y attributes per component.' + GROUND },
|
|
28
|
+
{ key: 'crosscut-perf-glyph-override', prompt: 'Design the CROSS-CUTTING performance + glyph-hygiene + override-elimination + token-consistency layer. Perf: rAF-coalesce all renders, stable keys, cap+page or virtualize long session/event lists, no per-token full re-layout, streaming md settles off-stream. Glyph: confirm NO decorative tells in the new surfaces (use ASCII words + .status-dot-disc), KEEP middot/ellipsis/dash; if c:\\dev\\fsbrowse README/public are touched, convert their emoji. Override-elimination: enumerate every place the redesign might tempt an index.html !important override and specify the KIT default/prop that avoids it. Tokens: all new css uses kit color/type tokens (lint-tokens), not hardcoded hex.' + GROUND },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const SPEC_SCHEMA = {
|
|
32
|
+
type: 'object',
|
|
33
|
+
required: ['surface', 'kitChanges', 'appChanges', 'serverChanges', 'risks'],
|
|
34
|
+
properties: {
|
|
35
|
+
surface: { type: 'string' },
|
|
36
|
+
kitChanges: {
|
|
37
|
+
type: 'array',
|
|
38
|
+
description: 'concrete kit (anentrypoint-design) edits: new/changed component, props, css',
|
|
39
|
+
items: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
required: ['file', 'change'],
|
|
42
|
+
properties: {
|
|
43
|
+
file: { type: 'string', description: 'kit file path' },
|
|
44
|
+
change: { type: 'string', description: 'component/prop/css to add or change' },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
appChanges: {
|
|
49
|
+
type: 'array',
|
|
50
|
+
description: 'agentgui app.js/backend.js wiring edits (state + callbacks only, no visual logic)',
|
|
51
|
+
items: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
required: ['file', 'change'],
|
|
54
|
+
properties: { file: { type: 'string' }, change: { type: 'string' } },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
serverChanges: {
|
|
58
|
+
type: 'array',
|
|
59
|
+
description: 'agentgui server/lib edits (endpoints, security)',
|
|
60
|
+
items: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
required: ['file', 'change'],
|
|
63
|
+
properties: { file: { type: 'string' }, change: { type: 'string' } },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
dependsOn: { type: 'array', items: { type: 'string' }, description: 'other surface keys this depends on' },
|
|
67
|
+
risks: { type: 'array', items: { type: 'string' } },
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const REVIEW_SCHEMA = {
|
|
72
|
+
type: 'object',
|
|
73
|
+
required: ['feasible', 'reason'],
|
|
74
|
+
properties: {
|
|
75
|
+
feasible: { type: 'boolean' },
|
|
76
|
+
reason: { type: 'string' },
|
|
77
|
+
// Set true if the spec proposes any new index.html !important override, any
|
|
78
|
+
// hardcoded hex instead of a token, any decorative glyph, or wrongly converts
|
|
79
|
+
// the kept typographic set (middot/ellipsis/dash). Each is a policy violation.
|
|
80
|
+
policyViolation: { type: 'boolean' },
|
|
81
|
+
corrections: { type: 'array', items: { type: 'string' } },
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
phase('Design');
|
|
86
|
+
|
|
87
|
+
// Pipeline: each surface is designed, then its spec is independently reviewed for
|
|
88
|
+
// feasibility + policy the moment that design returns - faster surfaces do not
|
|
89
|
+
// wait on slower ones.
|
|
90
|
+
const designed = await pipeline(
|
|
91
|
+
SURFACES,
|
|
92
|
+
(s) => agent(s.prompt, { label: 'design:' + s.key, phase: 'Design', schema: SPEC_SCHEMA }),
|
|
93
|
+
(spec, surface) =>
|
|
94
|
+
agent(
|
|
95
|
+
'Review this agentgui redesign build-spec for surface "' + surface.key + '" against the REAL kit + app + server source. Confirm every kitChange/appChange/serverChange actually fits the existing components and APIs (read them). POLICY CHECK (set policyViolation=true if any holds): proposes a new index.html !important override instead of a kit default/prop; uses hardcoded hex instead of a kit color/type token; introduces a decorative glyph (arrow/box-drawing/bullet/check/status-dot char/emoji); or wrongly converts the KEPT typographic set (middot/ellipsis/em-or-en-dash). Default feasible=false if you cannot confirm from source. Spec JSON:\n' +
|
|
96
|
+
JSON.stringify(spec, null, 2),
|
|
97
|
+
{ label: 'review:' + surface.key, phase: 'Review', schema: REVIEW_SCHEMA }
|
|
98
|
+
).then((r) => ({ ...spec, surface: surface.key, review: r }))
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const specs = designed.filter(Boolean);
|
|
102
|
+
const feasible = specs.filter((s) => s.review && s.review.feasible && !s.review.policyViolation);
|
|
103
|
+
const flagged = specs.filter((s) => !s.review || !s.review.feasible || s.review.policyViolation);
|
|
104
|
+
log(feasible.length + ' feasible specs, ' + flagged.length + ' flagged for correction across ' + SURFACES.length + ' surfaces');
|
|
105
|
+
|
|
106
|
+
phase('Plan');
|
|
107
|
+
|
|
108
|
+
const buildPlan = await agent(
|
|
109
|
+
'Synthesize these reviewed agentgui redesign specs into a single dependency-ordered BUILD PLAN. Order by the dependsOn DAG (shell-layout first, then rail/sessions, then content surfaces, then cross-cutting, then build+vendor+publish+browser-witness last). For each step give: the surface, the kit files to edit, the app/server files to edit, and a one-line acceptance check. Fold every flagged spec\'s corrections in. End with the build/vendor/publish closure (node scripts/build.mjs in c:\\dev\\anentrypoint-design, copy dist/247420.{js,css} into agentgui site/app/vendor/anentrypoint-design with git add -f, browser-witness http://localhost:3000/gm/, then commit+push the kit). Specs JSON:\n' +
|
|
110
|
+
JSON.stringify({ feasible, flagged }, null, 2),
|
|
111
|
+
{ label: 'synthesize', phase: 'Plan' }
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return { feasibleCount: feasible.length, flaggedCount: flagged.length, specs, buildPlan };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'gui-predictability-polish',
|
|
3
|
+
description: 'Polish the post-redesign agentgui GUI toward a Claude-Desktop/cowork feel: per-surface polish agents find the remaining primitive/rough/half-wired edges in the SHIPPED shell, adversarially verify, and emit a dependency-ordered kit-vs-app fix plan',
|
|
4
|
+
whenToUse: 'Run after the Claude-Desktop redesign has landed (WorkspaceShell + ConversationList + Files + Live dashboard + ContextPane exist). This sweep does not design NEW surfaces (gui-overhaul) nor hunt outright bugs (gui-audit) - it hunts the PRIMITIVE and the UNPOLISHED: missing affordances a real chat agent has (jump-to-latest, message actions, streaming caret, date grouping, roots picker, sort/filter, live per-session metrics, bulk session management), and the predictability gaps (inconsistent vocab/tone, dead grid columns, frozen counters). One polish agent per surface emits concrete kit-vs-app changes against the REAL post-redesign source; an adversarial verifier confirms each gap is real (with a kept-typography guard so middot/ellipsis/dash are never flagged); a synthesizer orders them. All visual/component work lands in c:\\dev\\anentrypoint-design; the app keeps wiring; no new index.html !important overrides.',
|
|
5
|
+
phases: [
|
|
6
|
+
{ title: 'Polish', detail: 'one agent per surface finds the remaining primitive/rough edges + a concrete fix' },
|
|
7
|
+
{ title: 'Verify', detail: 'adversarially confirm each gap is real against the live source (kept-typography guard)' },
|
|
8
|
+
{ title: 'Plan', detail: 'synthesize confirmed gaps into a dependency-ordered kit-vs-app fix plan' },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Each surface of the SHIPPED shell becomes one polish agent. It reads the real
|
|
13
|
+
// post-redesign source and returns the gaps between what exists and what a
|
|
14
|
+
// Claude-Desktop / cowork-class chat agent provides, each with a concrete fix.
|
|
15
|
+
const GROUND =
|
|
16
|
+
' GROUND IN REAL SOURCE (read, do not guess - the redesign HAS shipped): agentgui front-end c:\\dev\\agentgui\\site\\app\\js\\app.js (view/sessionsColumn/workspaceRail/filesMain/liveMain/chatMain/historyMain/settingsMain) + backend.js + index.html. The kit c:\\dev\\anentrypoint-design\\src\\components\\{shell.js (WorkspaceShell/WorkspaceRail),sessions.js (ConversationList/SessionDashboard/SessionCard),agent-chat.js,chat.js,files.js,context-pane.js,content.js} + root css {app-shell.css,chat.css,colors_and_type.css}. Server c:\\dev\\agentgui\\lib\\http-handler.js. POLICY: the components ALREADY EXIST - find the PRIMITIVE/ROUGH/HALF-WIRED edge and the missing affordance, not a from-scratch redesign. ALL visual/component work lands in the KIT as correct defaults/props; the app keeps state + callback wiring; NEVER new index.html !important overrides (convert any to a kit default); use kit color/type tokens not hardcoded hex; NO decorative glyphs (arrows/box-drawing/bullets/checks/status-dot chars/emoji) - ASCII words + the CSS .status-dot-disc, but KEEP the typographic product set (middot, ellipsis, em/en-dash); every surface needs a11y (roles/aria/focus/44x44/keyboard), responsive (<640 + 420px), and explicit empty/loading/error states.';
|
|
17
|
+
|
|
18
|
+
const SURFACES = [
|
|
19
|
+
{ key: 'files', prompt: 'POLISH the FILES view toward a real file manager / c:\\dev\\fsbrowse feel. Known-rough edges to confirm + fix: no roots-picker when multiple FS_ROOTS exist (only breadcrumb-walk down); bare Spinner loading (no skeleton); FileGrid in server order with no sort (name/size/modified) or in-dir filter; preview is a full MODAL not an inline side pane; toolbar (breadcrumb + use-as-chat-cwd) absent at the synthetic root; no keyboard nav (arrows/Enter/Backspace). Note the kit FileRow already supports onAction (download/rename/delete) the app does not wire - scope which are feasible against a read-only server. Specify kit changes (FileGrid sort/filter/skeleton/keyboard, split-pane preview) + app wiring + any server endpoint.' + GROUND },
|
|
20
|
+
{ key: 'live', prompt: 'POLISH the LIVE multi-session DASHBOARD toward managing many sessions simultaneously (claude.ai/code parallel feel). Known-rough edges: SessionCard counter is null - no live event/tool/error count per running session; elapsed is computed once per render (frozen between 3s polls); no stop-all / multi-select bulk controls; cards show start-elapsed but not last-activity / current-tool (stuck vs busy looks identical); verify empty vs offline states are visually distinct and the offline path actually triggers. Specify kit SessionDashboard/SessionCard changes (live metrics, last-activity, bulk header) + app wiring over the existing chat.active poll + live SSE.' + GROUND },
|
|
21
|
+
{ key: 'chat', prompt: 'POLISH the CHAT THREAD toward a Claude-Desktop chat agent. Known-rough edges: streaming shows a working tail but no inline typing CARET at the stream head; assistant messages have NO per-message actions (copy, retry, edit-and-resend); when scrolled up during a stream there is no jump-to-latest affordance and auto-scroll fights a reading user; the result usage event is DROPPED (no token/turn/cost surfaced); suggestion chips appear ONLY on an empty transcript (no contextual follow-ups). Specify kit AgentChat/ChatMessage/chat.css changes + app wiring.' + GROUND },
|
|
22
|
+
{ key: 'conversation-rail', prompt: 'POLISH the CONVERSATION/SESSION rail (ConversationList) toward a Claude-Desktop Chats sidebar. Known-rough edges: flat time-sorted list (no Today/Yesterday/This-week or project grouping - NOTE the kit ConversationList ALREADY accepts a `groups` prop the app does not pass); running sessions are not pinned/sectioned to the top; on the CHAT tab the inline search sets searchQ + runs the server search but the rail keeps showing time-sorted sessions, not the hits (chat-tab search never replaces the rail list - history side uses searchHits but the rail does not). Scope rename/delete/archive feasibility against read-only ccsniff. Specify kit + app wiring (mostly app: build groups[], wire chat-tab search hits into the rail).' + GROUND },
|
|
23
|
+
{ key: 'shell-contextpane', prompt: 'POLISH the WorkspaceShell + ContextPane. Known-rough edges: the right ContextPane renders only on the chat tab - verify the ws-shell grid reflows with NO dead column when pane is null across all tabs/breakpoints; the collapsed icon-only rail must keep accessible names + a keyboard-reachable, announced collapse toggle; the mobile (<900px) drawer needs working open/close + focus-trap + Esc-close + backdrop-dismiss; ContextPane is static (agent/model/cwd/toolCount) - evaluate enriching it (recent files, session metadata, token usage) within scope. Specify kit app-shell.css/shell.js/context-pane.js changes + app wiring.' + GROUND },
|
|
24
|
+
{ key: 'crosscut-glyph-override-consistency', prompt: 'CROSS-CUTTING: glyph hygiene + override-elimination + vocab/tone consistency across ALL surfaces incl the new ones. Glyph: scan app.js + kit src for ANY decorative tell (arrows/dots/checks/box-drawing/emoji); KEEP only middot/ellipsis/em-en-dash; one sighting -> codebase-wide fix list. Override: enumerate every index.html !important / local override of a kit rule and specify the KIT default that eliminates it. Consistency: status vocab (connected/connecting/offline), rail tone semantics (green=ok/selected, purple=subagent, flame=error), relative-time format, empty-state copy must be UNIFORM across Files/Live/ContextPane/ConversationList and the older chat/history/settings surfaces. List each divergence + the unifying fix.' + GROUND },
|
|
25
|
+
{ key: 'crosscut-perf-a11y-responsive-security', prompt: 'CROSS-CUTTING: performance + a11y + responsive + security across ALL surfaces. Perf: audit scheduleRender/scheduleStreamRender coalescing, EventList building full body for hundreds of rows, FileGrid for large dirs, ConversationList re-rendering on every 3s active poll - find per-frame O(n) waste + a fix. A11y: each new surface (Files/Live/ContextPane/ConversationList/rail) needs roles, aria, focus management, skip-link reach, keyboard operability - list gaps. Responsive: every surface at 420px + 1440px - no h-scroll, columns reflow, FileGrid + SessionDashboard wrap. Security: re-audit /api/list + /api/image + /api/file allowlist confinement (normalize + resolved-prefix, 403 outside roots), CORS gating under PASSWORD, markdown XSS (safeUrl + DOMPurify), WS token threading - confirm each holds or name the hole. List each gap with file:line + fix.' + GROUND },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const GAP_SCHEMA = {
|
|
29
|
+
type: 'object',
|
|
30
|
+
required: ['surface', 'gaps'],
|
|
31
|
+
properties: {
|
|
32
|
+
surface: { type: 'string' },
|
|
33
|
+
gaps: {
|
|
34
|
+
type: 'array',
|
|
35
|
+
items: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
required: ['title', 'where', 'fixLocation', 'fix', 'severity'],
|
|
38
|
+
properties: {
|
|
39
|
+
title: { type: 'string', description: 'the primitive/rough edge or missing affordance' },
|
|
40
|
+
where: { type: 'string', description: 'file:line or component the gap lives in' },
|
|
41
|
+
fixLocation: { type: 'string', enum: ['kit', 'app', 'server', 'kit+app'], description: 'where the fix lands' },
|
|
42
|
+
fix: { type: 'string', description: 'the concrete change: component/prop/css/wiring' },
|
|
43
|
+
severity: { type: 'string', enum: ['high', 'medium', 'low'] },
|
|
44
|
+
keptTypography: { type: 'boolean', description: 'true if this touches the middot/ellipsis/dash set - which must NOT be flagged as a glyph violation' },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const VERDICT_SCHEMA = {
|
|
52
|
+
type: 'object',
|
|
53
|
+
required: ['title', 'real', 'reason'],
|
|
54
|
+
properties: {
|
|
55
|
+
title: { type: 'string' },
|
|
56
|
+
real: { type: 'boolean', description: 'true if the gap is real and the fix is sound against the live source' },
|
|
57
|
+
reason: { type: 'string', description: 'why - cite the source you read' },
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
phase('Polish');
|
|
62
|
+
// Pipeline: each surface is polished, then every gap it found is adversarially
|
|
63
|
+
// verified as soon as that surface returns - no barrier between phases.
|
|
64
|
+
const verified = await pipeline(
|
|
65
|
+
SURFACES,
|
|
66
|
+
(s) => agent(s.prompt, { label: 'polish:' + s.key, phase: 'Polish', schema: GAP_SCHEMA }),
|
|
67
|
+
(report, s) => parallel((report?.gaps || []).map((g) => () =>
|
|
68
|
+
agent(
|
|
69
|
+
'Adversarially verify this GUI polish gap against the REAL source (read the cited file - do not trust the claim). '
|
|
70
|
+
+ 'KEPT-TYPOGRAPHY GUARD: the middot, ellipsis, and em/en-dash are intentional product typography - if the "gap" is merely flagging one of those as a decorative glyph, it is NOT real (real=false). '
|
|
71
|
+
+ 'A gap is real only if the primitive/rough edge genuinely exists in the shipped source AND the proposed fix is sound and lands in the right place (kit vs app). '
|
|
72
|
+
+ 'Gap: ' + JSON.stringify(g),
|
|
73
|
+
{ label: 'verify:' + (g.title || '').slice(0, 32), phase: 'Verify', schema: VERDICT_SCHEMA }
|
|
74
|
+
).then((v) => ({ ...g, surface: report.surface, verdict: v }))
|
|
75
|
+
))
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const confirmed = verified.flat().filter(Boolean).filter((g) => g.verdict && g.verdict.real);
|
|
79
|
+
log('confirmed ' + confirmed.length + ' real polish gaps across ' + SURFACES.length + ' surfaces');
|
|
80
|
+
|
|
81
|
+
phase('Plan');
|
|
82
|
+
const plan = await agent(
|
|
83
|
+
'Synthesize these adversarially-confirmed GUI polish gaps into a dependency-ordered, kit-vs-app build plan for agentgui + the anentrypoint-design kit. '
|
|
84
|
+
+ 'Group by fixLocation (kit first - they unblock app wiring), order so shared kit components (ConversationList, SessionDashboard, AgentChat, FileGrid, WorkspaceShell) are edited once with all their changes batched, then app wiring, then the build+vendor+witness step. '
|
|
85
|
+
+ 'Call out which gaps share a component (batch them), which are independent (parallelizable), and any that conflict. '
|
|
86
|
+
+ 'Confirmed gaps: ' + JSON.stringify(confirmed),
|
|
87
|
+
{ label: 'synthesize-plan', phase: 'Plan' }
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return { confirmed, plan, surfaceCount: SURFACES.length, confirmedCount: confirmed.length };
|
package/AGENTS.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# AgentGUI — Agent Notes
|
|
2
2
|
|
|
3
|
+
## GUI predictability + polish sweep (2026-06-05) — fifth maximum-effort run
|
|
4
|
+
|
|
5
|
+
A polish sweep on top of the shipped Claude-Desktop redesign (workflow `wf_980345e1-201`, 65 agents -> 44 adversarially-confirmed gaps, punch-list `PUNCHLIST-POLISH.md`). New workflow deliverable `.claude/workflows/gui-predictability-polish.js` (per-surface polish -> adversarial verify with kept-typography guard -> dependency-ordered plan; distinct from `gui-audit` which hunts jank and `gui-overhaul` which designs new surfaces — this one hunts the *primitive/half-wired* edge in the SHIPPED shell).
|
|
6
|
+
|
|
7
|
+
**Kit changes (`c:\dev\anentrypoint-design`, rebuilt + vendored into `site/app/vendor/`).** (1) **files.js** — `FileGrid` gained `sort{key,dir,onSort}` + clickable column header (`FileSortHeader`, ASCII `asc/desc` not glyphs), `filter`, `loading` (renders new `FileSkeleton` shimmer), and keyboard nav (`role=listbox` + roving focus over `.ds-file-open`, Arrow/Home/End + Backspace->`onUp`); new exports `FileSkeleton`+`sortFiles` (dirs-first stable sort). (2) **sessions.js** — `SessionCard` adds a words+disc status (`.ds-dash-status`, WCAG 1.4.1 — was colour-only), `lastActivity`+`currentTool` (`.ds-dash-activity`, so stuck vs busy differ), composes `counter`; `SessionDashboard` gained an `onStopAll` bulk header (`.ds-dash-header` count + stop-all). (3) **chat.js** — `ChatMessage` `streaming` prop -> blinking `.chat-stream-caret`; `actions[]` -> hover `.chat-msg-actions` row. (4) **agent-chat.js** — `.agentchat-thread-wrap` + `.agentchat-jump` (scroll-listener reveals jump-to-latest when scrolled up; scroll-anchoring no longer fights a reading user); wires `onCopyMessage/onRetryMessage/onEditMessage` + `streaming`. (5) **context-pane.js** — `usage` prop -> a `last turn` panel (tokens/cost/turns/duration — the dropped `result` event). (6) **shell.js (LOAD-BEARING mobile fix)** — the `<900px` sessions + pane drawers were DEAD (`.ws-sessions-open`/`.ws-pane-open` never toggled, no scrim): added `toggleWsDrawer`/`closeWsDrawers` + a `.ws-scrim` + crumb-hosted drawer toggles + Esc-close + auto-close-on-select; pane mobile reveal now keys off `.ws-pane-open` not `:not(.ws-pane-collapsed)`; rail/pane toggle aria-labels flip expand/collapse (were stale). chat.css: `.ds-session-group`/`-rows`/sticky label, session new+search bumped to 44px touch targets.
|
|
8
|
+
|
|
9
|
+
**App wiring (`site/app/js/app.js`).** `sessionGroups()` -> kit `groups` (Running pinned + Today/Yesterday/This-week/Earlier); chat-tab inline search now shows server hits in the rail on BOTH tabs (was a dead control); `liveMain` fills per-session metrics/last-activity/current-tool from `sessionsBySid` + `stopAllActive`; `startLiveTick()` 1s elapsed advance; `filesMain` sort/filter/skeleton/roots-picker/always-toolbar/keyboard-up; initial `loadDir`/preview-fetch moved OUT of render (`navTo('files')` effect + scheduled microtasks) — render is pure; `sendChat` captures `result.usage` -> `state.chat.usage`; `copyMessageText/retryLastTurn/editAndResend` message actions; `refreshActive` diffs `activeSig()` so the 3s poll only re-renders on real change.
|
|
10
|
+
|
|
11
|
+
**Security (`lib/http-handler.js`).** New `confineToRoots()` shared helper adds `fs.realpathSync` re-confinement to `/api/list`, `/api/file`, `/api/image` — a symlink living inside an allowed root but pointing OUTSIDE it passed the lexical prefix check but the resolved target now fails closed (symlink-escape / link-traversal, the workflow's one high-severity server gap).
|
|
12
|
+
|
|
13
|
+
**Witness.** Live at `localhost:3000/gm/`, 0 console/page errors: shell+5 rail items, session groups [Today,Earlier], files sort(`size asc`)/filter-narrows/keyboard-focus-moves, grid `role=listbox`, live dashboard empty-state, ContextPane, jump button + scrim present; pane reflow chat=4cols files/live/settings=2cols(`ws-no-pane`) history=3cols with NO h-scroll on any tab; 420px mobile sessions-drawer opens + scrim visible + no h-scroll; whole-DOM glyph sweep count:0 (kept middot/ellipsis/dash). Kit `lint-tokens`+`lint-glyphs` pass on build. Deliberately scoped-out (noted in punch-list, not gaps): inline split-pane file preview (modal retained — predictable, focus-trapped) and persistent mid-conversation suggestions (empty-only starter pattern kept). Update flow unchanged: edit kit -> `node scripts/build.mjs` -> copy `dist/247420.{js,css}` into `site/app/vendor/anentrypoint-design/` -> witness -> push kit.
|
|
14
|
+
|
|
15
|
+
## Claude-Desktop redesign + embedding fix (2026-06-05) — fourth maximum-effort run
|
|
16
|
+
|
|
17
|
+
A full GUI overhaul toward a claude.ai/code / Claude Desktop / cowork feel, plus a no-compromises fix to the gm-plugkit WASM embedding wedge.
|
|
18
|
+
|
|
19
|
+
**Shell.** The app moved from Topbar-tabs to a **three-column WorkspaceShell** (new kit component in `shell.js`: `WorkspaceShell({rail, sessions, main, pane, crumb, status, narrow})` + `WorkspaceRail({brand, action, items, footer})`, CSS `.ws-*` in `app-shell.css`, grid layout, collapse persisted to `localStorage ds.ws.{rail,pane}`, mobile <900px = fixed rail + overlay drawers). `app.js view()` composes it; a left rail nav drives `chat/history/files/live/settings` (keyboard `g+c/h/f/l/s`).
|
|
20
|
+
|
|
21
|
+
**New surfaces.** (1) **Conversation rail** — kit `ConversationList` (`sessions.js`, `.ds-session*`): the chat+history tabs share a session list (title/project/time/running dot/rail tone, inline search, New chat). `app.js sessionsColumn()` feeds it; chat-tab select -> `resumeInChat`, history-tab -> `loadSession`. Sessions load on chat-tab entry + boot (not just History). (2) **Files view** — server `/api/list` (`lib/http-handler.js`, allowlist-confined like `/api/image`: STARTUP_CWD/CLAUDE_PROJECTS_DIR/FS_ROOTS, normalize+resolved-prefix, 403 outside) + `backend.js listDir()` + `app.js filesMain()` rendering kit `BreadcrumbPath`+`FileGrid`; "use as chat cwd" sets the working dir by browsing. Mirrors the existing `c:\dev\fsbrowse` (same kit) but is a thin in-process endpoint, not the fsbrowse server. (3) **Live dashboard** — kit `SessionDashboard`/`SessionCard` (`sessions.js`, `.ds-dash*`): `app.js liveMain()` maps `state.active` (the existing 3s `chat.active` poll) to cards with per-session Stop/Open/Resume/events acting on each sid independently; empty + offline states.
|
|
22
|
+
|
|
23
|
+
**webjsx keying class-bug (load-bearing).** Mixing keyed VElements with `null`/strings in any children array crashes `applyDiff` ("reading 'key'"). Fixed in `ConversationList` (stable keyed body wrapper so loading/empty/populated diff children not container; `[...].filter(Boolean)` on conditional row children) AND `app.js runningPanel` (all three row children keyed). Also `refreshHistory` `render()` moved OUT of the try so a render exception no longer masquerades as a history fetch error. See the existing webjsx note below.
|
|
24
|
+
|
|
25
|
+
**Embedding fix (no-compromises, user-demanded).** The gm-plugkit WASM (`c:\dev\rs-plugkit`, the SINGLE owner of `code_index.rs`+`embed.rs`; built `cargo build --release --target wasm32-wasip1 --no-default-features --features wasm --lib` via wasi-sdk 24, deployed to `~/.gm-tools/plugkit.wasm`) froze its heartbeat 5+ min on every git-digest change because `code_index::index()` cleared all embeddings and re-embedded every chunk synchronously. Fixed with **incremental re-embed**: per-file `crc32` content hash in a new `codeinsight-manifest` namespace; unchanged files reuse persisted chunk embeddings, only changed/new files re-embed, deleted files reaped; removed the pre-emptive `clear_codeinsight()` on digest-mismatch (kept it for explicit `rebuild:true`). One-time manifest-seeding pass on first index after deploy, then incremental. **Witnessed**: after seeding, a 2nd digest change rebuilt in ~4s with 134ms max heartbeat gap (was 5+ min), real cosine hits. Commit `rs-plugkit` `ab09ed0` (push pending network). The `host_vec_embed` delegate contract in `embed.rs` is preserved for a future host-side fast path.
|
|
26
|
+
|
|
27
|
+
**Workflow deliverable.** `.claude/workflows/gui-overhaul.js` — a redesign-driver (8 per-surface designers -> feasibility+policy review with override/glyph/token guards -> dependency-ordered build plan), distinct from the jank-hunting `gui-audit.js`.
|
|
28
|
+
|
|
29
|
+
**Witness.** All surfaces browser-witnessed at `http://localhost:3000/gm/`: WorkspaceShell renders, rail nav [Chat,History,Files,Live,Settings], sessions rows, files 60 rows + breadcrumb, live dashboard, rail collapse persists, 0 console errors, `decorativeGlyphs=[]` (kept middot intact), a11y roles/aria/skip-link, responsive 420px no h-scroll. Kit `lint-glyphs`+`lint-tokens` pass on every build. Detail in rs-learn (recall "agentgui Claude-Desktop redesign"). Update/publish flow unchanged: edit kit -> `node scripts/build.mjs` -> copy `dist/247420.{js,css}` into `site/app/vendor/anentrypoint-design/` -> browser-witness -> push kit.
|
|
30
|
+
|
|
31
|
+
## GUI-predictability sweep closure (2026-06-05) — third maximum-effort run
|
|
32
|
+
|
|
33
|
+
Fan-out reviewers (chat/history/settings/shell + perf/security/glyph/override) -> adversarial verify -> 19 PRD rows fixed+pushed: agentgui `fe94ade`, kit `anentrypoint-design` `236d6ef` (publish.yml -> npm/unpkg). The headline theme was **override-elimination**: index.html's `!important` overrides were converted to kit defaults (Topbar active-tab = tinted+underline; `PageHeader` `compact` prop -> `.ds-section-compact` margin-top:0; `Row` `cursor:pointer` for `role=button`/`a.row`; kit `Chat` dropped the decorative head `.dot`). Also: kit `ToolCallNode` `(no output)` placeholder for done+empty tools; kit `safeUrl()` rejects `javascript:`/`data:`/`file:` in `renderInline`/image/link parts (inline renderer bypasses DOMPurify); streaming chat text uses the `.chat-md` container to avoid settle reflow. App reconciliation/state fixes (distinct backend-status keys, per-sid running-dot key, stale-selectedSid clear, per-session live counter, toolLabel scalar fallback, expand/collapse-**shown** relabel, projectFilter cleared on search). `.claude/workflows/gui-audit.js` gained an `overrides` surface + a **KEPT-SET glyph guard** in both the reviewer and the adversarial verifier (the middot/ellipsis/em-dash are kept product typography — never flag them). Detail + the kit dist `git add -f` / rebase-rebuild caveat in rs-learn (recall "agentgui GUI-predictability sweep"). **index.html loads the kit from LOCAL `./vendor/anentrypoint-design/247420.{js,css}`** — the vendored copy IS what ships; update flow is edit kit -> `node scripts/build.mjs` -> copy dist into vendor -> browser-witness -> push kit.
|
|
34
|
+
|
|
3
35
|
## GUI-audit closure (2026-06-04 fan-out) — second maximum-effort sweep
|
|
4
36
|
|
|
5
37
|
`.claude/workflows/gui-audit.js` ran a 64-agent fan-out (9 per-surface reviewers -> adversarial verify -> synthesize) -> 44 confirmed findings (`AUDIT-PUNCHLIST.md`, 38 deduped), all fixed across server/app/kit and pushed (agentgui `eb1eab3`/`951404e`, kit `anentrypoint-design` `bb776aa` -> CI publishes npm/unpkg). Per-finding detail + key learnings (ccsniff SSE `{sid,payload}` unwrap, CSP must allow Google Fonts, DS `Select` promotes `title`->`aria-label`, index.html now loads the kit from local `./vendor/`, kit publish flow) in rs-learn (recall "agentgui GUI-audit closure").
|
|
@@ -173,6 +205,6 @@ GUI source keeps typographic product characters — the middot separator `·`, t
|
|
|
173
205
|
|
|
174
206
|
**`anentrypoint-design`'s `SearchInput` (internal `De`) sets `aria-label = label || placeholder`; it ignores any `aria-label` prop you pass.** To give the search box a real accessible name, pass `label:` (and a matching `placeholder:` for the visible hint). Passing only `aria-label` leaves AT announcing the placeholder. A post-render `setAttribute` race-loses against the DS re-render, so the prop is the only durable fix.
|
|
175
207
|
|
|
176
|
-
## DS load
|
|
208
|
+
## DS load = LOCAL vendor (resolved — the earlier unpkg note is stale)
|
|
177
209
|
|
|
178
|
-
**`index.html`
|
|
210
|
+
**`index.html` loads the DS kit from the local `./vendor/anentrypoint-design/247420.{js,css}`, NOT unpkg.** The prior "moved to unpkg @latest" note described a transient state that was reverted: the kit was re-vendored (with `AgentChat`) in `eb1eab3` and witnessed loading from `./vendor/` again (2026-06-04 and 2026-06-05 runs). The vendored copy IS the shipped UI — predictable, no upstream-publish drift. Update flow: edit the kit at `c:\dev\anentrypoint-design`, `node scripts/build.mjs`, copy `dist/247420.{js,css}` into `site/app/vendor/anentrypoint-design/`, browser-witness, then push the kit so unpkg stays in sync for other consumers. (The markdown stack marked/dompurify/prismjs still fetches from jsdelivr on first chat render.)
|