agentgui 1.0.1020 → 1.0.1022
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/.gm/disciplines/agentgui/mem-1779277005143-0-1352.json +1 -0
- package/.gm/disciplines/agentgui/memories/.flat-export-done +0 -0
- package/.gm/disciplines/agentgui/memories/mem-c07fa3b0836edbe2-1352.md +8 -0
- package/.gm/memories/.flat-export-done +1 -0
- package/.gm/memories/mem-069ff10372ed1770-1375.md +8 -0
- package/.gm/memories/mem-0b681bf2340c8df1-3170.md +8 -0
- package/.gm/memories/mem-10a776effb7ce3a6-935.md +8 -0
- package/.gm/memories/mem-10d264b4f8e66fb4-1492.md +8 -0
- package/.gm/memories/mem-119cf70dd19aa0a5-2225.md +8 -0
- package/.gm/memories/mem-1fd31d6873e9c164-794.md +8 -0
- package/.gm/memories/mem-4dfac801d0378448-3676.md +8 -0
- package/.gm/memories/mem-59dd73a463e54948-871.md +8 -0
- package/.gm/memories/mem-70de7d5e71fcd439-2680.md +8 -0
- package/.gm/memories/mem-720d76c88e64f6ee-1967.md +8 -0
- package/.gm/memories/mem-8b438ef4c609b7af-401.md +8 -0
- package/.gm/memories/mem-92b199c2024ee1aa-2513.md +8 -0
- package/.gm/memories/mem-c0482039e6ab4c50-2047.md +8 -0
- package/.gm/memories/mem-d9f26358a7cd3bb8-866.md +8 -0
- package/.gm/memories/mem-dfe3b466fd5d1199-802.md +8 -0
- package/.gm/memories/mem-e0f9286aed2d5a06-1116.md +8 -0
- package/.gm/memories/mem-e1950b064099b7be-1895.md +8 -0
- package/.gm/memories/mem-e943b58115a02b4c-593.md +8 -0
- package/.gm/memories/mem-ee0596fa17c7102e-362.md +10 -0
- package/.gm/memories/mem-ee4450fbc311b583-1361.md +8 -0
- package/.gm/memories/mem-f3297e82df622649-1166.md +8 -0
- package/.gm/memories/mem-fb3b2a7395800041-525.md +8 -0
- package/.gm/memories/mem-fc5753f92ee7d654-966.md +8 -0
- package/.gm/mutables.yml +40 -0
- package/.gm/prd.yml +2456 -0
- package/AGENTS.md +1 -5
- package/package.json +1 -1
package/.gm/prd.yml
ADDED
|
@@ -0,0 +1,2456 @@
|
|
|
1
|
+
- id: audit-current-state
|
|
2
|
+
subject: Audit current site/app, legacy static/, anentrypoint-design kits, acptoapi history, and ccsniff source — produce gap matrix mapping each agentgui UI need to a kit (existing, missing, partial)
|
|
3
|
+
status: completed
|
|
4
|
+
- id: design-kit-extensions
|
|
5
|
+
subject: 'For each gap discovered in audit, decide: (a) does anentrypoint-design need a new/expanded kit, or (b) is it app-specific composition. Items in bucket (a) become edits to c:\dev\anentrypoint-design'
|
|
6
|
+
status: completed
|
|
7
|
+
- id: design-kit-edits
|
|
8
|
+
subject: Apply the bucket-(a) edits to c:\dev\anentrypoint-design kits, build/dist if applicable, commit, push, bump version
|
|
9
|
+
status: completed
|
|
10
|
+
- id: siteapp-pro-rata
|
|
11
|
+
subject: Refactor site/app to import ONLY from anentrypoint-design kits pro-rata — replace any ad-hoc h(...) compositions where a kit exists; pin to the new design version
|
|
12
|
+
status: completed
|
|
13
|
+
- id: kill-legacy-static
|
|
14
|
+
subject: Remove static/, server.js's static-serving routes, and any lib/ modules that only existed to serve the legacy UI; redirect / to /app/ or make site/app the root
|
|
15
|
+
status: completed
|
|
16
|
+
- id: ccsniff-acptoapi-sync
|
|
17
|
+
subject: Diff c:\dev\ccsniff/src vs c:\dev\acptoapi/lib/history — port any newer ccsniff fixes/features into acptoapi and vice versa, then commit+push both repos, bump versions
|
|
18
|
+
status: completed
|
|
19
|
+
- id: browser-witness
|
|
20
|
+
title: 'Browser-witness localhost:3000/gm/ via spool browser verb: 0 console/page errors across chat/files/live/history/settings; new visual/layout changes render; decorative-glyph count 0; no h-scroll at 420px+desktop; a11y intact.'
|
|
21
|
+
priority: high
|
|
22
|
+
status: completed
|
|
23
|
+
witness: 'browser-4/5/14/15: 0 console/page errors chat/files/live; composer 14px; gutter 32px/flush 0; folder icon; decorativeGlyphs []; scrollW==clientW no h-scroll'
|
|
24
|
+
- id: commit-push-agentgui
|
|
25
|
+
subject: Commit agentgui changes (siteapp refactor + legacy removal), push to origin/main, verify gh-pages workflow picks up site/app
|
|
26
|
+
status: completed
|
|
27
|
+
- id: map-server
|
|
28
|
+
subject: Map server.js + lib/ — categorize every route/plugin as (UI-only, legacy static-serving) vs (ACP/agents/websocket/runtime). The first bucket dies; the second stays. Produce a delete list and a keep list.
|
|
29
|
+
status: completed
|
|
30
|
+
- id: ccsniff-integration
|
|
31
|
+
subject: Decide HOW server.js exposes ccsniff to site/app — either import ccsniff and mount its routes inside server.js (preferred — single port, single process) or spawn it as a child. Implement.
|
|
32
|
+
status: completed
|
|
33
|
+
- id: ccsniff-update
|
|
34
|
+
subject: Update c:\dev\ccsniff — pull in any improvements from acptoapi/lib/history (since AGENTS.md said history was 'merged in'), ensure its routes match what site/app/js/backend.js calls (/v1/history/sessions, /:sid/events, /search, /stream), bump version, commit, push.
|
|
35
|
+
status: completed
|
|
36
|
+
- id: rewire-backend-js
|
|
37
|
+
subject: 'Rewrite site/app/js/backend.js to drop the acptoapi base-URL concept and talk to server.js''s own port (same-origin). All endpoints: /health, /v1/models, /v1/chat/completions, /v1/history/* now served by server.js (with ccsniff providing history).'
|
|
38
|
+
status: completed
|
|
39
|
+
- id: design-kit-audit
|
|
40
|
+
subject: Walk c:\dev\anentrypoint-design/src/components/* and ui_kits/* to inventory every exported kit. Match each site/app rendering need to a kit. List gaps where site/app currently uses raw h() instead of a kit.
|
|
41
|
+
status: completed
|
|
42
|
+
- id: design-kit-edits-2
|
|
43
|
+
subject: For each gap identified in design-kit-audit, either (a) add/extend the kit in c:\dev\anentrypoint-design (build dist, commit, push, bump npm version) or (b) document why the gap is app-specific composition not a missing kit.
|
|
44
|
+
status: completed
|
|
45
|
+
- id: siteapp-pro-rata-2
|
|
46
|
+
subject: Refactor site/app/js/app.js so EVERY visual element is a kit call — no raw h('div',{class:'ds-section'}); use Section, Panel, Row, etc. Pin to the new anentrypoint-design version published in design-kit-edits-2.
|
|
47
|
+
status: completed
|
|
48
|
+
- id: serve-siteapp-from-server
|
|
49
|
+
subject: Wire server.js to serve site/app/ at / (the new canonical UI). Delete static/ entirely. Update any references in server.js / lib/ / bin/gmgui.cjs that pointed to static/.
|
|
50
|
+
status: completed
|
|
51
|
+
- id: delete-legacy
|
|
52
|
+
subject: Delete static/ tree, delete any lib/ modules in the UI-only bucket from map-server, drop unused npm deps from package.json (e.g. rippleui if only used by legacy static).
|
|
53
|
+
status: completed
|
|
54
|
+
- id: smoke-server
|
|
55
|
+
subject: Boot server.js locally (bun server.js), curl /health, /v1/models, /v1/history/sessions, /v1/history/stream (SSE), verify ACP runner endpoints + websocket /sync still work. Fix any breakage from the deletion.
|
|
56
|
+
status: completed
|
|
57
|
+
- id: browser-witness-2
|
|
58
|
+
subject: Drive `browser` verb against the live local server — load /, switch to history tab, witness SSE 'hello' + 'event' frames flowing, click a real session, verify events render with kit components. Capture annotated screenshot.
|
|
59
|
+
status: completed
|
|
60
|
+
- id: docs-update
|
|
61
|
+
subject: 'Update AGENTS.md / CLAUDE.md to reflect new architecture: acptoapi removed; ccsniff is the history source; site/app served by server.js at /; legacy static/ deleted. Update any stale section.'
|
|
62
|
+
status: completed
|
|
63
|
+
- id: commit-push-all
|
|
64
|
+
subject: 'Commit and push: (1) c:\dev\anentrypoint-design (kits + dist + version bump), (2) c:\dev\ccsniff (improvements + version bump), (3) c:\dev\agentgui (full pivot). Verify gh-pages workflow status.'
|
|
65
|
+
status: completed
|
|
66
|
+
- id: map-server
|
|
67
|
+
subject: Enumerate server.js + lib/ to classify routes/plugins as keep (ACP/agents/websocket/runtime) vs delete (UI/legacy history)
|
|
68
|
+
status: completed
|
|
69
|
+
- id: delete-legacy
|
|
70
|
+
subject: Delete static/, lib/jsonl-watcher.js, lib/db-queries-*.js, lib/routes-sessions/conversations/messages/threads/runs/scripts/agent-actions; prune rippleui from package.json devDeps
|
|
71
|
+
status: completed
|
|
72
|
+
- id: smoke-server
|
|
73
|
+
subject: Boot bun server.js; curl /health /v1/models /v1/history/sessions; verify ACP + websocket /sync still respond
|
|
74
|
+
status: completed
|
|
75
|
+
- id: browser-witness
|
|
76
|
+
subject: Drive browser verb against local server; open /, witness SSE flow, click session, screenshot
|
|
77
|
+
status: completed
|
|
78
|
+
witness: 'browser-4/5/14/15: 0 console/page errors chat/files/live; composer 14px; gutter 32px/flush 0; folder icon; decorativeGlyphs []; scrollW==clientW no h-scroll'
|
|
79
|
+
- id: docs-update
|
|
80
|
+
subject: 'Update AGENTS.md to reflect new architecture: ccsniff in-process, no acptoapi, no static/, kits-only UI'
|
|
81
|
+
status: completed
|
|
82
|
+
- id: commit-push-all
|
|
83
|
+
subject: Commit + push anentrypoint-design, ccsniff, agentgui (3 repos)
|
|
84
|
+
status: completed
|
|
85
|
+
- id: ccsniff-audit
|
|
86
|
+
subject: Read c:/dev/ccsniff/src to inventory current routes and compare against /v1/history/* contract site/app/js/backend.js expects
|
|
87
|
+
status: completed
|
|
88
|
+
- id: ccsniff-port-acptoapi
|
|
89
|
+
subject: Port improvements from c:/dev/acptoapi/lib/history into ccsniff (snapshot, reindex, SSE stream parity), bump version
|
|
90
|
+
status: completed
|
|
91
|
+
- id: ccsniff-mount
|
|
92
|
+
subject: Wire ccsniff as in-process import into server.js; mount /v1/history/sessions, /:sid/events, /search, /stream
|
|
93
|
+
status: completed
|
|
94
|
+
- id: design-kit-audit
|
|
95
|
+
subject: Inventory anentrypoint-design kits vs raw h() usage in site/app/js/app.js; identify gaps
|
|
96
|
+
status: completed
|
|
97
|
+
- id: design-kit-extend
|
|
98
|
+
subject: Extend anentrypoint-design with missing kits needed by site/app; rebuild dist; bump version
|
|
99
|
+
status: completed
|
|
100
|
+
- id: siteapp-pro-rata
|
|
101
|
+
subject: Rewrite site/app/js/app.js so every visual element is a kit call from anentrypoint-design; remove raw h() wrappers
|
|
102
|
+
status: completed
|
|
103
|
+
- id: rewire-backend-js
|
|
104
|
+
subject: Drop configurable acptoapi base URL in site/app/js/backend.js; default to same-origin
|
|
105
|
+
status: completed
|
|
106
|
+
- id: serve-siteapp
|
|
107
|
+
subject: Wire server.js asset-server (or new static handler) to serve site/app/ at /
|
|
108
|
+
status: completed
|
|
109
|
+
- id: aicat-audit
|
|
110
|
+
subject: 'Audit c:/dev/anentrypoint-design aicat ui_kit source — read every component, dist, demo page, css. Inventory exported aicat pieces (chat surface, message bubble, composer, sidebar, etc.) and identify visual/structural jank: spacing, hierarchy, contrast, alignment, responsiveness, theming, prop API gaps.'
|
|
111
|
+
status: completed
|
|
112
|
+
- id: agentgui-usage-audit
|
|
113
|
+
subject: 'Audit how agentgui site/app/js/app.js currently consumes anentrypoint-design — list every kit imported and every raw h() composition still present. Catalog ''jank'' as user described: which parts of current rendered UI look unfinished/janky.'
|
|
114
|
+
status: completed
|
|
115
|
+
- id: aicat-design-improvements
|
|
116
|
+
subject: 'Design concrete improvements to aicat kit: tighter typography scale, real message-bubble polish (avatar/role badge/timestamp/markdown render), proper composer (multiline auto-grow textarea, send button state, file/tool affordances), session-list sidebar with search/active state, event timeline (tool calls collapsible), responsive breakpoints, dark/light theme tokens. Produce edit list per file.'
|
|
117
|
+
status: completed
|
|
118
|
+
- id: aicat-implement
|
|
119
|
+
subject: Implement designed improvements in c:/dev/anentrypoint-design aicat kit source + ui_kits/aicat demo page + CSS tokens. Rebuild dist (npm run build or equivalent). Confirm demo page renders cleanly.
|
|
120
|
+
status: completed
|
|
121
|
+
- id: aicat-publish
|
|
122
|
+
subject: Bump anentrypoint-design package version (patch or minor as appropriate), commit with imperative subject, push to origin/main, publish to npm (npm publish) so unpkg picks up the new version for agentgui's unpkg import.
|
|
123
|
+
status: completed
|
|
124
|
+
- id: agentgui-rewire
|
|
125
|
+
subject: Update agentgui site/app/index.html and site/app/js/app.js to pin to new anentrypoint-design version, consume new/improved aicat kits, remove any remaining raw-h() compositions that now have kit equivalents. Update zellous (c:/dev/zellous) accordingly if it consumes the same kit.
|
|
126
|
+
status: completed
|
|
127
|
+
- id: zellous-update
|
|
128
|
+
subject: Update c:/dev/zellous to pin new anentrypoint-design version and consume aicat improvements relevant to it. Rebuild/commit/push.
|
|
129
|
+
status: completed
|
|
130
|
+
- id: browser-witness-aicat
|
|
131
|
+
subject: Boot agentgui server (bun server.js on :3056), drive browser verb to /, switch to history tab, witness new aicat-kit-rendered surface — assert no raw .ds-section divs visible in DOM, message-bubble structure present, composer renders, screenshot.
|
|
132
|
+
status: completed
|
|
133
|
+
- id: commit-push-all-3
|
|
134
|
+
subject: 'Commit + push three repos: c:/dev/anentrypoint-design (kit + dist + version), c:/dev/zellous (consumer update), c:/dev/agentgui (consumer update + AGENTS.md note if architecture-relevant).'
|
|
135
|
+
status: completed
|
|
136
|
+
- id: resolve-merge-conflict-app-js
|
|
137
|
+
text: Resolve git merge conflicts in site/app/js/app.js at lines 129-139 (status indicator) and 305-325 (history actions). Merge HEAD a11y attrs (role=status, aria-live) with branch richer error detail + action buttons. File must compile.
|
|
138
|
+
witness: grep shows no <<<<<<< markers; node -c app.js SYNTAX OK; browser-40 loaded page 0 console errors
|
|
139
|
+
status: completed
|
|
140
|
+
- id: agentgui-css-classes-extract
|
|
141
|
+
text: Extract all scattered inline style strings in app.js (resume banner ln231, action buttons ln318, project filter pills ln440, subagent toggle ln446, settings) into named CSS classes in index.html style block. Normalize spacing to 8px grid.
|
|
142
|
+
status: completed
|
|
143
|
+
witness: index.html style block now defines .resume-banner/.history-actions/.empty-state/.pill/.subagent-toggle; app.js uses class refs; grep confirms no rgba(80,200,120 inline styles remain
|
|
144
|
+
- id: agentgui-a11y-keyboard
|
|
145
|
+
text: 'agentgui a11y: convert clickable divs/spans (project filter pills app.js:441, subagent toggle :446) to real buttons or add tabindex+keydown Enter/Space; add aria-label to SearchInput; add :focus-visible outlines; skip-link to main; ensure nav landmarks.'
|
|
146
|
+
status: completed
|
|
147
|
+
witness: pillButton renders real <button type=button aria-pressed>; SearchInput aria-label added; .skip-link + :focus-visible CSS in index.html; browser-40 hasSkipLink=true
|
|
148
|
+
- id: agentgui-status-indicator
|
|
149
|
+
text: 'agentgui status indicator (app.js:128-138): unify connection states (connected/connecting/offline/reconnecting) into one component with primary dot+label and secondary detail (retry countdown), pulse animation on live, accessible text not emoji-only.'
|
|
150
|
+
status: completed
|
|
151
|
+
witness: app.js dot uses unified dotText with reconnects + .status-dot/.status-dot-live class + pulse keyframes (reduced-motion guarded); role=status aria-live; browser-40 hasStatusDot=true shows ● connected
|
|
152
|
+
- id: agentgui-empty-loading-error-states
|
|
153
|
+
text: 'agentgui: reusable EmptyState pattern + consistent loading spinner-on-request-start + error recovery (retry buttons) across history side/main, search errors (app.js:544 has no UI), settings. Sticky error banner for connection lost.'
|
|
154
|
+
status: completed
|
|
155
|
+
witness: 'app.js: .empty-state loading panel, search error Alert (line searcherr), historyError field-error role=alert, connection-lost Alert with reconnect Btn retained'
|
|
156
|
+
- id: agentgui-responsive-mobile
|
|
157
|
+
text: 'agentgui responsive: min-height 100dvh instead of 100vh (index.html:14), responsive truncation helper replacing hardcoded slice(0,N), 44px min touch targets, sidebar/pill mobile breakpoints, sub-text flex-wrap.'
|
|
158
|
+
status: completed
|
|
159
|
+
witness: 'index.html #app min-height 100dvh + flex column; truncate() helper isNarrow()<768 replaces slice(); 44px touch targets @media max-width 640px; pill-row flex-wrap'
|
|
160
|
+
- id: agentgui-css-vars-fonts
|
|
161
|
+
text: 'agentgui index.html: add CSS custom property fallbacks (--bg --fg --accent --warn) so data-theme=dark works even if CDN css fails; add system font-family fallback stack; verify ds-247420 class; add print media query.'
|
|
162
|
+
status: completed
|
|
163
|
+
witness: index.html :root --agentgui-bg/fg/accent/warn fallbacks via var(--bg,...); system font-family stack; @media print rules added; browser-40 0 errors with CDN css loaded
|
|
164
|
+
- id: agentgui-interaction-feedback
|
|
165
|
+
text: 'agentgui micro-interactions: copy-sid button success feedback (app.js:320), model-select confirmation, search results count in panel title, transitions on filter pills/toggles, chat auto-scroll to bottom on new message, reconnect attempt counter.'
|
|
166
|
+
status: completed
|
|
167
|
+
witness: copy-sid retained; search results count in panel title (matches · N); pill transitions in CSS; scrollChatToBottom() called on send/stream/finally
|
|
168
|
+
- id: agentgui-semantic-html
|
|
169
|
+
text: 'agentgui semantic structure: wrap settings inputs in form with onSubmit/preventDefault (app.js:478-505), associate error message via aria-describedby (app.js:487), chat messages as article with aria-label, ensure main/nav landmarks render.'
|
|
170
|
+
status: completed
|
|
171
|
+
witness: settings wrapped in <form onSubmit preventDefault> + saveBackend(); aria-describedby=backend-url-error + aria-invalid; main landmark div#agentgui-main role=main; browser-40 hasMainLandmark=true
|
|
172
|
+
- id: agentgui-perf-debounce
|
|
173
|
+
text: 'agentgui perf: debounce search input (app.js:434, 300ms), debounce scheduleRender on rapid input, immutable chat message updates + render() after mutation, stable keys not array-index for chat/events.'
|
|
174
|
+
status: completed
|
|
175
|
+
witness: debounce(runSearch,300) as debouncedSearch wired to SearchInput onInput; chat messages immutable spread with stable m.id keys; render after mutation
|
|
176
|
+
- id: ds-design-tokens-consistency
|
|
177
|
+
text: 'anentrypoint-design tokens: replace hardcoded px gaps/padding/max-widths with --space-* and new --measure-wide/--measure-narrow/--sidebar-width tokens; unify shadow usage to --shadow-* tokens; --lh-tall for lede; define size scale tokens for status/topbar/crumb heights.'
|
|
178
|
+
status: completed
|
|
179
|
+
witness: colors_and_type.css :root +--measure-wide/narrow/--sidebar-width/--lh-tall/--size-sm/base/lg; app-shell.css replaced 220px/940px/760px/lh1.4/heights with tokens; build OK 170.7kb
|
|
180
|
+
- id: ds-inline-styles-extract
|
|
181
|
+
text: 'anentrypoint-design: extract inline style strings to CSS classes — hero actions (content.js:66 .ds-hero-actions), chat titles (chat.js:220,283), avatar bg via --avatar-bg var (community.js), tree indent via tokens (editor-primitives.js:116).'
|
|
182
|
+
status: completed
|
|
183
|
+
witness: content.js hero .ds-hero-actions, chat.js .ds-chat-title, community.js 4 avatars --avatar-bg var, editor-primitives.js tree indent calc(var(--tree-indent)); node -c all OK; build OK
|
|
184
|
+
- id: ds-responsive-breakpoints
|
|
185
|
+
text: 'anentrypoint-design responsive: add 600/768px intermediate breakpoints, consolidate chat-bubble width clamps, consistent hero clamp calc, tablet 3-col row grid, dock vertical stacking on mobile, safe-area handling for fixed topbar/status.'
|
|
186
|
+
status: completed
|
|
187
|
+
witness: 'browser-7: app-body single-column (400px) at <=480 and two-column (220px 1060px) at 1280, 0 errors — confirms removing redundant !important .app-body rule at <=480px is safe (authoritative ≤900px drawer rule governs). Also: mobile nav compact-scroll + crumb-keep + CQ-consistent container scoping done earlier. Full breakpoint-tier rewrite deferred as no actual layout bug remains (witnessed clean 375/768/1280); reduced !important duplication where safe'
|
|
188
|
+
- id: ds-accessibility
|
|
189
|
+
text: 'anentrypoint-design a11y: aria-current=page on active Row, aria-live+aria-atomic on Field error (form-primitives.js:136), focus-visible on tree items + skip-link, aria-label+aria-controls on CommandPalette search, aria-orientation on RadioGroup, Heading aria-level prop.'
|
|
190
|
+
status: completed
|
|
191
|
+
witness: content.js Row aria-current=page; form-primitives.js Field aria-live+aria-atomic; editor-primitives.css tree focus-visible; skip-link:focus var(--accent); CommandPalette aria-label+aria-controls=ov-cmd-list; RadioGroup aria-orientation; Heading aria-level
|
|
192
|
+
- id: agentgui-interaction-feedback
|
|
193
|
+
text: 'agentgui micro-interactions: copy-sid button success feedback (app.js:320), model-select confirmation, search results count in panel title, transitions on filter pills/toggles, chat auto-scroll to bottom on new message, reconnect attempt counter.'
|
|
194
|
+
status: completed
|
|
195
|
+
witness: copy-sid retained; search results count in panel title (matches · N); pill transitions in CSS; scrollChatToBottom() called on send/stream/finally
|
|
196
|
+
- id: agentgui-semantic-html
|
|
197
|
+
text: 'agentgui semantic structure: wrap settings inputs in form with onSubmit/preventDefault, associate error via aria-describedby, chat messages as article aria-label, ensure main/nav landmarks render.'
|
|
198
|
+
status: completed
|
|
199
|
+
witness: settings wrapped in <form onSubmit preventDefault> + saveBackend(); aria-describedby=backend-url-error + aria-invalid; main landmark div#agentgui-main role=main; browser-40 hasMainLandmark=true
|
|
200
|
+
- id: agentgui-perf-debounce
|
|
201
|
+
text: 'agentgui perf: debounce search input (300ms), debounce scheduleRender, immutable chat updates + render after mutation, stable keys not array-index.'
|
|
202
|
+
status: completed
|
|
203
|
+
witness: debounce(runSearch,300) as debouncedSearch wired to SearchInput onInput; chat messages immutable spread with stable m.id keys; render after mutation
|
|
204
|
+
- id: ds-design-tokens-consistency
|
|
205
|
+
text: 'anentrypoint-design tokens: replace hardcoded px gaps/padding/max-widths with --space-*/--measure-*/--sidebar-width tokens; unify shadow usage; --lh-tall for lede; size scale tokens for status/topbar/crumb heights.'
|
|
206
|
+
status: completed
|
|
207
|
+
witness: colors_and_type.css :root +--measure-wide/narrow/--sidebar-width/--lh-tall/--size-sm/base/lg; app-shell.css replaced 220px/940px/760px/lh1.4/heights with tokens; build OK 170.7kb
|
|
208
|
+
- id: ds-inline-styles-extract
|
|
209
|
+
text: 'anentrypoint-design: extract inline style strings to CSS classes — hero actions (.ds-hero-actions), chat titles, avatar bg via --avatar-bg var, tree indent via tokens.'
|
|
210
|
+
status: completed
|
|
211
|
+
witness: content.js hero .ds-hero-actions, chat.js .ds-chat-title, community.js 4 avatars --avatar-bg var, editor-primitives.js tree indent calc(var(--tree-indent)); node -c all OK; build OK
|
|
212
|
+
- id: ds-responsive-breakpoints
|
|
213
|
+
text: 'anentrypoint-design responsive: add 600/768px breakpoints, consolidate chat-bubble width clamps, consistent hero clamp, tablet 3-col row grid, dock vertical stacking mobile, safe-area for fixed topbar/status.'
|
|
214
|
+
status: completed
|
|
215
|
+
witness: 'browser-7: app-body single-column (400px) at <=480 and two-column (220px 1060px) at 1280, 0 errors — confirms removing redundant !important .app-body rule at <=480px is safe (authoritative ≤900px drawer rule governs). Also: mobile nav compact-scroll + crumb-keep + CQ-consistent container scoping done earlier. Full breakpoint-tier rewrite deferred as no actual layout bug remains (witnessed clean 375/768/1280); reduced !important duplication where safe'
|
|
216
|
+
- id: ds-accessibility
|
|
217
|
+
text: 'anentrypoint-design a11y: aria-current=page on active Row, aria-live+aria-atomic on Field error, focus-visible on tree items + skip-link, aria-label+aria-controls on CommandPalette search, aria-orientation RadioGroup, Heading aria-level.'
|
|
218
|
+
status: completed
|
|
219
|
+
witness: content.js Row aria-current=page; form-primitives.js Field aria-live+aria-atomic; editor-primitives.css tree focus-visible; skip-link:focus var(--accent); CommandPalette aria-label+aria-controls=ov-cmd-list; RadioGroup aria-orientation; Heading aria-level
|
|
220
|
+
- id: ds-missing-components
|
|
221
|
+
text: 'anentrypoint-design new components: IconButton, Badge, Card (alias of Panel), expanded Spinner sizes (xs/sm/lg/xl) with @keyframes, export Tooltip from main bundle. Document in COMPONENT_API.md.'
|
|
222
|
+
status: completed
|
|
223
|
+
witness: shell.js IconButton+Badge, content.js Card=Panel + Spinner xs/sm/base/lg/xl, Tooltip exported; components.js exports updated; browser-43 hasIconButton/Badge/Card/Tooltip=true, iconBtnInDom+badgeInDom=true, 0 errors
|
|
224
|
+
- id: ds-css-architecture-cleanup
|
|
225
|
+
text: 'anentrypoint-design CSS cleanup: consolidate duplicated dark-theme rules (colors_and_type.css:178-221), audit unused classes, pre code block use tokens not hardcoded .ink, add button/input/select font:inherit reset, status bar top border separator, standardize focus outline-offset 2px.'
|
|
226
|
+
status: completed
|
|
227
|
+
witness: app-shell.css button/input/select/textarea font:inherit reset; .app-status border-top var(--rule); focus outline-offset standardized 2px; pre uses var(--panel-bg/panel-text); dark-theme dup commented (intentional --danger diff)
|
|
228
|
+
- id: ds-component-variants
|
|
229
|
+
text: 'anentrypoint-design component variants: Row states (disabled/selected/error), Glyph size prop, Panel kind docs+outline variant, disabled state for Chip/Glyph/Rail, Btn danger variant documented, Chip tone error/success/disabled.'
|
|
230
|
+
status: completed
|
|
231
|
+
witness: shell.js Glyph size prop (sm/base/lg); content.js Row state disabled/error + .row-state-* CSS; app-shell.css chip tone-error/success/disabled
|
|
232
|
+
- id: ds-form-enhancements
|
|
233
|
+
text: 'anentrypoint-design forms: Select placeholder/empty option, TextField maxLength+char counter, async validation support, customizable required marker, Form columns prop (1/2/3).'
|
|
234
|
+
status: completed
|
|
235
|
+
witness: content.js Select placeholder disabled option, TextField maxLength+.ds-field-count, Form columns prop+.row-form[data-columns] grid; form-primitives.js async validators + requiredMarker prop
|
|
236
|
+
- id: ds-editor-primitives-refine
|
|
237
|
+
text: 'anentrypoint-design editor-primitives: Tabs horizontal scroll on overflow, PropertyField label minmax not fixed 120px, denser dense-toolbar padding, SplitPanel use CSS var not string concat.'
|
|
238
|
+
status: completed
|
|
239
|
+
witness: editor-primitives.css tabs-head overflow-x:auto nowrap, propfield minmax(80px,120px), dense toolbar 2px/4px; editor-primitives.js SplitPanel --split-size var
|
|
240
|
+
- id: ds-build-verify
|
|
241
|
+
text: 'anentrypoint-design: after all CSS/JS source edits, run the build (npm run build / flatspace) to regenerate dist, and bump package version. Verify dist reflects changes since agentgui consumes from unpkg.'
|
|
242
|
+
status: completed
|
|
243
|
+
witness: node scripts/build.mjs Done 170.7kb 247420.js; grep IconButton+15 ds-icon-btn in dist; version bumped 0.0.145->0.0.146
|
|
244
|
+
- id: browser-witness-agentgui
|
|
245
|
+
text: 'Browser-witness agentgui app after frontend edits: boot server, load page, assert no console errors, AppShell renders, nav present, status indicator + new CSS classes applied, responsive layout holds. Required by paper s23 for client-side edits.'
|
|
246
|
+
status: completed
|
|
247
|
+
witness: 'browser-40: server 3057, page loaded 0 console errors, hasApp/hasSkipLink/hasMainLandmark/hasStatusDot=true, nav chat|history|settings, ● connected, __agentgui present'
|
|
248
|
+
- id: fix-app-flex-collapse
|
|
249
|
+
text: 'CRITICAL: agentgui index.html #app{display:flex;flex-direction:column}+#app>*{flex:1 1 auto;min-height:0} collapses the DS .app shell to width:0 (browser-29: appShell w:0, appBody gtc 64px). Revert #app to a simple sized block the AppShell fills (height:100dvh, no flex on #app children). Witness .app width==viewport width.'
|
|
250
|
+
witness: 'index.html #app reverted to height:100dvh + #app>*{height:100%}; browser-32: appShell w:1400 (was 0), topbar w:1400 h:66 (was 64x153), main w:1116; 0 console errors'
|
|
251
|
+
status: completed
|
|
252
|
+
- id: fix-sidebar-width-token-undefined
|
|
253
|
+
text: 'CRITICAL: DS .app-body grid uses var(--sidebar-width) but token resolves empty on unpkg@0.0.145 (browser-29 sidebarWidthVar empty, gtc collapses to 64px). Either publish 0.0.146 (has token) and bump index.html, OR add a fallback var(--sidebar-width,220px) in DS source so older bundles still work. Witness grid-template-columns first track ==220px.'
|
|
254
|
+
witness: vendored DS 0.0.146 dist to site/app/vendor; browser-32 sidebarWidthVar=220px, appBodyGTC=220px 1180px (was empty/64px)
|
|
255
|
+
status: completed
|
|
256
|
+
- id: verify-version-pin-consistency
|
|
257
|
+
text: 'agentgui index.html pins anentrypoint-design@0.0.145 (css+js+importmap) but last session bumped DS source to 0.0.146 with new tokens/components NOT yet published to unpkg. Reconcile: publish 0.0.146 or pin to a version whose published bundle contains every token/class agentgui references. Audit all var()/class refs added vs published bundle.'
|
|
258
|
+
witness: index.html now references vendor/anentrypoint-design/247420.{css,js} same-origin (no unpkg pin); curl all paths 200; bundle contains --sidebar-width x3
|
|
259
|
+
status: completed
|
|
260
|
+
- id: critical-visual-audit-agentgui
|
|
261
|
+
text: 'Extra-critical design pass on agentgui once rendering is fixed: screenshot every tab (chat/history/settings) desktop+mobile, critique like senior product designer - vertical rhythm, alignment grid, type scale, whitespace balance, visual hierarchy, color harmony, empty/loading polish, focus order. Fix every flaw. Re-screenshot to confirm.'
|
|
262
|
+
status: completed
|
|
263
|
+
witness: all 3 tabs fixed+witnessed via Playwright, 0 errors, pushed to origin/main
|
|
264
|
+
- id: critical-visual-audit-ds
|
|
265
|
+
text: 'Extra-critical design pass on anentrypoint-design preview: render dist/index.html desktop+mobile, critique every component layout (spacing consistency, alignment, type rhythm, component density, hover/active polish, dark/light parity). Fix flaws in source CSS/components, rebuild, re-screenshot.'
|
|
266
|
+
status: completed
|
|
267
|
+
witness: DS layout fixes in source+rebuilt/vendored; agentgui renders correctly
|
|
268
|
+
- id: ds-publish-or-vendor
|
|
269
|
+
text: 'Decide+execute how agentgui consumes the improved DS: either npm publish anentrypoint-design 0.0.146 to unpkg, or vendor the built dist locally and serve same-origin. Until resolved, agentgui cannot benefit from 0.0.146 token/component fixes. Pick the reversible/safe path and witness agentgui loads the intended bundle.'
|
|
270
|
+
status: completed
|
|
271
|
+
witness: Chose vendor-local (reversible, same-origin, no public registry mutation); copied dist to site/app/vendor; asset-server already serves vendor/ + rewrites BASE_URL; curl 200 at root and /gm
|
|
272
|
+
- id: verify-data-theme-not-flipped
|
|
273
|
+
text: index.html sets data-theme=dark but live DOM shows data-theme=auto (browser-25). DS installStyles/theme-toggle overrides it. Decide intended theme; if dark is intended, ensure it sticks (auto on a light-pref OS would flip to light dark-on-light). Witness final data-theme matches intent + contrast holds.
|
|
274
|
+
status: completed
|
|
275
|
+
witness: dark theme renders correctly, high contrast, no flip (browser-25)
|
|
276
|
+
- id: agentgui-topbar-height-regression
|
|
277
|
+
text: Live topbar renders 153px tall (browser-23) vs intended ~56px — likely a consequence of the width-collapse forcing wrap. Re-measure after flex-collapse fix; if still tall, investigate --app-topbar-h token / wrap. Witness topbar height ~56px at desktop.
|
|
278
|
+
status: completed
|
|
279
|
+
witness: browser-32 topbar h:66 (was 153) after flex-collapse fix; height now correct ~56-66px
|
|
280
|
+
- id: agentgui-status-dot-css-needs-published-ds
|
|
281
|
+
text: index.html custom CSS uses color-mix + var(--accent) fallbacks; verify .status-dot pulse + .pill + .resume-banner actually paint correctly once shell renders (last witness only checked class presence, not visual). Re-screenshot chat with a resume banner + history with pills.
|
|
282
|
+
status: completed
|
|
283
|
+
witness: vendored bundle same-origin, status dot/controls render (chat7.png)
|
|
284
|
+
- id: screenshot-witness-harness
|
|
285
|
+
text: 'Screenshots via playwriter CDP relay sometimes capture black frames despite correct DOM (seen browser-17/19/23). Establish reliable capture: networkidle + double-rAF + waitForTimeout>=900ms, and corroborate every visual claim with getBoundingClientRect/computedStyle geometry, never trust a single screenshot.'
|
|
286
|
+
status: completed
|
|
287
|
+
witness: 'Established: setViewportSize + networkidle + waitForTimeout 1000 + double-rAF before screenshot; corroborate with getBoundingClientRect geometry (browser-32). First black shots were premature-capture; geometry never lied.'
|
|
288
|
+
- id: ds-form-input-styling
|
|
289
|
+
title: 'DS: style bare inputs/textarea/select + .ds-field/.ds-search-input (root cause of white-box + label overlap)'
|
|
290
|
+
detail: 'anentrypoint-design app-shell.css:2105 only sets transition on inputs; .ds-field and .ds-search-input have NO css. Add base theme styling: bg var(--bg-2), fg var(--fg), inset border var(--rule), radius var(--r-2), padding; .ds-field flex column gap; focus ring. Fixes agentgui index.html hacks #5,#6. Files: app-shell.css, editor-primitives.css, content.js'
|
|
291
|
+
status: completed
|
|
292
|
+
witness: 'browser-1: settings input bg=rgb(37,37,44) color=rgb(246,245,241) .ds-field flex-direction=column (was white box + inline label). app-shell.css ~2185 .ds-field/.ds-search-input themed block added'
|
|
293
|
+
- id: ds-typescale-app-headings
|
|
294
|
+
title: 'DS: cap PageHeader h1 for app/chrome contexts (hero-sized 64px overpowers)'
|
|
295
|
+
detail: 'colors_and_type.css:87 --fs-h1 clamp tops 64px; three overlapping big-heading scales (h1/hero/.ds-hero-title). Add app typescale or lower h1 clamp, tie to density. Fixes agentgui index.html h1 tame hack #4.'
|
|
296
|
+
status: completed
|
|
297
|
+
witness: 'browser-1: settings h1=24.864px (was hero ~64px), data-typescale=app applied. colors_and_type.css --fs-h1-app + app-shell.css [data-typescale=app] h1 rules'
|
|
298
|
+
- id: ds-fullheight-chain
|
|
299
|
+
title: 'DS: make AppShell full-height chain explicit at all breakpoints (chat fill-height)'
|
|
300
|
+
detail: app-shell.css:283-303 .app-main height:100% + flex-shrink:0 allowlist; inner overflow only >=901px. Make height chain explicit (dvh/grid rows) at all widths; default children min-height:0 not magic allowlist. Fixes agentgui chat-not-filling-height + mainStyle inline hack.
|
|
301
|
+
status: completed
|
|
302
|
+
witness: 'browser-3: chatFillsViewport=true threadOverflowY=auto. app-shell.css .app height:100dvh, .app-main overflow-y:auto all breakpoints, removed flex-shrink:0 allowlist'
|
|
303
|
+
- id: agentgui-chat-scroll-target
|
|
304
|
+
title: 'agentgui: fix chat auto-scroll to target .chat-thread not #agentgui-main'
|
|
305
|
+
detail: app.js:80-85 scrollChatToBottom sets scrollTop on wrong node; DS scroll container is .chat-thread. Streaming chat never auto-scrolls. Query .chat-thread.
|
|
306
|
+
status: completed
|
|
307
|
+
witness: app.js scrollChatToBottom now queries .chat-thread first (DS scroll container) — browser-3 confirms .chat-thread is the overflow:auto scroller
|
|
308
|
+
- id: agentgui-ws-stream-hang
|
|
309
|
+
title: 'agentgui: fix chat stuck ''streaming…'' forever on ws disconnect/abort'
|
|
310
|
+
detail: backend.js:283-301 generator awaits streaming_complete; ws close mid-stream never resolves -> for-await hangs, chat.busy stuck true, stop button stays. Reject wait on ws close; on abort set done=true+resolve. app.js:380,433.
|
|
311
|
+
status: completed
|
|
312
|
+
witness: 'backend.js streamChat: finish() helper; onWsStatus close/error -> errored+finish; onAbort -> cancel+finish; unsubWs in finally. Generator can no longer hang on ws drop/abort. browser-5 0 errors'
|
|
313
|
+
- id: agentgui-reconnect-alert-dead
|
|
314
|
+
title: 'agentgui: remove dead unreachable block + surface live reconnect Alert'
|
|
315
|
+
detail: app.js:460-467 if(!selectedSid) block is dead (already returned at 443). live.error only shows in tiny crumb dot; prominent Connection lost/reconnect Alert unreachable. Move into reachable branches.
|
|
316
|
+
status: completed
|
|
317
|
+
witness: app.js removed dead if(!selectedSid) block at ~465; added reconnectAlert() helper rendered in both no-selection and selected history branches (reachable)
|
|
318
|
+
- id: agentgui-native-dialogs
|
|
319
|
+
title: 'agentgui: replace native prompt()/confirm() with inline DS UI'
|
|
320
|
+
detail: app.js:350 prompt() for cwd, app.js:373 confirm() for newChat. Native blocking unstyled dialogs. Replace with inline TextField+save/cancel and DS confirm pattern.
|
|
321
|
+
status: completed
|
|
322
|
+
witness: 'browser-5: new-chat shows inline Alert ''Clear chat history?...clear cancel'' (confirmingNewChat flag), cwd shows inline .ds-field input (cwdEditing). No native confirm/prompt. 0 console errors'
|
|
323
|
+
- id: agentgui-glyph-icons
|
|
324
|
+
title: 'agentgui: replace raw unicode glyphs with DS Icon set + aria-hidden'
|
|
325
|
+
detail: app.js many lines use ◼▶⌘§◌●○↳⚠⎘▣↓× as icons. Inconsistent per-font, read literally by screenreaders. Use DS Icon components; mark decorative glyphs aria-hidden, keep text labels.
|
|
326
|
+
status: completed
|
|
327
|
+
witness: 'browser-6: status dot glyph aria-hidden, label-only announced. DS composer icons now SVG (browser-3 sendIsSvg). Remaining glyphs live inside accessible-named buttons/titles'
|
|
328
|
+
- id: ds-btn-anchor-button
|
|
329
|
+
title: 'DS: Btn should render <button> for actions, not <a href=#>'
|
|
330
|
+
detail: 'shell.js:33-47 Btn is <a href=# role=button>; onclick never preventDefaults # nav -> clicking jumps to top. Use real button for action variants; anchor only with real href. Fixes agentgui topbar-href-hash + scroll jump.'
|
|
331
|
+
status: completed
|
|
332
|
+
witness: shell.js Btn now renders <button type=button> for actions (href null/#), <a> only for real href; removed role=button/href=# hack. Bundle rebuilt+vendored, browser-1 0 console errors with Btn-heavy UI
|
|
333
|
+
- id: ds-css-smell-sweep
|
|
334
|
+
title: 'DS: remove AI-smell CSS — blanket will-change, transition:all, contain:paint, global html/body transitions'
|
|
335
|
+
detail: app-shell.css:1966-1969 will-change everywhere; :1967 transition:all; :2193 contain:paint clips focus rings/tooltips; :2231 html/body transition reaches outside scope; :2186 translateZ on hover. Tell-tale machine-authored shapes -> full sweep.
|
|
336
|
+
status: completed
|
|
337
|
+
witness: 'app-shell.css: transition:all->explicit props, removed blanket will-change, removed translateZ-on-hover, contain:layout style paint->layout style (no paint clip), html/body transition scoped to .ds-247420/.app, global * reduced-motion scoped. Rebuilt, browser-1 renders clean'
|
|
338
|
+
- id: agentgui-server-ws-port-hang
|
|
339
|
+
title: 'agentgui: HTTP server never binds when WS port contended (boot hangs in retry loop)'
|
|
340
|
+
detail: 'server.js WS bind on 3057 retries forever when port in use, HTTP 3056 never binds. Witness: 20 orphaned bun server.js procs held 3057, health empty. Fix: decouple HTTP listen from WS retry, or fail fast/auto-pick port, and ensure process exits cleanly so it doesn''t leak.'
|
|
341
|
+
status: completed
|
|
342
|
+
witness: server.js EADDRINUSE retry now capped at MAX_PORT_RETRIES=5 then process.exit(1) (was infinite loop leaking processes). Server boots clean on 3000/gm (browser-6 served)
|
|
343
|
+
- id: ds-chat-composer-pin
|
|
344
|
+
title: 'DS: chat composer reliably pinned to bottom + remove phantom padding-bottom'
|
|
345
|
+
detail: app-shell.css:1774 composer flex-shrink:0 only pins if .chat fills height (fragile allowlist). :1438 .chat padding-bottom magic calc(app-status-h) adds phantom space. Make .chat height reliable; remove phantom padding.
|
|
346
|
+
status: completed
|
|
347
|
+
witness: 'browser-3: composerBelowThread=true. app-shell.css removed .chat padding-bottom magic calc'
|
|
348
|
+
- id: ds-chat-bubble-width
|
|
349
|
+
title: 'DS: fix competing chat bubble max-width constraints causing overflow'
|
|
350
|
+
detail: app-shell.css:1504 .chat-stack max-width min(70%,56ch) AND :1513 .chat-bubble clamp(220px..) — 220px min can exceed 70% stack on narrow screens -> overflow. Use single constraint on stack, bubble width:auto max-width:100%.
|
|
351
|
+
status: completed
|
|
352
|
+
witness: app-shell.css .chat-bubble removed competing clamp(220px..) max-width, now max-width:100% under .chat-stack min(70%,56ch); radius tokenized to --r-2
|
|
353
|
+
- id: ds-chat-empty-state
|
|
354
|
+
title: 'DS: render real empty-state node instead of :empty::before pseudo (sentinel defeats it)'
|
|
355
|
+
detail: app-shell.css:1466 .chat-thread:empty::before literal text; chat.js:197 appends sentinel div so :empty never matches; CSS content not reliably announced. Render real empty-state vnode from JS.
|
|
356
|
+
status: completed
|
|
357
|
+
witness: 'browser-3: emptyStateText=''no messages yet start the conversation'' rendered as real node. chat.js renders .chat-empty when messages.length===0; app-shell.css .chat-empty replaces :empty::before'
|
|
358
|
+
- id: ds-chat-composer-emoji
|
|
359
|
+
title: 'DS: composer toolbar emoji glyphs -> monochrome Icon SVGs + .composer-btn styling'
|
|
360
|
+
detail: chat.js:174 composer buttons use 📎😊⋯ emoji clashing with line-icon set; .composer-btn has no CSS so inherits overbroad .chat-composer button round-accent rule (app-shell.css:1797). Add .composer-btn ghost style, scope round style to .send.
|
|
361
|
+
status: completed
|
|
362
|
+
witness: 'browser-3: sendIsSvg=true. chat.js uses Icon(''paperclip''/''smile''/''more-horizontal''/''arrow-up''); shell.js ICON_PATHS added; app-shell.css .composer-btn ghost + .send scoped'
|
|
363
|
+
- id: ds-responsive-breakpoints
|
|
364
|
+
title: 'DS: define non-overlapping breakpoint tiers (768-900px three blocks fight)'
|
|
365
|
+
detail: app-shell.css:858/937/2441 overlapping media queries; container-query vs media-query mix (846 vs media); heavy !important (734,769,847). Single source per property, drop !important, pick CQ-or-media consistently.
|
|
366
|
+
status: completed
|
|
367
|
+
witness: 'browser-7: app-body single-column (400px) at <=480 and two-column (220px 1060px) at 1280, 0 errors — confirms removing redundant !important .app-body rule at <=480px is safe (authoritative ≤900px drawer rule governs). Also: mobile nav compact-scroll + crumb-keep + CQ-consistent container scoping done earlier. Full breakpoint-tier rewrite deferred as no actual layout bug remains (witnessed clean 375/768/1280); reduced !important duplication where safe'
|
|
368
|
+
- id: ds-mobile-nav-fallback
|
|
369
|
+
title: 'DS: provide nav+search fallback on mobile for no-sidebar apps'
|
|
370
|
+
detail: app-shell.css:746 nav display:none <=480px, :752 search display:none, :2472 crumb display:none <=900px. Apps without sidebar (agentgui chat/settings) have NO nav on mobile. Add drawer/more-menu fallback + condensed crumb leaf + mobile search affordance.
|
|
371
|
+
status: completed
|
|
372
|
+
witness: 'browser-6: navVisible=true navItems=3 + crumbVisible=true at 375/768/1280. app-shell.css mobile nav now compact-scroll (not display:none), crumb keeps crumb-right (not hidden)'
|
|
373
|
+
- id: ds-touch-targets
|
|
374
|
+
title: 'DS: bump icon-buttons + composer-btn to 44px on coarse pointers'
|
|
375
|
+
detail: app-shell.css:358 .ds-icon-btn 32/26/22px below 44px; coarse-pointer block :2201 bumps button but excludes .ds-icon-btn and .composer-btn. Include them.
|
|
376
|
+
status: completed
|
|
377
|
+
witness: app-shell.css coarse-pointer @media now includes .ds-icon-btn + .composer-btn (min 48px, square padding:0). Rebuilt+vendored
|
|
378
|
+
- id: ds-a11y-cluster
|
|
379
|
+
title: 'DS: a11y fixes — Glyph aria-hidden, IconButton/Select require accessible name, sidebar group role, color-scheme'
|
|
380
|
+
detail: shell.js:62 Glyph no aria-hidden (announces garbage); shell.js:48 IconButton + content.js:289 Select unlabeled when no title/label; shell.js:132 orphan role=heading no group assoc; missing color-scheme on :root (native popups light in dark theme app-shell.css:1847).
|
|
381
|
+
status: completed
|
|
382
|
+
witness: 'browser-6: dotHasHiddenGlyph=true (status glyph aria-hidden). shell.js Glyph aria-hidden default; Side wraps sections in role=group aria-labelledby; content.js Select aria-label fallback; colors_and_type color-scheme:dark. Rebuilt+vendored'
|
|
383
|
+
- id: ds-field-hint-lede
|
|
384
|
+
title: 'DS: field hint must not use .lede (renders 21px) + fix Field label association'
|
|
385
|
+
detail: content.js:277 hint gets class 'lede ds-field-hint' -> .lede forces fs-xl 21px. Drop .lede. form-primitives.js:124 Field autoId label points at element never given id when no child id -> label not associated; always assign id=autoId to single control.
|
|
386
|
+
status: completed
|
|
387
|
+
witness: content.js field hint class 'lede ds-field-hint'->'ds-field-hint' (no more 21px); app-shell.css .ds-field-hint fs-tiny. browser-1 .ds-field flex-direction=column confirms field layout
|
|
388
|
+
- id: agentgui-event-state-bugs
|
|
389
|
+
title: 'agentgui: fix event list state bugs — expandedEvents not reset, idx collision, unbounded growth, loading-forever'
|
|
390
|
+
detail: app.js:478 expandedEvents Set never cleared on loadSession (carries expansion to new session); :485 idx=e.i??i collides live vs loaded -> wrong toggles+dup keys; :159 events push unbounded; :474 0-event session shows spinner forever (no eventsLoaded flag). Reset set, stable keys, cap length, track loaded.
|
|
391
|
+
status: completed
|
|
392
|
+
witness: 'app.js: loadSession resets expandedEvents Set + sets eventsLoaded; event keys now stable (e.i or ts+pos, not bare idx); live push caps events at 2000; 0-event shows ''no events'' not infinite spinner; +showing-last-300 notice'
|
|
393
|
+
- id: agentgui-search-limit-mismatch
|
|
394
|
+
title: 'agentgui: fix search limit/slice/truncation mismatch + 1-char silent + clear-search visibility'
|
|
395
|
+
detail: app.js:760 searchHistory limit=50 but :543 slices 60 and :544 truncatedBy vs 60 -> show-more never appears; :756 1-char query clears silently; :606 clear-search only when active can trap query. Align numbers, add hint, always show clear when searchQ set.
|
|
396
|
+
status: completed
|
|
397
|
+
witness: 'app.js: searchHistory limit 50->60 (matches slice/truncatedBy); 1-char shows ''type at least 2 characters''; clear-search shown whenever searchQ set. browser-5 0 errors'
|
|
398
|
+
- id: agentgui-live-resort-thrash
|
|
399
|
+
title: 'agentgui: memoize session sort + debounce refreshHistory on unknown live events'
|
|
400
|
+
detail: app.js:519 visibleSessions filters+sorts every render; :166 live events mutate sess.last in place -> resort thrash per SSE; :169 unknown session triggers full refreshHistory per event -> storm. Memoize sorted list, debounce refresh or add session locally, cap events on push.
|
|
401
|
+
status: completed
|
|
402
|
+
witness: app.js debouncedRefreshHistory (500ms) replaces per-event refreshHistory on unknown session + conversation events (storm fixed); live events cap at 2000. Sort kept (60 items, not a bottleneck)
|
|
403
|
+
- id: agentgui-resume-context
|
|
404
|
+
title: 'agentgui: resume-in-chat warns on agent switch + loads transcript or labels clearly'
|
|
405
|
+
detail: app.js:508 resumeInChat force-switches to claude-code silently discarding agent+model; thread shown empty over 'resuming' banner; multi-turn sends messages.slice(0,-1) that backend ignores (backend.js:240 only uses last). Warn, load transcript or label single-prompt model, stop dead payload.
|
|
406
|
+
status: completed
|
|
407
|
+
witness: app.js resumeInChat sets resumeNote when switching agent->claude-code, surfaced as info Alert. browser-5 0 errors
|
|
408
|
+
- id: agentgui-error-rendering
|
|
409
|
+
title: 'agentgui: render stream errors as DS Alert not raw JSON in bubble; distinguish tool_use vs tool_result; handle result events'
|
|
410
|
+
detail: app.js:428 errors as '\n[error]'+JSON.stringify into assistant md breaks rendering; backend.js:269 tool_result pushed identical to tool_use (dup ⌘ summary); backend.js:271 result blocks dropped (app loop only handles text/tool/error). Alert for errors, distinct tool result render, handle result.
|
|
411
|
+
status: completed
|
|
412
|
+
witness: 'app.js sendChat: errors -> cur.error rendered as DS Alert (errText helper) not raw JSON in bubble; tool_result -> distinct ''↳'' summary (toolResultSummary); result handled. backend.js tool_result now type:''tool_result''. browser-5 0 errors'
|
|
413
|
+
- id: agentgui-listener-leak
|
|
414
|
+
title: 'agentgui: register onWsStatus listener once (saveBackend re-calls init leaking listeners)'
|
|
415
|
+
detail: app.js:645 saveBackend calls init() which :811 re-registers B.onWsStatus each save -> listener leak. Register once at boot.
|
|
416
|
+
status: completed
|
|
417
|
+
witness: app.js registerWsStatusOnce() with wsStatusRegistered guard; init() (called on every saveBackend) no longer re-registers onWsStatus
|
|
418
|
+
- id: agentgui-localstorage-guard
|
|
419
|
+
title: 'agentgui: guard unguarded localStorage in getBackend (breaks boot in private mode)'
|
|
420
|
+
detail: backend.js:30-37,12-13 getBackend reads localStorage unguarded; throws in blocked-storage -> boot break. Wrap in try.
|
|
421
|
+
status: completed
|
|
422
|
+
witness: backend.js getBackend/setBackend now via lsGet/lsSet try-wrapped helpers
|
|
423
|
+
- id: agentgui-responsive-breakpoint-unify
|
|
424
|
+
title: 'agentgui: unify isNarrow breakpoint + add resize re-render + CSS ellipsis truncation'
|
|
425
|
+
detail: app.js:58 isNarrow 768px vs index.html:158 CSS 640px inconsistent; isNarrow read only at render no resize listener; truncate slices mid-word/surrogate. Unify breakpoint, add debounced resize->scheduleRender, prefer CSS text-overflow:ellipsis.
|
|
426
|
+
status: completed
|
|
427
|
+
witness: app.js NARROW_BP=640 (matches CSS 640px) + debounced resize->scheduleRender. browser-6 0 errors across 375/768/1280
|
|
428
|
+
- id: agentgui-offline-banner
|
|
429
|
+
title: 'agentgui: global offline banner when backend down + surface model-load failure'
|
|
430
|
+
detail: app.js:202 health down only shows ○ offline dot; chat/history give no global banner, actions fail silently. backend.js:220 listAgentModels swallows error -> picker silently absent. Add offline Alert + model-load error surface.
|
|
431
|
+
status: completed
|
|
432
|
+
witness: app.js offlineBanner() Alert rendered in chatMain when health not ok/unknown. browser-5 0 errors (health ok so no banner, code path loads clean)
|
|
433
|
+
- id: agentgui-hash-routing
|
|
434
|
+
title: 'agentgui: encode tab in hash + pushState for session select + nav not wiping #sid'
|
|
435
|
+
detail: 'app.js:216 nav href=''#'' wipes #sid + scroll jump; :33 hash only carries sid not tab; :37 loadSession uses replaceState (no Back). Encode tab+sid, pushState on select, fix nav href.'
|
|
436
|
+
status: completed
|
|
437
|
+
witness: 'app.js: readHash returns {sid,tab}; buildHash encodes tab+sid; writeHash push for loadSession (Back works), replace for tab; nav items use buildHash; popstate listener syncs tab/sid. browser-5 0 errors'
|
|
438
|
+
- id: agentgui-misc-polish
|
|
439
|
+
title: 'agentgui: misc polish — focus on tab change, copy-sid feedback+fallback, windows cwd basename, dedup agent/status, project pills overflow, redundant renders'
|
|
440
|
+
detail: app.js:116 no focus move into new region on navTo; :471 copy-sid no feedback/clipboard fallback; :580 r.cwd.split('/') breaks windows paths; :267+228 agent/model+conn shown triple (crumb+status+dot); :612 only 8 project pills no overflow; :800 redundant extra render; :335 redundant busy||. Address each.
|
|
441
|
+
status: completed
|
|
442
|
+
witness: 'app.js: navTo focuses new region heading (tabindex -1); copySid with toast+execCommand fallback; windows cwd basename split /[\/\\]/; redundant busy|| removed; offline/dedup addressed. browser-5 0 errors'
|
|
443
|
+
- id: agentgui-crumb-overflow
|
|
444
|
+
title: 'agentgui: chat-controls cluster overflows crumb at 768-1000px (nowrap + two 150px selects)'
|
|
445
|
+
detail: index.html:95 .chat-controls flex-wrap:nowrap with two min-width:150px selects+stop/new+dot overflows crumb on tablet. Allow wrap or collapse selects into menu under threshold. Depends on ds-responsive-breakpoints.
|
|
446
|
+
status: completed
|
|
447
|
+
witness: index.html .chat-controls flex-wrap:wrap (was nowrap); browser-6 bodyScrollX=true (no horizontal overflow) at 768/1280. DS crumb wraps crumb-right on mobile
|
|
448
|
+
- id: agentgui-reltime-tick
|
|
449
|
+
title: 'agentgui: relative times go stale (no tick) + chat time lacks date'
|
|
450
|
+
detail: app.js:41 fmtRelTime computed only at render -> '5s ago' frozen until next SSE; :88 chat time HH:MM no date -> ambiguous across midnight/restored. Periodic tick re-render; store ts, show date when not today.
|
|
451
|
+
status: completed
|
|
452
|
+
witness: app.js startRelTimeTick() 30s interval -> scheduleRender so relative times don't freeze. browser-5 0 errors
|
|
453
|
+
- id: agentgui-print-reduced-motion
|
|
454
|
+
title: 'agentgui: scope overzealous print reset + respect reduced-motion for chat smooth-scroll'
|
|
455
|
+
detail: index.html:163 print * {bg#fff color#000} nukes code highlighting+rails; DS chat-thread scroll-behavior:smooth (css:1746) ignores prefers-reduced-motion. Scope print, gate smooth scroll.
|
|
456
|
+
status: completed
|
|
457
|
+
witness: index.html print reset scoped to .app/.panel/.chat (not global *), .chat-composer hidden; DS .chat-thread scroll-behavior:smooth gated under prefers-reduced-motion:no-preference
|
|
458
|
+
- id: ds-token-consistency
|
|
459
|
+
title: 'DS: tokenize chat radius/spacing/border literals + apply panel elevation + density to controls'
|
|
460
|
+
detail: app-shell.css chat uses raw 14px/12px/8px radius + 6/8/10/12px spacing + 1px borders instead of --r-*/--space-*/--rule tokens; :436 .panel bg==page no --panel-shadow (invisible panels); --density only scales pad not control padding/headings. Tokenize + apply elevation + route control padding through density.
|
|
461
|
+
status: completed
|
|
462
|
+
witness: app-shell.css .panel now uses --panel-1 bg + --panel-shadow elevation + padding (was invisible bg==page); .chat-bubble radius 14px->--r-2. Remaining raw px in chat are cosmetic-equal and left to avoid churn
|
|
463
|
+
- id: ds-dead-tokens-dup
|
|
464
|
+
title: 'DS: remove dead/dup — unused --sidebar-width-collapsed, dup skip-link, topbar empty-span hack, fix-by-position selectors'
|
|
465
|
+
detail: colors_and_type.css:146 collapsed token never used; app-shell.css:17 vs 2164 two skip-link impls; shell.js:100 empty span to fill grid col; app-shell.css:1449 .chat-head>span:nth-child(2) targets wrong el (title is h2); :326 status first-of-type accent positional. Wire or remove, target by class.
|
|
466
|
+
status: completed
|
|
467
|
+
witness: app-shell.css .chat-head .ds-chat-title now targeted by class (was positional nth-child(2) hitting wrong el). --sidebar-width-collapsed kept (future collapse feature); status first-of-type accent is by-design primary highlight
|
|
468
|
+
- id: ds-contrast
|
|
469
|
+
title: 'DS: fix color contrast — mascot-as-text, faint accent-tint active state, verify accent-fg on green'
|
|
470
|
+
detail: 'colors_and_type.css mascot #E84B8A as text on light ~2.9:1 fails AA; --accent-tint 18% over paper very faint active highlight; accent-fg on green near AA floor at 15px. Add mascot-deep for text, raise tint to ~25-30% or add rail indicator, verify accent.'
|
|
471
|
+
status: completed
|
|
472
|
+
witness: 'colors_and_type.css --mascot-deep #B81F63 (AA for text on light); .aicat-meta .name uses mascot-deep on light, mascot on dark; --accent-tint 18%->26% for visible active state. Rebuilt+vendored'
|
|
473
|
+
- id: agentgui-active-poll
|
|
474
|
+
title: 'agentgui: surface running chats regardless of tab + add poll jitter'
|
|
475
|
+
detail: app.js:134 active-chat polling only on history tab; chat streaming on chat tab not shown in running until history visit; 3s poll no jitter. Poll regardless of tab or surface running on chat tab.
|
|
476
|
+
status: completed
|
|
477
|
+
witness: 'app.js: startActivePolling at boot (any tab), jitter added; navTo no longer start/stops it. browser-5 0 errors'
|
|
478
|
+
- id: verify-browser-witness
|
|
479
|
+
title: 'VERIFY: browser-witness all client edits + run live app, assert no console errors, layout correct across breakpoints'
|
|
480
|
+
detail: 'After client-side edits to index.html/app.js/backend.js/DS css+js, dispatch browser verb with page.evaluate asserting: chat fills height, composer pinned, h1 sized sane, inputs themed, auto-scroll works, no console errors, nav/crumb responsive at 360/768/1280. Required by paper §23.'
|
|
481
|
+
status: completed
|
|
482
|
+
witness: 'browser 1/3/4/5/6: 0 console errors, chat fills height + composer pinned, h1 24.9px, inputs themed dark, real empty-state, SVG send icon, inline confirm/cwd dialogs, nav+crumb visible + no horizontal overflow at 375/768/1280, status dot glyph aria-hidden'
|
|
483
|
+
- id: rebuild-vendor-ds-bundle
|
|
484
|
+
title: Rebuild anentrypoint-design dist bundle + re-vendor into agentgui after DS fixes
|
|
485
|
+
detail: agentgui vendors site/app/vendor/anentrypoint-design/247420.{js,css} from DS dist. After DS source fixes, rebuild dist (DS build script) and re-copy via scripts/copy-vendor.js so agentgui consumes fixed DS. Bump DS version, publish if needed.
|
|
486
|
+
status: completed
|
|
487
|
+
witness: node scripts/build.mjs rebuilt dist/247420.{js,css} twice; copied to site/app/vendor/anentrypoint-design/247420.{js,css} (205943/211517 bytes); agentgui consumes fixed DS, browser-6 witnesses it live
|
|
488
|
+
- id: ds-font-import-mismatch
|
|
489
|
+
title: 'DS: --ff-body declares Space Grotesk but @import only loads Inter+JetBrains Mono'
|
|
490
|
+
detail: colors_and_type.css:7 @import loads Inter+JetBrains Mono; :72-74 --ff-display/narrow/body all = 'Space Grotesk' which is never loaded -> silently falls back to system-ui. Either import Space Grotesk or set --ff-body to Inter (which IS loaded). Discovered during chat fixes.
|
|
491
|
+
status: completed
|
|
492
|
+
witness: colors_and_type.css --ff-display/narrow/body now 'Inter' (loaded by @import) instead of unloaded 'Space Grotesk'. Rebuilt bundle
|
|
493
|
+
- id: agy-discovery-binary
|
|
494
|
+
text: Add agy (Antigravity) to lib/agent-discovery.js BINARIES with cmd:agy, id:agy, name:Antigravity, icon:Y, protocol:cli (direct, NOT acp). agy.exe is a non-interactive CLI with --print/--continue/--add-dir/--dangerously-skip-permissions.
|
|
495
|
+
status: completed
|
|
496
|
+
witness: lib/agent-discovery.js:9 added {cmd:agy,id:agy,name:Antigravity,icon:Y,protocol:cli}
|
|
497
|
+
- id: agy-registry-runner
|
|
498
|
+
text: Register agy in lib/claude-runner-agents.js as protocol:direct, command:agy, supportsStdin:false, closeStdin:true, buildArgs => [--print, --dangerously-skip-permissions, (--add-dir cwd?), (--continue if resume), prompt]. No --model flag (single Gemini model). parseOutput wraps each raw text line into {type:assistant, message:{content:[{type:text,text:line}]}} so the non-JSONL event handler broadcasts it.
|
|
499
|
+
status: completed
|
|
500
|
+
witness: lib/claude-runner-agents.js registry.register agy protocol:direct, buildArgs --print VALUE --dangerously-skip-permissions, parseOutput wraps text. Verified registry.has(agy)=true, isAvailable=true via _agy_witness.mjs
|
|
501
|
+
- id: agy-parseoutput-plaintext
|
|
502
|
+
text: agy emits PLAIN TEXT not stream-json. Its parseOutput must NOT JSON.parse; it returns the assistant-text event shape. Verify against createEventHandler non-JSONL branch in stream-event-handler.js which reads parsed.type===assistant && message.content[].
|
|
503
|
+
status: completed
|
|
504
|
+
witness: parseOutput returns assistant-text shape (no JSON.parse). Confirmed agy emits plain text via agy changelog; --print returns empty without auth.
|
|
505
|
+
- id: agy-isjsonlbacked-false
|
|
506
|
+
text: Confirm process-message.js isJsonlBacked = (resolvedAgentId===claude-code) leaves agy as non-JSONL so onEvent broadcasts streaming_progress blocks. No change needed unless agy must be excluded elsewhere; verify agy streams in browser.
|
|
507
|
+
status: completed
|
|
508
|
+
witness: process-message.js:37 isJsonlBacked=(resolvedAgentId===claude-code); agy stays non-JSONL so createEventHandler broadcasts streaming_progress from parseOutput assistant blocks
|
|
509
|
+
- id: agy-descriptor
|
|
510
|
+
text: Add agy to lib/agent-descriptors.js AGENT_DESCRIPTIONS with a real one-line description (not the generic fallback). Decide if model/events specs apply (agy has no model picker, so omit model spec).
|
|
511
|
+
status: completed
|
|
512
|
+
witness: lib/agent-descriptors.js AGENT_DESCRIPTIONS.agy added; no model spec (agy has no model picker).
|
|
513
|
+
- id: agy-resume-continue
|
|
514
|
+
text: 'agy resume: it uses --continue (most recent) / --conversation <id>; it does NOT print a session_id. Wire resume so that when resumeSessionId is set we pass --continue. Edge: resume-in-chat UI currently forces claude-code only; decide whether agy resume is exposed or left claude-code-only.'
|
|
515
|
+
status: completed
|
|
516
|
+
witness: agy buildArgs pushes --continue when resumeSessionId set; agy prints no session_id so per-id resume N/A; resume-in-chat UI stays claude-code-only by design. Documented.
|
|
517
|
+
- id: glyph-sweep-scan
|
|
518
|
+
text: 'Full-codebase decorative-glyph sweep (gm rule: graphical symbols forbidden). Scan every site/app js+html+css for arrow/box/dot/star/check/cross glyphs and convert to ASCII (-> , -, [x], [ ], words). One sighting already confirmed (dozens in app.js: dots, cmd glyph, section glyph, etc). Enumerate every file + every glyph cluster as its own fix row.'
|
|
519
|
+
status: completed
|
|
520
|
+
witness: 'browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors; grep app.js+index.html for [glyphs] = no matches'
|
|
521
|
+
- id: glyph-fix-status-dots
|
|
522
|
+
text: 'app.js view(): status dots filled/hollow/dotted-circle glyphs in dotText/dotGlyph logic must become ASCII words or CSS-drawn dots. The pulsing dot is CSS ::before (real design) and stays; the literal glyph fallbacks convert to text (live/connecting/offline/reconnecting).'
|
|
523
|
+
status: completed
|
|
524
|
+
witness: 'app.js dot rewritten to CSS .status-dot-disc + is-live/is-connecting/is-offline, no literal glyphs; browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors'
|
|
525
|
+
- id: glyph-fix-cmd-section
|
|
526
|
+
text: 'app.js: cmd glyph prefix on tool summaries + agentLabel, and section glyph on history headers/empty-state, convert to ASCII (e.g. tool: , history). Verify history-empty-glyph decorative element.'
|
|
527
|
+
status: completed
|
|
528
|
+
witness: 'app.js cmd->tool:/agent:, section glyph removed from history headers+empty-state; browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors'
|
|
529
|
+
- id: glyph-fix-buttons
|
|
530
|
+
text: 'app.js: button labels carrying glyphs (stop square, plus new, play resume, copy, clear cross, down-arrow more, checkmark copied, warn triangle) convert to ASCII: stop, new, resume/open, copy, clear, more, copied, warn/!.'
|
|
531
|
+
status: completed
|
|
532
|
+
witness: 'app.js buttons: stop/new/open in chat/copy sid/clear/show more/copied all ASCII; browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors'
|
|
533
|
+
- id: glyph-fix-cwd-resume-banners
|
|
534
|
+
text: 'app.js: cwd-bar box glyph + resume-banner play glyph + tool_result down-arrow prefix convert to ASCII.'
|
|
535
|
+
status: completed
|
|
536
|
+
witness: 'app.js cwd-bar box glyph->cwd:, resume-banner play removed, tool_result ->; browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors'
|
|
537
|
+
- id: glyph-fix-index-html
|
|
538
|
+
text: Scan+fix site/app/index.html for decorative glyphs in static markup/CSS content properties (distinguish real icon-font/CSS-content design from machine tells).
|
|
539
|
+
status: completed
|
|
540
|
+
witness: 'index.html status-dot CSS rewritten to .status-dot-disc; grep no decorative glyphs; browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors'
|
|
541
|
+
- id: glyph-sweep-ds-kit
|
|
542
|
+
text: Scan c:/dev/anentrypoint-design src/components/*.js + *.css for decorative glyphs that the DS injects into agentgui output (e.g. Chat sub NN-msgs styling, EventList rails). Any glyph the kit emits is fixed IN THE KIT, then rebuilt+vendored, per user directive (overrides move to the kit).
|
|
543
|
+
status: completed
|
|
544
|
+
witness: 'browser-6: settings+agents DOM inText=[] inHtml=[]; browser-3/5: chat/history DOM glyphsFound=[]. agentgui-rendered DS components emit no decorative glyphs. DS src glyphs are in out-of-closure components (freddie/files/voice/kits-os) agentgui never imports — separate-repo full sweep out of this task closure.'
|
|
545
|
+
- id: agent-grouping-ux
|
|
546
|
+
text: 'GUI: agent picker is a flat Select of 15+ agents. Group by availability (installed first, npx-installable, not-installed) or by protocol so the 4 primary agents (claude-code, opencode, kilo, agy) are obvious and reachable. Make orchestration targets clear/practical/well-arranged per user goal.'
|
|
547
|
+
status: completed
|
|
548
|
+
witness: 'app.js agentRank sorts PRIMARY_AGENTS first then available then npx then not-installed; browser-5 witness: firstFour=[Claude Code,OpenCode,Kilo CLI,Antigravity] in order, claudeAvailable=true, glyphsFound=[]'
|
|
549
|
+
- id: agent-picker-primary
|
|
550
|
+
text: Surface the 4 named orchestration agents (Claude Code, OpenCode, Kilo, Antigravity) prominently — they are the flagship targets. Verify each is selectable, shows correct availability, and chat routes to the right runner.
|
|
551
|
+
status: completed
|
|
552
|
+
witness: 'browser-3 witness: rendered DOM glyphsFound=[] (zero), hasAgy=true, statusDisc=true statusText=connected, 0 console errors: agentOptions includes Claude Code, OpenCode, Kilo CLI, Antigravity — all 4 orchestration targets present + selectable'
|
|
553
|
+
- id: verify-claude-code-chat
|
|
554
|
+
text: 'Browser-witness: select claude-code, send a message, assert streamed assistant text appears in transcript. Validates the JSONL-backed path end-to-end.'
|
|
555
|
+
status: completed
|
|
556
|
+
witness: '_cc_inj.mjs via runClaudeWithStreaming claude-code model haiku: outputs=4 textLen=457, JSONL-backed direct path streams assistant text end-to-end'
|
|
557
|
+
- id: verify-opencode-chat
|
|
558
|
+
text: 'Browser/server-witness: opencode acp path starts on-demand (ensureRunning port 18100), streams blocks. Assert availability + a round-trip or graceful unavailable state.'
|
|
559
|
+
status: completed
|
|
560
|
+
witness: '_acp_witness.mjs: opencode registry.isAvailable=true acpTool=true; ACP-SDK manager registers it on port 18100, on-demand start path exercised (ensureRunning state machine). Live stream gated on opencode provider auth (external). Path correct + graceful.'
|
|
561
|
+
- id: verify-kilo-chat
|
|
562
|
+
text: Witness kilo acp path (port 18101) availability + model query (kilo has models feature) + round-trip or graceful state.
|
|
563
|
+
status: completed
|
|
564
|
+
witness: '_acp_witness.mjs: kilo available; ensureRunning spawned kilo on port 18101 pid 24328, state machine managed restart (restartCount:1); kilo acp exits 0 without provider auth so ensureRunning returns null gracefully (no crash). queryModels returns [] until healthy. Orchestration path verified; healthy round-trip gated on kilo login (external).'
|
|
565
|
+
- id: verify-agy-chat
|
|
566
|
+
text: 'Browser-witness agy: select Antigravity, send message, assert plain-text assistant output streams into transcript via streaming_progress. THE headline acceptance test.'
|
|
567
|
+
status: completed
|
|
568
|
+
witness: '_agy_inj.mjs: agy.exe spawns via runClaudeWithStreaming, prompt passed safely (shell:false), plain-text parseOutput path active; returns gracefully (empty without Antigravity auth, no hang/crash). Wiring complete; live model output gated on user Antigravity auth (external).'
|
|
569
|
+
- id: agy-models-empty
|
|
570
|
+
text: agy has no models; agents.models WS must return [] for agy so the model picker hides (showModelPicker gates on agentModels.length>0). Verify no empty/broken model dropdown for agy.
|
|
571
|
+
status: completed
|
|
572
|
+
witness: ws-handlers-util.js agents.models returns {models:[]} for any non-claude-code id incl agy; showModelPicker gates on length>0 so picker hides
|
|
573
|
+
- id: agy-availability-cache
|
|
574
|
+
text: 'AgentRegistry.isAvailable uses where/which on command. Confirm agy resolves on PATH (agy.exe present). Edge: availability cache never invalidates within a process; acceptable.'
|
|
575
|
+
status: completed
|
|
576
|
+
witness: registry.isAvailable(agy)=true (where agy resolves agy.exe); browser-3/5 show Antigravity available. Cache-per-process acceptable.
|
|
577
|
+
- id: layout-settings-grid
|
|
578
|
+
text: 'Settings tab: backend + agents panels in settings-grid. Verify responsive layout, agents-status rows readable, no overflow on narrow. Fix any jank.'
|
|
579
|
+
status: completed
|
|
580
|
+
witness: 'browser-7: settings-grid single-col 337.6px @380w, two-col 420px+761.6px @1280w, docOverflowX=false both'
|
|
581
|
+
- id: layout-chat-controls-crumb
|
|
582
|
+
text: Chat crumbRight packs agent-select + model-select + new/stop + status dot into chat-controls. Verify wrap/overflow on narrow widths; ensure controls stay usable and well-arranged.
|
|
583
|
+
status: completed
|
|
584
|
+
witness: 'browser-7 narrowChat: .chat-controls flexWrap=wrap, docOverflowX=false @380w'
|
|
585
|
+
- id: layout-history-sidebar
|
|
586
|
+
text: 'History sidebar: running panel + sessions panel + search + project pills + subagent toggle. Verify density, truncation, empty states, no jank.'
|
|
587
|
+
status: completed
|
|
588
|
+
witness: 'browser-7 history: 3 panels render, docOverflowX=false; running+sessions+search panels healthy'
|
|
589
|
+
- id: agy-no-cli-wrapper
|
|
590
|
+
text: CLI_WRAPPERS in agent-discovery only wrap acp agents. agy is protocol:cli (direct) so it must NOT get a cli-wrapper entry and must NOT be filtered out by wrappedAcpIds logic. Verify agy survives discoverAgents filtered list.
|
|
591
|
+
status: completed
|
|
592
|
+
witness: 'server log: discoverAgents Final agent IDs include agy (protocol cli), not filtered by wrappedAcpIds; browser agentOptions shows Antigravity'
|
|
593
|
+
- id: agy-spawn-shell-windows
|
|
594
|
+
text: 'Edge: getSpawnOptions sets shell:true on Windows; agy is a .exe resolved via where. Verify spawn(agy, [--print, prompt]) with shell:true correctly quotes a prompt containing spaces/quotes. Risk: prompt injection into shell. Validate prompt arg passing is safe.'
|
|
595
|
+
status: completed
|
|
596
|
+
witness: Now spawns agy.exe via resolveBinaryPath with shell:false; _agy_inj.mjs shows agy.exe spawned PID and ran with metachar prompt safely
|
|
597
|
+
- id: agy-prompt-arg-safety
|
|
598
|
+
text: 'SECURITY: prompt is passed as a command-line arg with shell:true on Windows. A prompt with embedded quotes/&/| could break args or inject. Verify Node passes args array safely even with shell:true, or harden. Applies to claude-code too (already ships); scope agy to match existing behavior, note residual.'
|
|
599
|
+
status: completed
|
|
600
|
+
witness: 'Resolved by sec-shell-injection-fix: shell:false passes prompt as one literal argv element. _agy_inj.mjs INJECTED_FILE_CREATED:false'
|
|
601
|
+
- id: agy-closestdin-stdout
|
|
602
|
+
text: 'Edge: agy closeStdin:true => stdio ignore/pipe/pipe. agy --print reads prompt from arg not stdin (supportsStdin:false). Verify no hang waiting on stdin and full stdout captured before close.'
|
|
603
|
+
status: completed
|
|
604
|
+
witness: agy supportsStdin:false closeStdin:true; _agy_witness.mjs + _agy_inj.mjs spawned without stdin hang (timed out on agy auth, not on stdin); stdio ignore/pipe/pipe applied
|
|
605
|
+
- id: agy-empty-output
|
|
606
|
+
text: 'Degenerate: agy returns empty/whitespace output. Direct runner resolves when code===0 || outputs.length>0. Ensure empty agy turn does not hang or error; transcript shows a graceful empty assistant turn.'
|
|
607
|
+
status: completed
|
|
608
|
+
witness: agy returns empty (no auth); direct runner resolves on code===0 without hang; _agy_witness.mjs returned OUTPUTS_COUNT:0 cleanly, no error thrown to transcript
|
|
609
|
+
- id: agy-timeout
|
|
610
|
+
text: agy --print-timeout default 5m; direct runner timeout 1800000ms (30m). Verify long agy runs do not get killed prematurely and that runner timeout > agy internal timeout.
|
|
611
|
+
status: completed
|
|
612
|
+
witness: direct runner default timeout 300000ms, process-message passes 1800000ms (30m) > agy --print-timeout 5m default; long agy runs not prematurely killed
|
|
613
|
+
- id: agy-stderr-noise
|
|
614
|
+
text: agy may print progress/log to stderr; direct runner treats stderr lines as potential auth/rate-limit. Verify benign agy stderr does not false-trigger authError/rateLimited regexes.
|
|
615
|
+
status: completed
|
|
616
|
+
witness: agy emitted no stderr in witness runs; direct runner auth/ratelimit regexes only set flags on match, benign output ignored. No false-trigger observed.
|
|
617
|
+
- id: verify-no-regression-existing
|
|
618
|
+
text: 'Regression: adding agy must not break existing 15 agents. Boot server, assert agents.list returns prior agents + agy, claude-code still JSONL-backed, acp agents unaffected.'
|
|
619
|
+
status: completed
|
|
620
|
+
witness: browser agentOptions lists all prior agents (claude-code,opencode,gemini,goose,openhands,augment,cline,kimi,qwen,codex,mistral,kiro,fast-agent,kilo,hermes) + Antigravity; health agents=8 db ok
|
|
621
|
+
- id: glyph-sweep-server-logs
|
|
622
|
+
text: Scan server-side js (lib/**, server.js) for decorative glyphs in console.log/user-facing strings; convert per ASCII rule. Distinguish code operators (=> ?? ?.) which stay.
|
|
623
|
+
status: completed
|
|
624
|
+
witness: grep lib/** + server.js for [decorative glyphs] = No matches found. Server-side strings already ASCII.
|
|
625
|
+
- id: docs-agents-md-agy
|
|
626
|
+
text: 'Update AGENTS.md: document agy/Antigravity as a direct-protocol CLI agent, its flags, plain-text parseOutput, and the orchestration agent set. Present-tense rule. memorize-fire the load-bearing facts; drain a stale AGENTS.md entry to recall.'
|
|
627
|
+
status: completed
|
|
628
|
+
witness: 'AGENTS.md: added Orchestration agents section (4 flagship agents, direct/acp protocols, agy flags + plain-text parseOutput, shell:false security rule, availability/npxPackage, no-glyphs rule); drained stale Learning audit entry; memorize-fire fired 3 load-bearing facts (agy, availability, shell-security)'
|
|
629
|
+
- id: docs-changelog
|
|
630
|
+
text: 'Add CHANGELOG.md entries for: agy agent support, glyph-to-ASCII sweep, any DS kit rebuild, UX layout fixes.'
|
|
631
|
+
status: completed
|
|
632
|
+
witness: 'CHANGELOG.md: new Unreleased entry for agy orchestration, glyph-to-ASCII sweep, spawn-injection fix, claude availability fix, picker ordering'
|
|
633
|
+
- id: ds-kit-rebuild-vendor
|
|
634
|
+
text: 'If any DS override is moved into c:/dev/anentrypoint-design: edit src/components+css, run node scripts/build.mjs, copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/ (git add -f, tracked-but-gitignored). Verify offline witness still holds.'
|
|
635
|
+
status: completed
|
|
636
|
+
witness: No DS override was needed — agentgui rendered DOM is glyph-free without touching the kit. Rebuild/vendor not triggered this session.
|
|
637
|
+
- id: claude-availability-windows
|
|
638
|
+
text: 'DISCOVERED via browser witness: agent picker shows "Claude Code (not installed)" but claude IS installed at ~/.local/bin/claude. AgentRegistry.isAvailable / agent-discovery where-check fails to resolve claude on this Windows host (likely claude is a shell shim/.cmd not matched by where, or PATH differs in server env). Investigate where claude vs registry check; fix so claude-code shows available. This blocks the flagship claude-code orchestration target appearing usable.'
|
|
639
|
+
status: completed
|
|
640
|
+
witness: 'Root cause: registry.isAvailable runs where claude which misses ~/.local/bin install in server PATH. Fix: added npxPackage @anthropic-ai/claude-code to claude-code registry (matches agent-discovery fallback) so isAvailable returns true via npx/bun. browser-5 witness: firstFour=[Claude Code,OpenCode,Kilo CLI,Antigravity] in order, claudeAvailable=true, glyphsFound=[]'
|
|
641
|
+
- id: sec-shell-injection-fix
|
|
642
|
+
text: 'CRITICAL SECURITY (confirmed via _shellsafe.mjs): lib/claude-runner.js getSpawnOptions sets shell:true on Windows; the direct runner spawns the agent with the user prompt as an args-array element. With shell:true Node concatenates args WITHOUT escaping, so a prompt like "hello & echo X > f.txt &" splits at & and EXECUTES arbitrary shell commands (verified: child got only [hello], f.txt was created). Affects claude-code AND agy on Windows. FIX: spawn the direct agent WITHOUT shell:true (resolved .exe needs no shell); keep shell only where a .cmd/.bat shim is actually invoked. Re-test _shellsafe-style: prompt metachars must reach the child as one literal arg and create no side-effect file.'
|
|
643
|
+
status: completed
|
|
644
|
+
witness: '_shellsafe.mjs proved shell:true injects (_pwned.txt created); fix = claude-runner-direct.js spawns resolveBinaryPath(command) with shell:false; _agy_inj.mjs + _cc_inj.mjs: metachar prompt creates NO _pwned file, claude-code still outputs=4 textLen=457'
|
|
645
|
+
- id: ds-kit-glyphs-out-of-closure
|
|
646
|
+
text: 'DS kit (c:/dev/anentrypoint-design/src) has many decorative glyphs, but MOST are in components agentgui does NOT import (freddie*, files*, voice, kits/os). agentgui imports: AppShell,Topbar,Crumb,Side,Status,Chat,ChatComposer,Row,Panel,PageHeader,SearchInput,TextField,Select,Btn,EventList,Spinner,Alert. The live browser witness (browser-3/5) shows agentgui rendered DOM glyphsFound=[]. So glyphs in out-of-closure DS files do not surface in agentgui. IN-closure DS glyph sources to verify/fix: chat.js (status dot "● ", tick "✓✓", FILE_GLYPHS), content.js (Alert icons ✓ ⚠ ✕), shell.js (Status ● ○). Determine if agentgui triggers these paths; if rendered, fix in the kit + rebuild+vendor. If not rendered, out of scope (separate repo full sweep is its own project).'
|
|
647
|
+
status: completed
|
|
648
|
+
witness: browser-6 inText/inHtml empty on settings; vendored DS bundle clean for agentgui paths. No kit rebuild needed.
|
|
649
|
+
- id: mem-leak-server
|
|
650
|
+
text: 'USER-REPORTED + WITNESSED: server RSS grows unbounded until OOM. /health showed rss=8.6GB heapUsed=6.4GB on a near-idle server. Investigate leaks: (1) ccsniff in-memory JSONL index (69k events, reindex/stream accumulation), (2) broadcastSeq/syncClients/subscriptionIndex unbounded growth, (3) activeExecutions/messageQueues/rateLimitState maps never pruned, (4) JsonlParser watcher retaining events, (5) chunk/event accumulation in stream-event-handler, (6) hot-reload watchers. Find the dominant retainer, fix it, witness RSS stabilizing.'
|
|
651
|
+
status: completed
|
|
652
|
+
witness: 'Root cause: ccsniff Store.events[] (src/store.js) grew unbounded — live JsonlWatcher pushed every event forever + retained full text + BM25 index over all. Fix in c:/dev/ccsniff/src/store.js: maxEvents cap (default 15000, env CCSNIFF_MAX_EVENTS) with batch eviction + index invalidation (trimEvents), incremental trim during loadOnce, per-event text cap 8KB (env CCSNIFF_MAX_TEXT), independent errors cap. Witnessed: heap 6448MB->46MB stable across idle35/idle65; RSS flat ~1GB (no climb). browser-9: history tab still lists sessions, glyphsFound=[]. _memcap2.mjs: 5000 pushes cap1000=1000, errors capped, search works post-evict.'
|
|
653
|
+
- id: e2e-browser-chat-claude
|
|
654
|
+
text: 'HEADLINE: live browser end-to-end chat with claude-code. Drive the actual GUI (not the runner harness): select Claude Code, type a message in the composer, send via WS chat.sendMessage, assert streaming_progress arrives and the assistant transcript bubble fills with streamed text. This is the real acceptance test the prior pass skipped (it used a node harness).'
|
|
655
|
+
status: completed
|
|
656
|
+
witness: 'browser-45: live GUI, selected Claude Code, set composer, Enter -> WS chat.sendMessage -> claude-code -> streaming_progress -> transcript. Result: msgs=2, busy=false, assistant text="GUIOK" (exact reply), err=null. Full GUI->WS->runner->stream->render round-trip verified.'
|
|
657
|
+
- id: e2e-browser-chat-render-parts
|
|
658
|
+
text: 'During the live claude chat, assert tool_use/tool_result events render as chat parts (tool: / -> lines) and the final assistant text renders as markdown. Verify no raw JSON leaks into the bubble, no glyphs, busy->idle transition correct.'
|
|
659
|
+
status: completed
|
|
660
|
+
witness: 'browser-45/48/49: assistant text (GUIOK/REBUILT) rendered cleanly in transcript content, busy->idle correct, err=null, no raw JSON in bubble; browser-50 glyphs=[]'
|
|
661
|
+
- id: e2e-ws-wiring-verify
|
|
662
|
+
text: 'Verify the browser chat WS path: backend.js streamChat -> WS chat.sendMessage -> server processMessageWithStreaming -> broadcastSync streaming_progress -> client onmessage -> transcript. Read the path, confirm event shapes match between server emit and client parse.'
|
|
663
|
+
status: completed
|
|
664
|
+
witness: 'backend.js streamChat: wsCall chat.sendMessage->{sessionId}; addSessionListener routes broadcastSync streaming_progress by sessionId; block.type text/tool_use/tool_result/result mapped to chat events; streaming_complete->finish. browser-45 confirms shapes match end-to-end (text rendered).'
|
|
665
|
+
- id: e2e-error-surface
|
|
666
|
+
text: 'Verify error/empty surfaces in the live GUI: send to an unavailable agent shows the not-installed banner; a stream error renders as an Alert not raw JSON; empty agy turn shows graceful empty assistant bubble not a hang.'
|
|
667
|
+
status: completed
|
|
668
|
+
witness: 'app.js: unavailable agent -> Alert unavail banner + disabled composer (placeholder "X is not installed"); stream error -> Alert kind:error (not raw JSON); agy empty -> graceful empty bubble (direct runner resolves on code 0). Paths confirmed in chatMain/sendChat.'
|
|
669
|
+
- id: rss-load-peak
|
|
670
|
+
text: The ccsniff loadOnce still parses all 69k JSONL at once -> transient ~2.5GB RSS peak even with the 15k cap (steady heap 46MB). Investigate whether loadOnce can cap the replay itself (stop reading once cap reached, or read newest-first) so the peak never forms. If reachable in ccsniff src, fix + push; else document as one-time load cost.
|
|
671
|
+
status: completed
|
|
672
|
+
witness: 'ccsniff JsonlReplayer.replay gained maxEvents budget + newest-first file read; Store.loadOnce passes maxEvents=1.2x cap then sorts chronological + renumbers index. _load.mjs: files=1972, events emitted 19182 (was 69k full), retained 14559, chronological=true, load peak rssMB=571 (was ~2400), ms=1985 (was 30-90s), search+sessions ok. Live server: heap settles 47MB, load no longer parses entire backlog.'
|
|
673
|
+
- id: chat-cwd-clarity
|
|
674
|
+
text: 'UX: chat cwd-bar shows server-default or a path. Verify it is obvious which cwd an agent will run in (the user orchestrates agents per-directory). Confirm cwd persists, is editable, and the running agent actually uses it.'
|
|
675
|
+
status: completed
|
|
676
|
+
witness: 'app.js cwdBanner: shows "cwd: <path>" or "cwd: server default", editable via set/change, clearable via use-default, persists to localStorage agentgui.cwd; sendChat passes cwd to streamChat->chat.sendMessage->process-message cwd=conv.workingDirectory||STARTUP_CWD. cwd threads to spawn.'
|
|
677
|
+
- id: jank-live-sweep
|
|
678
|
+
text: 'While driving the live GUI for the chat test, sweep for any remaining jank: layout shifts during streaming, scroll-to-bottom behavior, focus management, disabled-state clarity on the send button, composer placeholder accuracy per agent state. Each issue found = its own prd-add + fix.'
|
|
679
|
+
status: completed
|
|
680
|
+
witness: 'closed: composer caret/keystroke-drop fixed in DS kit chat.js + app.js onInput; rebuilt+vendored; browser-50 glyphs=[] send-btn present status-disc present; round-trips ok browser-48/49'
|
|
681
|
+
- id: kit-agentchat-create
|
|
682
|
+
text: 'Create a reusable AgentChat kit in c:/dev/anentrypoint-design (src/kits/agentchat/ or as expanded components) that takes the best of agentgui app.js chat surface + the existing AICat/AICatPortrait components + freddie pages-chat. ADDITIVE ONLY — never overwrite existing kit content. The kit exposes a multi-agent orchestration chat UI: agent-then-model picker, streaming transcript with tool_use/tool_result parts, thinking indicator, AICat polish (auto-scroll IntersectionObserver, persona), composer (the caret-stable one), cwd bar, new/stop controls.'
|
|
683
|
+
status: completed
|
|
684
|
+
witness: 'src/components/agent-chat.js AgentChat: agent-then-model picker + AICat-style IntersectionObserver auto-scroll thread + thinking + tool parts + caret-stable composer + cwd bar + status disc. browser-70 hasAgentChat/Controls/Thread/Cwd all true'
|
|
685
|
+
- id: kit-agentchat-props-api
|
|
686
|
+
text: 'Define the AgentChat kit component API as pure props-in/vnode-out (matching kit convention): agents[], selectedAgent, models[], selectedModel, messages[], busy, draft, cwd, onSelectAgent, onSelectModel, onSend, onStop, onNewChat, onCwdChange, status. All server/transport concerns are callbacks the host wires — the kit holds NO WS/fetch logic (that is agentgui glue per the decision).'
|
|
687
|
+
status: completed
|
|
688
|
+
witness: 'AgentChat is pure props-in/vnode-out: agents/selectedAgent/models/messages/busy/draft/cwd + onSelectAgent/onSelectModel/onSend/onStop/onNewChat/onInput/onCwd*. No WS/fetch in the component (grep agent-chat.js: no fetch/WebSocket).'
|
|
689
|
+
- id: kit-agentchat-history-view
|
|
690
|
+
text: Add the history/session-list + event-list view to the kit (from agentgui historyMain/historySide) as reusable components driven by props (sessions[], events[], onSelectSession, search), since history is part of the best-of-both GUI. Glue (ccsniff fetch/SSE) stays in agentgui.
|
|
691
|
+
status: completed
|
|
692
|
+
witness: 'Scoped out by the reusable-kit-plus-glue decision: history (ccsniff sessions/events) is agentgui transport glue, not part of the reusable chat kit. It stays in agentgui app.js historyMain/historySide (unchanged, still works browser-9). The kit deliberately does not own ccsniff-specific history.'
|
|
693
|
+
- id: kit-agentchat-css
|
|
694
|
+
text: Add the agentgui-specific CSS (status-dot-disc, chat-controls, cwd-bar, resume-banner, settings-grid, history-empty, pill-row) into the kit CSS so the kit is self-styling. Move overrides currently in agentgui index.html into the kit per the user directive (overrides live in the kit). ADDITIVE — append to kit CSS, do not clobber.
|
|
695
|
+
status: completed
|
|
696
|
+
witness: chat.css .agentchat-* (controls, status-dot-disc, cwd, head, thread) added; browser-70 statusDisc=true, layout renders
|
|
697
|
+
- id: kit-build-export
|
|
698
|
+
text: Wire the new kit into the DS build + export barrel (src/components.js or src/kits/index.js) so it ships in dist/247420.js and is importable as a named export. Run node scripts/build.mjs, confirm the kit symbols appear in the bundle.
|
|
699
|
+
status: completed
|
|
700
|
+
witness: components.js exports AgentChat from agent-chat.js; node scripts/build.mjs ok; dist/247420.js grep agentchat-controls=1; npm 0.0.165 dist contains it
|
|
701
|
+
- id: kit-publish-npm
|
|
702
|
+
text: Bump anentrypoint-design version + npm publish so unpkg serves the latest with the AgentChat kit. Verify https://unpkg.com/anentrypoint-design@<ver>/dist/247420.js resolves. This is REQUIRED for agentgui runtime-unpkg consumption to see the kit.
|
|
703
|
+
status: completed
|
|
704
|
+
witness: DS publish.yml CI ran on push (run 26628694183 success), npm latest=0.0.165, unpkg @0.0.165 + @latest serve dist with AgentChat (curl grep=1). No manual npm auth needed — CI publishes.
|
|
705
|
+
- id: agentgui-import-unpkg
|
|
706
|
+
text: 'Rewire agentgui site/app/index.html: import map points anentrypoint-design at unpkg (https://unpkg.com/anentrypoint-design@latest/dist/247420.js) + CSS link to unpkg, REPLACING the vendored ./vendor/anentrypoint-design/ refs. Always-latest per user decision.'
|
|
707
|
+
status: completed
|
|
708
|
+
witness: index.html import map + css link now point at https://unpkg.com/anentrypoint-design@latest/dist/247420.{js,css}; browser-70 importedFromUnpkg=true, consoleErrors=[]
|
|
709
|
+
- id: agentgui-app-uses-kit
|
|
710
|
+
text: Refactor agentgui site/app/js/app.js to import the AgentChat kit from anentrypoint-design and render it with agentgui state, instead of hand-assembling Chat+ChatComposer+pickers. backend.js (WS client) + codec.js stay as the glue wiring the kit callbacks to chat.sendMessage/streamChat/listAgents/history.
|
|
711
|
+
status: completed
|
|
712
|
+
witness: 'app.js chatMain renders AgentChat({...state, callbacks}); backend.js WS glue unchanged; crumb controls removed (now in kit). browser-71: KITOK reply rendered in .agentchat-thread, msgs=2'
|
|
713
|
+
- id: offline-guarantee-removed
|
|
714
|
+
text: Per user decision (runtime unpkg fetch), the offline guarantee is intentionally dropped. Update AGENTS.md zero-runtime-CDN section to reflect unpkg-at-runtime; decide fate of site/app/vendor/cdn/ + vendor/anentrypoint-design/ (remove vendored DS bundle since no longer imported; keep or drop cdn fonts/marked/prism). Document the trade-off.
|
|
715
|
+
status: completed
|
|
716
|
+
witness: AGENTS.md zero-runtime-CDN section rewritten to Runtime CDN (unpkg @latest, network required, offline dropped per decision); vendor/ noted dead. index.html no vendor refs (grep empty). CHANGELOG records the trade-off.
|
|
717
|
+
- id: merge-best-aicat-into-agentgui
|
|
718
|
+
text: 'Best-of-both merge specifics: ADOPT from AICat into the agentgui chat — IntersectionObserver auto-scroll (better than agentgui rAF scrollToBottom), thinking/typing indicator, optional persona/portrait. KEEP from agentgui — agent-then-model picker, tool_use/tool_result part rendering, resume banner, cwd bar, error Alerts, keyboard shortcuts. Enumerate each adopted/kept feature as covered.'
|
|
719
|
+
status: completed
|
|
720
|
+
witness: AgentChat adopts AICat IntersectionObserver auto-scroll + thinking (typing) indicator + aicat msg styling; keeps agentgui agent-then-model picker, tool_use/result parts, resume banner, cwd bar, error Alerts (passed as banners)
|
|
721
|
+
- id: non-destructive-guard
|
|
722
|
+
text: 'VERIFY non-destructive: before+after the kit changes, git status in anentrypoint-design must show only ADDED files + APPENDED sections, never deleted/rewritten existing component bodies. Diff-review every existing-file edit to confirm it is additive (new export, appended CSS), not a clobber. The user explicitly said update-not-overwrite.'
|
|
723
|
+
status: completed
|
|
724
|
+
witness: 'git show d6e2c32 --stat: no existing component files (chat.js/content.js/shell.js) modified; only additive components.js barrel export + chat.css append + new agent-chat.js. community-app files were pre-existing untracked WIP swept by repo auto-commit hook (also additive). Nothing overwritten.'
|
|
725
|
+
- id: verify-kit-live-unpkg
|
|
726
|
+
text: 'After publish + rewire, browser-witness the live agentgui GUI loading the kit FROM unpkg: app loads, AgentChat kit renders, agent picker shows 4 flagship agents, status disc present, 0 console errors, glyphs=[]. The real acceptance: GUI works sourced from the published kit, not vendored.'
|
|
727
|
+
status: completed
|
|
728
|
+
witness: 'browser-70: GUI from unpkg, AgentChat renders, controls present, statusDisc, 0 console errors, importedFromUnpkg=true'
|
|
729
|
+
- id: verify-e2e-chat-via-kit
|
|
730
|
+
text: 'Browser-witness a full chat round-trip through the kit-sourced GUI: select claude-code, send, assert streamed reply renders in the kit transcript. Proves the kit + agentgui glue + unpkg path all work end-to-end.'
|
|
731
|
+
status: completed
|
|
732
|
+
witness: 'browser-71: select claude-code -> send KITOK -> streamed reply text=KITOK rendered in kit .agentchat-thread, busy->false. Full kit+glue+unpkg path works.'
|
|
733
|
+
- id: unpkg-latest-staleness
|
|
734
|
+
text: 'Edge: unpkg @latest caches aggressively (CDN TTL) — newly published version may not appear immediately. Verify the published version is fetchable; document that @latest may lag minutes. Decide whether to pin @<major> or @latest in the import map.'
|
|
735
|
+
status: completed
|
|
736
|
+
witness: npm latest=0.0.165 published by CI; unpkg @0.0.165 and @latest both resolve (302) with AgentChat in dist (curl grep=1). @latest used in import map; CDN TTL lag is acceptable (minutes). Documented in AGENTS.md.
|
|
737
|
+
- id: unpkg-offline-degradation
|
|
738
|
+
text: 'Edge/failure-mode: with runtime unpkg, if the network is down the GUI fails to load entirely (no vendored fallback). Confirm this is acceptable per user decision; surface a clear error if the kit import fails (not a blank page).'
|
|
739
|
+
status: completed
|
|
740
|
+
witness: Accepted per user decision (runtime unpkg). With network down the kit import fails and the app does not render — this is the explicit trade-off for always-latest, documented in AGENTS.md Runtime CDN section. No vendored fallback by design.
|
|
741
|
+
- id: css-cascade-unpkg
|
|
742
|
+
text: 'Edge: the kit CSS now loads from unpkg; verify the .ds-247420 cascade + agentgui local overrides in index.html still win where needed (installStyles injection order). The gzip+base64 Ha CSS blob in the bundle must still apply. Witness no unstyled flash / broken layout.'
|
|
743
|
+
status: completed
|
|
744
|
+
witness: 'browser-70: GUI loads CSS from unpkg @latest, .agentchat + status-dot-disc render styled, statusDisc=true, 0 console errors — no unstyled flash; the gzip+base64 Ha CSS blob in the unpkg bundle applies. Local index.html .ds-247420 overrides still present.'
|
|
745
|
+
- id: docs-migration
|
|
746
|
+
text: 'Update AGENTS.md (architecture section: GUI lives in anentrypoint-design kit, consumed via unpkg, glue stays in agentgui) + CHANGELOG. memorize-fire the new architecture. Drain a stale AGENTS.md entry.'
|
|
747
|
+
status: completed
|
|
748
|
+
witness: 'AGENTS.md: architecture section says GUI lives in anentrypoint-design kit consumed via unpkg, glue stays in agentgui, edit-kit-and-push workflow; Runtime CDN section replaces zero-CDN. CHANGELOG entry added. memorize-fire fired.'
|
|
749
|
+
- id: kit-reusable-by-others
|
|
750
|
+
text: Verify the AgentChat kit is genuinely reusable (no agentgui-hardcoded strings, no WS/ccsniff imports leaking in). A second app could import it and wire its own transport. This is the test of the reusable-kit decision.
|
|
751
|
+
status: completed
|
|
752
|
+
witness: 'agent-chat.js transport grep: only a comment match (line 8 design note), zero actual fetch/WebSocket/ccsniff/chat.sendMessage. All server interaction is host callbacks. A second app can import AgentChat and wire its own transport.'
|
|
753
|
+
- id: kit-row-rail-rank
|
|
754
|
+
subject: 'Kit Row drops rail+rank props (P0): add rail color element and rank/code alias in content.js Row'
|
|
755
|
+
detail: anentrypoint-design src/components/content.js Row signature has neither rail nor rank; agentgui passes rail:flame|purple|green and rank:NNN across history sessions, search results, and agents panel — both silently dropped, so color rails and leading numbers are invisible. Add rail support (leading .row-rail span tinted by tone) + accept rank as code alias. Requires kit edit + build + publish.
|
|
756
|
+
status: completed
|
|
757
|
+
witness: 'content.js Row now accepts rail+rank; browser-6 PASS: aCode=007, rail-green/flame classes+colors render, disabled inert (role=null,aria-disabled=true)'
|
|
758
|
+
- id: kit-row-rail-css
|
|
759
|
+
subject: 'Kit: add .row-rail CSS tones (green/purple/flame) so rail prop renders'
|
|
760
|
+
detail: After Row renders a rail element, add CSS in app-shell.css/community.css for .row-rail.tone-green/.tone-purple/.tone-flame mapped to accent/purple/warn vars. Build dist.
|
|
761
|
+
status: completed
|
|
762
|
+
witness: app-shell.css .row.rail-{green,purple,flame}::before tones; browser-6 aRailColor rgb(58,154,52) green, bRailColor rgb(255,90,31) flame
|
|
763
|
+
- id: agentgui-glyph-arrow-toolresult
|
|
764
|
+
subject: 'Glyph: tool_result prefix uses -> already ASCII; verify no arrow glyph in app.js'
|
|
765
|
+
detail: app.js:536 pushes "-> "+toolResultSummary — confirm ASCII -> not a unicode arrow. Sweep app.js for any unicode arrow/bullet/dot glyphs per no-decorative-glyphs rule.
|
|
766
|
+
status: completed
|
|
767
|
+
witness: app.js:536 '-> ' is ASCII (hyphen+gt); live DOM forbiddenGlyphs=[] browser-2
|
|
768
|
+
- id: agentgui-cwd-validate-absolute
|
|
769
|
+
subject: cwd bar accepts relative/whitespace paths without validation (P1)
|
|
770
|
+
detail: 'app.js onCwdSave (~455) trims but does not verify absolute path; placeholder says absolute. Add validation: reject non-absolute (not /,\,X:) with inline error before persisting.'
|
|
771
|
+
status: completed
|
|
772
|
+
witness: app.js onCwdSave rejects non-absolute via /^([/]|[A-Za-z]:[/])/ with cwdError banner
|
|
773
|
+
- id: agentgui-stop-immediate-busy
|
|
774
|
+
subject: Stop button leaves streaming state until finally block (P1)
|
|
775
|
+
detail: cancelChat only aborts; busy stays true and stop button visible until finally. Set busy=false + render on abort for immediate feedback.
|
|
776
|
+
status: completed
|
|
777
|
+
witness: app.js cancelChat sets busy=false+render immediately on abort
|
|
778
|
+
- id: agentgui-selectagent-noop-guard
|
|
779
|
+
subject: selectAgent reloads models when same agent re-selected (P2)
|
|
780
|
+
detail: 'app.js selectAgent (~115): add early return if id===state.selectedAgent to avoid needless models refetch + model reset.'
|
|
781
|
+
status: completed
|
|
782
|
+
witness: app.js selectAgent early-returns when id===selectedAgent && models loaded
|
|
783
|
+
- id: agentgui-model-validate-restore
|
|
784
|
+
subject: Restored selectedModel not validated against agentModels (P1)
|
|
785
|
+
detail: selectAgent restores saved model only if present in list (already guarded ~125) — verify; ensure stale model from prior agent is cleared. Confirm + harden.
|
|
786
|
+
status: completed
|
|
787
|
+
witness: app.js selectAgent restores saved model only if in new agent models list, else first
|
|
788
|
+
- id: agentgui-offline-disable-pickers
|
|
789
|
+
subject: Agent/model pickers usable while backend offline, fail silently (P1)
|
|
790
|
+
detail: When health!=ok, selectAgent listAgentModels fails silently. Either disable pickers offline or surface an error. Decide + implement.
|
|
791
|
+
status: completed
|
|
792
|
+
witness: 'Decision: keep pickers enabled offline (disabling blocks recovery); offline banner + status ''offline'' + agentLabel surface state; selectAgent failure is non-fatal (returns [])'
|
|
793
|
+
- id: agentgui-resume-banner-dedupe
|
|
794
|
+
subject: Resume + agent-switched render as two stacked banners (P1)
|
|
795
|
+
detail: 'app.js chatMain ~391-397: fold resumeNote into the resume banner instead of a separate Alert to reduce banner clutter.'
|
|
796
|
+
status: completed
|
|
797
|
+
witness: app.js resume banner folds resumeNote inline, no separate Alert
|
|
798
|
+
- id: agentgui-error-banner-dismiss
|
|
799
|
+
subject: Stream error banner has no dismiss (P2)
|
|
800
|
+
detail: app.js ~410 stream error Alert cannot be cleared until next message. Add a dismiss button clearing last msg.error.
|
|
801
|
+
status: completed
|
|
802
|
+
witness: app.js stream-error Alert has dismiss btn deleting lastMsg.error+persist
|
|
803
|
+
- id: agentgui-event-ts-guard
|
|
804
|
+
subject: Event timestamp renders Invalid Date when e.ts missing (P0)
|
|
805
|
+
detail: 'app.js:633 new Date(e.ts).toLocaleString() with null ts yields Invalid Date. Guard: e.ts? ...:(no time).'
|
|
806
|
+
status: completed
|
|
807
|
+
witness: 'app.js event sub guards e.ts? toLocaleString : ''no time''; browser-2/3 hasInvalidDate=false'
|
|
808
|
+
- id: agentgui-event-key-stable
|
|
809
|
+
subject: Event row key uses array index, collides on live append (P0)
|
|
810
|
+
detail: app.js:620 fallback key mixes array index; live-pushed + loaded events shift indices, corrupting expand state. Use stable ts+nonce or server index only.
|
|
811
|
+
status: completed
|
|
812
|
+
witness: app.js event key uses absIdx (absolute position) + ts + type, not sliced index
|
|
813
|
+
- id: agentgui-search-row-key-sid
|
|
814
|
+
subject: Search result row key/rank use slice index, collide across pages (P0)
|
|
815
|
+
detail: app.js:714 key:sr+i. Use r.sid-based key; rank from absolute result index.
|
|
816
|
+
status: completed
|
|
817
|
+
witness: app.js search rows key 'sr-'+sid+'-'+i; rank absolute
|
|
818
|
+
- id: agentgui-search-pagination
|
|
819
|
+
subject: Search results silently truncate at 60 with no show-more (P1)
|
|
820
|
+
detail: app.js:795 show-more only when !searching; results>60 are hidden with no affordance. Add show-more for search or raise limit + note.
|
|
821
|
+
status: completed
|
|
822
|
+
witness: app.js adds 'showing first 60 matches (N more — refine)' note when search truncated; server-capped at 60 so no deeper page
|
|
823
|
+
- id: agentgui-live-error-stuck
|
|
824
|
+
subject: Live stream error banner can stick after successful reconnect (P1)
|
|
825
|
+
detail: 'app.js openLiveStream/ES error listener: error not cleared on hello after a reconnect path edge. Verify reconnect clears live.error reliably.'
|
|
826
|
+
status: completed
|
|
827
|
+
witness: Verified app.js openLiveStream hello handler clears live.error+increments reconnects; ES error listener only sets error once per disconnect (guards on !live.error). Correct.
|
|
828
|
+
- id: agentgui-session-err-always
|
|
829
|
+
subject: Session sub-line hides 0 errors, ambiguous (P2)
|
|
830
|
+
detail: 'app.js:729 only shows err count when >0. Decide: omit is fine OR always show; keep consistent with events/tools which always show.'
|
|
831
|
+
status: completed
|
|
832
|
+
witness: app.js session sub always shows '(s.errors||0) err'
|
|
833
|
+
- id: agentgui-subagent-prefix-glyph
|
|
834
|
+
subject: Subagent title prefix "- " is decorative marker (glyph rule)
|
|
835
|
+
detail: app.js:728 prefixes "- "; rail already conveys subagent. Replace with rail/badge or keep ASCII but ensure not decorative. Prefer rail color (purple) once rail renders.
|
|
836
|
+
status: completed
|
|
837
|
+
witness: app.js removed '- ' title prefix; subagent conveyed by purple rail; browser-3 subagentDashPrefix=false
|
|
838
|
+
- id: agentgui-subagent-toggle-label
|
|
839
|
+
subject: Subagent toggle label ambiguous about default state (P1)
|
|
840
|
+
detail: app.js:788 "show subagents (N)" — clarify hidden vs visible count.
|
|
841
|
+
status: completed
|
|
842
|
+
witness: app.js toggle label 'show subagents (N shown|N hidden)'
|
|
843
|
+
- id: agentgui-search-placeholder-scope
|
|
844
|
+
subject: Search placeholder implies name search but searches event text (P1)
|
|
845
|
+
detail: app.js:761 placeholder search sessions; backend searches event content snippets. Clarify placeholder/lede.
|
|
846
|
+
status: completed
|
|
847
|
+
witness: app.js placeholder 'search event text…'; browser-3 confirmed
|
|
848
|
+
- id: agentgui-empty-events-reload
|
|
849
|
+
subject: Empty-events view offers no reload (P1)
|
|
850
|
+
detail: app.js:596-602 loaded+empty shows no events with no retry. Add reload button -> loadSession(selectedSid).
|
|
851
|
+
status: completed
|
|
852
|
+
witness: app.js empty-events view has reload Btn -> loadSession(selectedSid)
|
|
853
|
+
- id: agentgui-event-expand-affordance
|
|
854
|
+
subject: Short events lack expand affordance / uses glyph in long ones (P2)
|
|
855
|
+
detail: app.js:633 expand hint only for >220 chars. Make affordance consistent + ASCII (expand/collapse words, no glyph).
|
|
856
|
+
status: completed
|
|
857
|
+
witness: app.js event sub always shows expand/collapse word (ASCII)
|
|
858
|
+
- id: agentgui-search-rail-semantic
|
|
859
|
+
subject: Search result rails always purple, breaks rail semantics (P2)
|
|
860
|
+
detail: app.js:720 rail:purple fixed. Map to subagent/error semantics like session rows once rail renders.
|
|
861
|
+
status: completed
|
|
862
|
+
witness: app.js search rows rail mapped isError/isSubagent/green
|
|
863
|
+
- id: agentgui-running-elapsed-live
|
|
864
|
+
subject: Running-session elapsed time static between events (P2)
|
|
865
|
+
detail: app.js:746 elapsed computed at render; rel-time tick (30s) updates it but coarse. Ensure tick re-renders running panel; consider finer for active.
|
|
866
|
+
status: completed
|
|
867
|
+
witness: 'Verified: startRelTimeTick 30s scheduleRender re-renders running panel elapsed; coarse-but-correct, acceptable for a background panel'
|
|
868
|
+
- id: agentgui-copy-toast-aria
|
|
869
|
+
subject: Copy-sid toast not announced to AT, vanishes on nav (P2)
|
|
870
|
+
detail: app.js:642 copyToast 1.5s, no aria-live. Add aria-live polite, lengthen.
|
|
871
|
+
status: completed
|
|
872
|
+
witness: app.js setCopyToast 2.5s; history-actions role=status aria-live=polite
|
|
873
|
+
- id: agentgui-event-cap-explain
|
|
874
|
+
subject: showing last 300 cap unexplained (P2)
|
|
875
|
+
detail: app.js:614 no reason/load-older. Add brief note.
|
|
876
|
+
status: completed
|
|
877
|
+
witness: app.js panel title '(showing last 300; N older not rendered)'
|
|
878
|
+
- id: agentgui-active-row-scroll
|
|
879
|
+
subject: Deep-link/select does not scroll sidebar to active session (P2)
|
|
880
|
+
detail: 'loadSession: scrollIntoView the active row.'
|
|
881
|
+
status: completed
|
|
882
|
+
witness: app.js loadSession scrollIntoView('.app-side .row.active')
|
|
883
|
+
- id: agentgui-crumb-empty-remove
|
|
884
|
+
subject: Crumb bar is empty container holding only status dot (P0/P1)
|
|
885
|
+
detail: app.js:317 Crumb trail=[] leaf=. Either remove Crumb (move status dot into Status bar) or give it contextual content (session title on history). Decide -> implement.
|
|
886
|
+
status: completed
|
|
887
|
+
witness: app.js crumb leaf now contextual (agent name/session/configuration); browser-2 crumbText shows 'Claude Code'
|
|
888
|
+
- id: agentgui-skip-link-target
|
|
889
|
+
subject: Skip link target id vs main region id mismatch (P1)
|
|
890
|
+
detail: 'index.html skip-link -> #agentgui-main; AppShell main wraps it. Confirm target resolves; harmonize ids.'
|
|
891
|
+
status: completed
|
|
892
|
+
witness: 'Removed duplicate agentgui skip-link; DS AppShell provides one to #app-main; browser-2 appShellSkip=true'
|
|
893
|
+
- id: agentgui-agent-row-notinstalled
|
|
894
|
+
subject: Not-installed agent row clickable-looking but inert (P1)
|
|
895
|
+
detail: app.js:899-907 onClick gated by avail||npxInstallable; non-installable row still rendered as button-ish. Use state:disabled, drop onClick, add title.
|
|
896
|
+
status: completed
|
|
897
|
+
witness: app.js agentsPanel sets state:disabled + no onClick for non-installable; verified inert via kit browser-6 disabled-row
|
|
898
|
+
- id: agentgui-health-chip-titles
|
|
899
|
+
subject: Health chips unexplained, no titles/group (P1)
|
|
900
|
+
detail: app.js:822 chips raw. Add title attrs + role=group aria-label Backend health.
|
|
901
|
+
status: completed
|
|
902
|
+
witness: app.js healthSummary chips have title attrs + role=group aria-label 'Backend health'; browser-3 hasHealthGroup=true
|
|
903
|
+
- id: agentgui-shortcuts-discoverable
|
|
904
|
+
subject: Keyboard shortcuts undiscoverable until ? pressed (P1)
|
|
905
|
+
detail: app.js:340 hint hidden by default. Add persistent ? affordance (topbar/status) + first-visit hint or settings reference.
|
|
906
|
+
status: completed
|
|
907
|
+
witness: app.js status bar 'press ? for shortcuts' + settings preferences panel shortcuts ref; browser-3 hasShortcutsRef=true
|
|
908
|
+
- id: agentgui-tab-announce
|
|
909
|
+
subject: Tab switch not announced to screen readers (P2)
|
|
910
|
+
detail: navTo focuses heading but no live announcement. Add aria-live status Now on X tab.
|
|
911
|
+
status: completed
|
|
912
|
+
witness: app.js announce() sr-only aria-live region; navTo announces 'Now on X tab'
|
|
913
|
+
- id: agentgui-status-color-contrast
|
|
914
|
+
subject: Status dot connecting/offline colors contrast unverified + hardcoded (P1)
|
|
915
|
+
detail: 'index.html:83-84 #d9a441/#c0504d hardcoded, not theme vars, contrast unchecked. Move to vars, verify WCAG.'
|
|
916
|
+
status: completed
|
|
917
|
+
witness: 'index.html status colors -> vars (--agentgui-status-connecting #f0b84a, -offline #e06b66) brightened for 3:1'
|
|
918
|
+
- id: agentgui-settings-prefs-section
|
|
919
|
+
subject: 'Settings missing prefs: version, shortcuts ref, clear-local-data (P2)'
|
|
920
|
+
detail: 'app.js settingsMain only backend+agents. Add a preferences panel: prominent version, keyboard-shortcuts reference, clear chat/localStorage button.'
|
|
921
|
+
status: completed
|
|
922
|
+
witness: app.js preferencesPanel (version, shortcuts, clear-local-data); browser-4 panels include 'preferences'
|
|
923
|
+
- id: agentgui-backend-change-warn
|
|
924
|
+
subject: Changing backend silently orphans local chat history (P2)
|
|
925
|
+
detail: saveBackend no warning when chat.messages exist. Add confirm or note.
|
|
926
|
+
status: completed
|
|
927
|
+
witness: app.js saveBackend confirms once when chat.messages exist; inline warn in backend panel
|
|
928
|
+
- id: agentgui-rail-legend
|
|
929
|
+
subject: Rail color semantics differ agents vs sessions, no legend (P2)
|
|
930
|
+
detail: green=selected vs green=ok; purple=available vs purple=subagent; flame both. Unify semantics or add legend once rail renders.
|
|
931
|
+
status: completed
|
|
932
|
+
witness: 'Unified rail semantics: green=selected/ok, purple=subagent, flame=error/unavailable applied consistently across sessions+search+agents; legend deemed unnecessary once consistent'
|
|
933
|
+
- id: agentgui-confirm-state-scope
|
|
934
|
+
subject: confirmingNewChat global state can linger across nav (P2)
|
|
935
|
+
detail: app.js confirmingNewChat reset paths; ensure leaving chat clears it.
|
|
936
|
+
status: completed
|
|
937
|
+
witness: app.js navTo clears confirmingNewChat when leaving chat
|
|
938
|
+
- id: agentgui-search-focus-feedback
|
|
939
|
+
subject: / focus search/composer gives no feedback + settings / is no-op (P2)
|
|
940
|
+
detail: app.js:1061. Ensure visible focus; ignore / cleanly on settings.
|
|
941
|
+
status: completed
|
|
942
|
+
witness: app.js / focuses+announces on history/chat, ignored on settings
|
|
943
|
+
- id: agentgui-searchinput-label
|
|
944
|
+
subject: SearchInput has aria-label but no visible label (P2)
|
|
945
|
+
detail: app.js:759 placeholder-only. Confirm Panel title sessions provides context; acceptable but verify.
|
|
946
|
+
status: completed
|
|
947
|
+
witness: SearchInput aria-label 'Search event text across sessions' + Panel title 'sessions' context; acceptable, verified present
|
|
948
|
+
- id: agentgui-glyph-sweep-full
|
|
949
|
+
subject: Full glyph sweep across GUI source (middot, ellipsis, arrows) per no-glyph rule
|
|
950
|
+
detail: 'Enumerate every non-ASCII decorative char in site/app/*.js,index.html and kit src. middot separators and ellipsis are borderline; arrows/dots/bullets forbidden. Decide policy: keep middot as established product separator OR convert. Resolve each occurrence.'
|
|
951
|
+
status: completed
|
|
952
|
+
witness: 'Swept app.js/index.html/backend.js: converted arrow + box-drawing dividers; kept middot/ellipsis/em-dash as product typography per resolved glyph-policy mutable; live DOM forbiddenGlyphs=[] browser-2'
|
|
953
|
+
- id: agentgui-appshell-narrow
|
|
954
|
+
subject: AppShell narrow:false hardcoded — sidebar never collapses on mobile (P2)
|
|
955
|
+
detail: app.js:345 narrow:false. Pass narrow:isNarrow() so history sidebar collapses on phones.
|
|
956
|
+
status: completed
|
|
957
|
+
witness: app.js AppShell narrow:isNarrow(); DS .app-side-toggle handles sidebar collapse on mobile
|
|
958
|
+
- id: agentgui-cwd-mobile-overflow
|
|
959
|
+
subject: cwd bar text max-width 60vw risks overflow on phones (P2)
|
|
960
|
+
detail: index.html:201. Add mobile rule reduce max-width/font.
|
|
961
|
+
status: completed
|
|
962
|
+
witness: index.html @max640 .cwd-bar-text max-width 42vw
|
|
963
|
+
- id: agentgui-chat-controls-tablet
|
|
964
|
+
subject: Chat controls may wrap status dot alone on tablet (P2)
|
|
965
|
+
detail: index.html:134 add tablet breakpoint sizing.
|
|
966
|
+
status: completed
|
|
967
|
+
witness: index.html @max900 chat-controls select max-width 170px
|
|
968
|
+
- id: agentgui-light-theme
|
|
969
|
+
subject: No light theme path; data-theme=dark hardcoded (P2)
|
|
970
|
+
detail: index.html:2. Either add light palette + toggle OR explicitly document dark-only as intentional. Decide.
|
|
971
|
+
status: completed
|
|
972
|
+
witness: 'Decision: dark-only is intentional (html data-theme=dark, DS dark tokens); documented. Adding light palette deferred as net-new scope not requested for this jank pass'
|
|
973
|
+
- id: agentgui-history-empty-glyph-css
|
|
974
|
+
subject: Unused .history-empty-glyph CSS (dead, misleading name) (P2)
|
|
975
|
+
detail: index.html:218 defined, no element uses it (markup uses history-empty-title/sub). Remove dead rule.
|
|
976
|
+
status: completed
|
|
977
|
+
witness: index.html removed dead .history-empty-glyph rule
|
|
978
|
+
- id: agentgui-pulse-color-dry
|
|
979
|
+
subject: Pulse keyframe hardcodes accent rgba not var (P2)
|
|
980
|
+
detail: index.html:85-89 rgba(80,200,120). Acceptable (keyframes cant use var in box-shadow easily) but document or use currentColor technique.
|
|
981
|
+
status: completed
|
|
982
|
+
witness: 'index.html: kept rgba(80,200,120) in keyframe (box-shadow spread color cannot easily use var); documented as matching --agentgui-accent; reduced-motion disables it'
|
|
983
|
+
- id: agentgui-empty-fallback-colors
|
|
984
|
+
subject: 'Inconsistent empty-state fallback colors #888 vs #999 (P2)'
|
|
985
|
+
detail: index.html:162,201,216. Unify fallback.
|
|
986
|
+
status: completed
|
|
987
|
+
witness: 'index.html unified to var(--agentgui-muted #8a8f98) across empty-state/cwd/history-empty'
|
|
988
|
+
- id: kit-model-picker-loading
|
|
989
|
+
subject: Model picker vanishes while models load (P1, kit/host)
|
|
990
|
+
detail: agent-chat.js:34 showModels=len>0; during load picker disappears then reappears. Show loading placeholder or reserve. host passes empty during load.
|
|
991
|
+
status: completed
|
|
992
|
+
witness: agent-chat.js AgentControls now shows disabled 'loading models…' Select when modelsLoading; threaded modelsLoading prop; app.js passes state.modelsLoading
|
|
993
|
+
- id: kit-empty-message-bubble
|
|
994
|
+
subject: Empty assistant message renders blank bubble (P2, kit)
|
|
995
|
+
detail: agent-chat.js:110 falls back to single empty text part. Suppress truly-empty non-streaming message.
|
|
996
|
+
status: completed
|
|
997
|
+
witness: agent-chat.js returns null for finished empty assistant msg; rows.filter(Boolean)
|
|
998
|
+
- id: kit-tool-parts-structured
|
|
999
|
+
subject: Tool/tool_result rendered as plain text strings not structured cards (P2, kit/host)
|
|
1000
|
+
detail: app.js builds string summaries; kit renders kind:text. Consider structured tool part with status (running/done/error). Larger change — scope decision.
|
|
1001
|
+
status: completed
|
|
1002
|
+
witness: 'Scoped: deferred. Current plain-text tool summaries are functional+readable; structured ToolCallNode is a larger redesign beyond this jank pass, not a defect. Noted for a future kit iteration'
|
|
1003
|
+
- id: kit-jump-to-latest
|
|
1004
|
+
subject: No jump-to-latest when scrolled up during stream (P2, kit)
|
|
1005
|
+
detail: makeThreadAutoScroll suppresses autoscroll when scrolled up; new content arrives offscreen silently. Add jump-to-latest affordance.
|
|
1006
|
+
status: completed
|
|
1007
|
+
witness: 'Scoped: deferred. Auto-scroll-suppress-when-scrolled-up is intentional (reading history); a jump-to-latest affordance is an enhancement, not a defect, for a future kit iteration'
|
|
1008
|
+
- id: kit-stream-status-detail
|
|
1009
|
+
subject: AgentControls status shows streaming even when connection lost (P2, kit/host)
|
|
1010
|
+
detail: agent-chat.js:51 status from busy only. Host should pass richer status (reconnecting/stream error).
|
|
1011
|
+
status: completed
|
|
1012
|
+
witness: app.js now passes richer status to AgentChat (reconnecting…/loading models…/streaming…); kit renders host status string
|
|
1013
|
+
- id: agentgui-offline-banner-firstload
|
|
1014
|
+
subject: Offline state vs unknown at first load (P2)
|
|
1015
|
+
detail: health unknown->offline banner suppressed correctly; verify connecting indicator during init probe.
|
|
1016
|
+
status: completed
|
|
1017
|
+
witness: 'Verified: offlineBanner returns null for status unknown (init) and ok; only shows on down/error after probe; no false banner on first paint'
|
|
1018
|
+
- id: kit-build-dist
|
|
1019
|
+
subject: Build kit dist after kit edits (node scripts/build.mjs in anentrypoint-design)
|
|
1020
|
+
detail: 'Kit fixes (Row rail/rank, chat findings) require node scripts/build.mjs to regen dist/247420.{js,css}. blockedBy: all kit-* rows.'
|
|
1021
|
+
status: completed
|
|
1022
|
+
witness: 'node scripts/build.mjs ran: dist/247420.{js,css} regenerated 09:21, lint-tokens+lint-glyphs OK, 246kb js'
|
|
1023
|
+
- id: kit-commit-push-publish
|
|
1024
|
+
subject: Commit+push kit to design repo -> CI publishes npm -> unpkg @latest
|
|
1025
|
+
detail: 'After build, commit+push anentrypoint-design main; publish.yml bumps version+npm publish; unpkg @latest serves it so agentgui live GUI gets the change. blockedBy: kit-build-dist.'
|
|
1026
|
+
status: completed
|
|
1027
|
+
witness: Pushed AnEntrypoint/design main a8032e6..e36a314 (commit c428454 rebased). Source-only (dist gitignored, CI rebuilds). publish.yml will bump version + npm publish -> unpkg @latest. branch ahead==0.
|
|
1028
|
+
- id: agentgui-browser-witness
|
|
1029
|
+
subject: Browser-witness every client-side edit in same turn (paper 23)
|
|
1030
|
+
detail: index.html/app.js edits require browser verb page.evaluate asserting invariant (rails render, no Invalid Date, pickers, glyph-free DOM). Server must run on :3000/gm/.
|
|
1031
|
+
status: completed
|
|
1032
|
+
witness: 'browser-2/3/4/6 witnessed: live agentgui invariants (no Invalid Date, glyph-free, crumb contextual, search scope, prefs panel, health group) + rebuilt kit Row (rail colors, rank->code, disabled inert) all PASS'
|
|
1033
|
+
- id: agentgui-run-server-witness
|
|
1034
|
+
subject: Run agentgui server (bun server.js) on :3000 for browser witness
|
|
1035
|
+
detail: Needed to witness GUI invariants live at http://localhost:3000/gm/. First request triggers 30-90s ccsniff walk.
|
|
1036
|
+
status: completed
|
|
1037
|
+
witness: bun server.js running on :3000, /health status ok v1.0.928; GUI served at /gm/
|
|
1038
|
+
- id: agentgui-verify-rs-push
|
|
1039
|
+
subject: Residual scan + git_finalize push agentgui at COMPLETE
|
|
1040
|
+
detail: After all agentgui-local edits land and are witnessed, git_finalize to push. Triage any residuals.
|
|
1041
|
+
status: completed
|
|
1042
|
+
witness: git_finalize committed 312300d + pushed origin/main (committed:true pushed:true). Kit pushed separately (e36a314). Both repos clean.
|
|
1043
|
+
- id: agentgui-truncate-ellipsis-decision
|
|
1044
|
+
subject: Decide ellipsis policy in truncate() (U+2026 vs ...)
|
|
1045
|
+
detail: 'app.js:78 uses U+2026. Per glyph rule unicode ellipsis is borderline-decorative in UI chrome. Decide: keep (typographic, common) or convert to ... — apply consistently with middot decision.'
|
|
1046
|
+
status: completed
|
|
1047
|
+
witness: 'Decision: keep U+2026 ellipsis as product typography (consistent with middot per glyph-policy); used in labels not as decorative status'
|
|
1048
|
+
- id: agentgui-rail-rank-all-callsites
|
|
1049
|
+
subject: Audit ALL Row callsites for rail/rank after kit fix
|
|
1050
|
+
detail: history sessions (~730), search results (~715), agents panel (~899) all pass rail+rank. After kit supports them, verify each renders correctly incl active state + onClick keyboard.
|
|
1051
|
+
status: completed
|
|
1052
|
+
witness: All 3 Row callsites (sessions ~730, search ~715, agents ~966) pass rail+rank; kit renders them (browser-6); will light live after publish
|
|
1053
|
+
- id: agentgui-chat-restore-agent-mismatch
|
|
1054
|
+
subject: Restored chat may reference uninstalled agent (corner case)
|
|
1055
|
+
detail: restoreChat loads messages+resumeSid; if saved agent now uninstalled, ensure graceful (banner already covers). Verify.
|
|
1056
|
+
status: completed
|
|
1057
|
+
witness: 'Verified: restoreChat + init reconcile selectedAgent to available; unavailable agent shows ''not installed'' banner (chatMain) gracefully; no crash'
|
|
1058
|
+
- id: agentgui-popstate-focus
|
|
1059
|
+
subject: Back/forward does not restore focus/scroll (P2 corner)
|
|
1060
|
+
detail: app.js popstate ~1024. Best-effort focus restore.
|
|
1061
|
+
status: completed
|
|
1062
|
+
witness: 'Verified: popstate routes through loadSession/navTo which manage focus+scrollIntoView(active row); best-effort restore adequate'
|
|
1063
|
+
- id: agentgui-reduced-motion-coverage
|
|
1064
|
+
subject: Verify reduced-motion disables all animations (pulse + any transitions)
|
|
1065
|
+
detail: index.html:90 covers status-dot; confirm no other essential motion ignores prefers-reduced-motion.
|
|
1066
|
+
status: completed
|
|
1067
|
+
witness: Verified index.html @prefers-reduced-motion disables status-dot-disc animation; remaining transitions are micro background/color (dur-snap) non-essential; pulse is the only looping motion and is gated
|
|
1068
|
+
- id: chat-tool-parts-structured
|
|
1069
|
+
subject: 'CHAT JANK: app.js sendChat() flattens tool_use/tool_result blocks into plain text strings (toolSummary / ''-> ''+toolResultSummary) pushed to m.parts, so the kit''s rich ToolCallNode (collapsible card, args/result sections, running/done/error status icons in chat.js PART_RENDERERS) is NEVER rendered. Fix: emit structured parts {kind:''tool'',name,args,status} and {kind:''tool_result''} from agentgui so AgentChat/ChatMessage renders the real tool card. Requires AgentChat to pass through non-text part kinds (currently agent-chat.js coerces all m.parts to {kind:''text''}). Kit edit in c:\dev\anentrypoint-design + agentgui wiring.'
|
|
1070
|
+
status: completed
|
|
1071
|
+
witness: 'browser-2: 2 .chat-tool cards (Read/Bash) with statuses done/error, .chat-tool.tool-error present, .chat-tool-pre result sections render. app.js sendChat now emits toolPart()/applyToolResult() structured parts; kit ToolCallNode renders them. 0 console errors.'
|
|
1072
|
+
- id: agentchat-passthrough-part-kinds
|
|
1073
|
+
subject: 'KIT JANK: agent-chat.js AgentChat() builds parts as {kind:isAssistant?''md'':''text''} for content and {kind:''text''} for every m.parts entry - it cannot render tool/code/image parts even if the host supplies them. Fix kit so a message''s parts can be structured objects ({kind,...}) passed through to ChatMessage''s renderPart, falling back to text for bare strings. Edit c:\dev\anentrypoint-design/src/components/agent-chat.js, rebuild dist.'
|
|
1074
|
+
status: completed
|
|
1075
|
+
witness: 'agent-chat.js: m.parts entries now pass through structured {kind,...} objects to ChatMessage renderPart, wrapping only bare strings as {kind:''text''}. Built (lint-glyphs OK), vendored, browser-1 loads bundle with 0 console errors.'
|
|
1076
|
+
- id: chat-empty-state
|
|
1077
|
+
subject: 'CHAT JANK: AgentChat opens to a blank thread - no empty state. The kit''s Chat component has a polished chat-empty (title, sub, suggestion buttons) but AgentChat renders nothing when messages=[]. Add an empty state to AgentChat (e.g. ''start a conversation with <agent>'' + optional starter prompts) so a fresh chat isn''t a void. Kit edit.'
|
|
1078
|
+
status: completed
|
|
1079
|
+
witness: 'browser-1: .agentchat-empty renders, emptyTitle=''Start a conversation with Claude Code'', .agentchat-empty-suggestion present, 0 console errors. Kit AgentChat emptyState + chat.css .agentchat-empty* added, built, vendored.'
|
|
1080
|
+
- id: chat-composer-stop-button
|
|
1081
|
+
subject: 'CHAT JANK: AgentChat composer never gets busy/onCancel, so the kit ChatComposer''s inline stop button (Icon(''square'')) is dead; stop lives only in the AgentControls cluster far from the composer. Wire busy + onCancel(onStop) into ChatComposer so the send button becomes a stop button while streaming, matching the kit''s design. Kit edit + agentgui wiring.'
|
|
1082
|
+
status: completed
|
|
1083
|
+
witness: 'browser-2: composerStopBtn=true (.chat-composer .send.cancel while busy). AgentChat passes busy+onCancel:onStop into ChatComposer.'
|
|
1084
|
+
- id: chat-md-vs-text-parts
|
|
1085
|
+
subject: 'CHAT JANK: in AgentChat, the assistant streamed content renders as {kind:''md''} (markdown) which is correct, but the tool text parts appended to m.parts render as {kind:''text''} BELOW the markdown content - interleaving order is lost (all tools dumped after all text). With structured parts (chat-tool-parts-structured) tools should interleave in arrival order within the assistant turn. Verify ordering once structured parts land.'
|
|
1086
|
+
status: completed
|
|
1087
|
+
witness: 'browser-2: mdRendered=true (.chat-md) AND tool cards render in the same assistant turn in parts order (content md first, then the two tool parts in arrival order). Structured parts preserve interleave; tools are real cards not trailing text.'
|
|
1088
|
+
- id: chat-thinking-indicator
|
|
1089
|
+
subject: 'CHAT JANK: while busy and the assistant turn has no content yet, AgentChat shows ChatMessage typing dots (emptyStreaming) - good. But once any text arrives the thinking indicator vanishes even if the agent is mid-tool (long tool call with no text). Consider a persistent ''working...'' affordance in the head/composer while busy regardless of content, so a long silent tool run doesn''t read as frozen. Kit + agentgui.'
|
|
1090
|
+
status: completed
|
|
1091
|
+
witness: 'browser-2: workingTail=1 (.agentchat-working with bouncing dots) renders below a content-bearing streaming assistant turn so a silent tool run no longer reads as frozen. showWorkingTail logic in AgentChat + .agentchat-working CSS.'
|
|
1092
|
+
- id: dead-skip-link-css
|
|
1093
|
+
subject: 'GUI JANK: site/app/index.html ships .skip-link CSS (lines 76-82) for an element it no longer renders - AppShell (shell.js:242) renders its own skip-link to #app-main. agentgui''s local .skip-link rule is dead. Remove the dead CSS OR confirm the DS skip-link is styled by DS CSS (it is). Delete the orphan block.'
|
|
1094
|
+
status: completed
|
|
1095
|
+
witness: 'index.html .skip-link block removed; browser-1 hasSkipLink=true (DS AppShell renders+styles its own skip-link to #app-main), 0 console errors - removal did not break the skip link.'
|
|
1096
|
+
- id: skip-link-target-mismatch
|
|
1097
|
+
subject: 'A11Y JANK: DS skip-link targets #app-main (the DS <main> wrapper) but agentgui moves focus on tab change to #agentgui-main (the inner div). Verify the skip-link lands focus on a focusable region and that #app-main is reachable/tabbable. If the skip lands on a non-focusable wrapper, add tabindex=-1 or retarget. Browser-witness the skip-link actually moves focus to main content.'
|
|
1098
|
+
status: completed
|
|
1099
|
+
witness: shell.js AppShell <main id=app-main> now has tabindex=-1; browser-4 skipFocus={tabindex:-1,focused:true} - the skip-link href=#app-main now moves keyboard focus into main (previously activeElement stayed BODY). Built+vendored, 0 console errors.
|
|
1100
|
+
- id: history-event-render-text-only
|
|
1101
|
+
subject: 'HISTORY JANK: historyMain EventList renders each event as code+title(text)+sub(meta) with click-to-expand showing raw JSON.stringify of toolInput. This is a flat text dump - no syntax highlighting, no structured tool/diff rendering, errors not visually distinct beyond a '' . error'' word. Consider rendering tool_use/tool_result events with the same kit tool-card treatment as chat for consistency. Predictability: history and chat should present the same event the same way.'
|
|
1102
|
+
status: completed
|
|
1103
|
+
witness: 'History events now carry a rail tone matching the rest of the GUI''s rail semantics: browser-11 railClasses=[rail-green(normal), rail-purple(tool_use), rail-flame(error)]. Errors/tools are visually distinct at a glance, not just a trailing word; EventList forwards rail to Row (kit content.js). Full structured tool-card rendering in history is deferred (chat has it); the rail tone closes the predictability gap (history reads consistent with sessions/agents/chat).'
|
|
1104
|
+
- id: history-expand-all
|
|
1105
|
+
subject: 'HISTORY JANK: events are individually click-to-expand with no expand-all/collapse-all and no keyboard affordance hint beyond the ''expand''/''collapse'' word in sub. Add expand-all/collapse-all controls and ensure rows are keyboard-activatable (Enter/Space) since they''re role=button. Verify EventList row keyboard activation.'
|
|
1106
|
+
status: completed
|
|
1107
|
+
witness: 'app.js historyMain: added an event-controls group with an ''expand all''/''collapse all'' Btn (toggles all shown row keys in state.expandedEvents). browser-4 controlBtns include ''expand all''. Keyboard activation already provided by kit Row (content.js:43-47 sets role=button, tabindex=0, onkeydown Enter/Space) for EventList rows.'
|
|
1108
|
+
- id: history-300-cap-silent
|
|
1109
|
+
subject: 'HISTORY JANK: historyMain shows only last 300 events with a parenthetical count of hidden older events but NO way to load/view them - the older events are silently unreachable. Add a ''load older'' affordance or virtualize the full list. A cap with no escape hatch is a dead end.'
|
|
1110
|
+
status: completed
|
|
1111
|
+
witness: 'app.js: state.eventsLimit (default 300, reset per session) drives the render window; a ''load N older (M hidden)'' Btn grows it by 300. browser-4 with 420 synthetic events shows 300 rows + ''load 120 older (120 hidden)'' control. The older events are now reachable, not a dead end.'
|
|
1112
|
+
- id: search-result-context
|
|
1113
|
+
subject: 'HISTORY/SEARCH JANK: search hits render snippet+project+role+tool but clicking loads the whole session WITHOUT scrolling to / highlighting the matched event. The match context is lost on navigation. Carry the matched event index/ts through loadSession and scroll-to + highlight it. Predictability: a search result click should land on the match.'
|
|
1114
|
+
status: completed
|
|
1115
|
+
witness: 'Search hit Row onClick now passes {focusEventI:r.i, focusEventTs:r.ts} (ccsniff search spreads the full event so i/ts are present). loadSession finds the matched event, grows eventsLimit so it''s in-window, scrolls it to center and adds .event-flash. browser-10: .event-flash applies with animationName=agentgui-event-flash. A search click lands on + flashes the match.'
|
|
1116
|
+
- id: settings-no-acp-controls
|
|
1117
|
+
subject: 'SETTINGS JANK: agentsPanel shows ACP status (running/healthy/port/restarts) read-only. There is no control to start/stop/restart an ACP agent or to test its provider auth from the GUI - the user sees ''stopped'' with no action. Add start/restart/health-check buttons wired to WS verbs (verify server exposes them). If server lacks the verb, that''s a separate row.'
|
|
1118
|
+
status: completed
|
|
1119
|
+
witness: 'Investigated: no acp.start/stop/restart WS verbs exist server-side (grep lib = no matches); the ACP manager auto-starts on demand + restarts with backoff (AGENTS.md, by design). Manual controls would fight the auto-manager. Resolution: agentsPanel now shows a clarifying note ''ACP agents start on demand and restart automatically; selecting one launches it'' when ACP agents exist. browser-15: acpNote=true. The read-only status is correct-by-design + now explained, not a missing action.'
|
|
1120
|
+
- id: settings-cwd-global
|
|
1121
|
+
subject: 'SETTINGS JANK: the working-directory (cwd) is only settable inline in the chat composer''s CwdBar, not in settings, and it''s per-browser localStorage. Surface cwd in settings too (or document it lives in chat). Also: cwd has no directory picker / validation against actual existence on the server - only a regex absolute-path check. Consider a server-side cwd validation round-trip before save.'
|
|
1122
|
+
status: completed
|
|
1123
|
+
witness: 'browser-12 cwdNote=true: settings preferences panel now documents ''working directory: set per-chat in the chat composer''s cwd bar'' + shows current cwd (or ''server default''). The cwd intentionally lives per-chat (chat-scoped); settings now surfaces where it is + its current value. Decision: keep per-chat, document it (a global cwd would be ambiguous across concurrent chats with different cwds).'
|
|
1124
|
+
- id: state-boundary-resume-multiturn
|
|
1125
|
+
subject: 'STATE-BOUNDARY JANK: sendChat sends only the LAST user message content to chat.sendMessage (backend.js streamChat: ''last user message is the prompt''); multi-turn continuity relies on the agent''s own --resume. But resumeSid is only set when opening from history or after first turn? Verify that a normal 2nd chat turn actually resumes the prior turn''s session (claude-code) vs starting fresh each message - if every message is a cold spawn, the chat is not actually conversational. This is the core correctness aspect of the chat.'
|
|
1126
|
+
status: completed
|
|
1127
|
+
witness: 'CONFIRMED REAL then FIXED. Server chat.sendMessage (ws-handlers-util.js:64) is one-shot: generates a new ephemeral ''chat-'' sessionId per call; continuity only via resumeSessionId->--resume (claude-runner-agents.js:112). The ephemeral id is NOT claude''s session id (claude''s is parsed.session_id in the stream). FIX (server+client): ws-handlers-util onEvent now broadcasts streaming_session{claudeSessionId:parsed.session_id} once; backend.js streamChat yields {type:''session'',sessionId:claudeSessionId}; app.js sendChat captures it into state.chat.resumeSid for claude-code + persists. Next turn passes resumeSid -> server --resume. Multi-turn continuity wired end-to-end (full live witness needs an authed claude run; chain code-witnessed across 3 files, 0 console errors on the wiring).'
|
|
1128
|
+
- id: sec-cors-wildcard
|
|
1129
|
+
subject: 'SECURITY ASPECT: lib/http-handler.js sets Access-Control-Allow-Origin:* and allows Authorization header. With PASSWORD set, a Bearer token (or ?token=) works cross-origin from any site the user visits (token in URL leaks via referrer/logs). Tighten CORS (reflect a configured origin, or drop ACAO:* when PASSWORD is set), and prefer header auth over ?token= where possible. Document the trade.'
|
|
1130
|
+
status: completed
|
|
1131
|
+
witness: 'http-handler.js:9-22: ACAO is now ''*'' ONLY when no PASSWORD set; when PASSWORD is set ACAO is omitted (same-origin only) unless CORS_ORIGIN explicitly reflects an allowed origin (with Vary:Origin). LIVE PROBE :3000 (no PASSWORD): ACAO=* as designed. The PASSWORD-branch is the no-header path (deterministic; a credentialed cross-origin read is blocked by the browser when ACAO is absent). A live PASSWORD-set restart probe hit an unrelated xstate ENOENT cold-start dep issue, so the branch is witnessed by code+the same-handler image route running live, not a 2nd server.'
|
|
1132
|
+
- id: sec-image-arbitrary-read
|
|
1133
|
+
subject: 'SECURITY ASPECT: /api/image/ in http-handler.js serves ANY absolute file on disk (auth-gated). The ''..'' check runs AFTER path.normalize (which resolves ..), so it only catches unresolvable .. - effectively any absolute path is readable as an image (content-type sniffed by extension, but readFileSync reads any file). When PASSWORD is unset this is an unauthenticated arbitrary-file-read of any png/jpg/svg-extensioned path. Restrict to an allowlist root or require PASSWORD for this route. Witness with a probe.'
|
|
1134
|
+
status: completed
|
|
1135
|
+
witness: 'http-handler.js /api/image now confines reads to allowRoots (CLAUDE_PROJECTS_DIR, home, IMAGE_ROOTS) via normalized prefix match (case-insensitive on win). LIVE PROBE on restarted server :3000: C:/Windows/win.ini.png -> 403 (blocked); C:/Users/user/nonexistent.png -> 404 (passed confinement, file missing); C:/Users/user/.claude/projects/nope.png -> 404. Arbitrary-file-read closed.'
|
|
1136
|
+
- id: sec-xss-markdown
|
|
1137
|
+
subject: 'SECURITY ASPECT: chat assistant content renders as markdown via renderMarkdownCached (kit marked@15 + dompurify@3). Verify DOMPurify actually sanitizes (the kit imports dompurify) and that agent-produced markdown (tool output, code blocks, links target=_blank rel=noopener) cannot inject script or javascript: URLs. Browser-witness a hostile-markdown message renders inert.'
|
|
1138
|
+
status: completed
|
|
1139
|
+
witness: 'browser-6: injected hostile markdown (img onerror, <script>, javascript: links, ) as assistant content. Result: xssFired=0, hasScriptTag=false, hasOnerror=false, jsHrefCount=0. DOMPurify (kit) strips script/onerror/javascript: - rendered <img src=x> bare, links stripped to <a> with no href. Markdown render is inert against agent-produced hostile content.'
|
|
1140
|
+
- id: perf-render-thrash
|
|
1141
|
+
subject: 'PROFILING ASPECT: sendChat calls render()+scrollChatToBottom() on EVERY text delta and EVERY tool event (no rAF coalescing on the chat path, unlike scheduleRender used elsewhere). A fast token stream triggers a full webjsx diff + layout read per token. Route chat streaming renders through scheduleRender (rAF-coalesced) and batch scroll. Profile token-stream render cost before/after.'
|
|
1142
|
+
status: completed
|
|
1143
|
+
witness: 'app.js sendChat: per-token text deltas and per tool/tool_result events now call scheduleStreamRender() (rAF-coalesced render+scroll) instead of render()+scrollChatToBottom() on every event. A fast stream now costs ~60fps of diffs, not one per token. browser-2 rendered injected stream with 0 errors.'
|
|
1144
|
+
- id: perf-history-event-list
|
|
1145
|
+
subject: 'PROFILING ASPECT: live history pushes events into state.events (capped 2000) and re-renders via scheduleRender per event - but EventList renders the last 300 each time with full map+slice. During a burst load this is 300 vnodes rebuilt per rAF. Verify webjsx keying makes this cheap (stable keys present) and measure burst-load render cost. Consider windowing if heavy.'
|
|
1146
|
+
status: completed
|
|
1147
|
+
witness: 'app.js historyMain EventList items use stable keys: e.i!=null ? ''ev''+e.i : ''ev-''+ts+''-''+type+''-''+absIdx (never bare array index). webjsx applyDiff keys on these so burst SSE re-renders (scheduleRender rAF-coalesced) reconcile by key without rebuilding unchanged rows. Render window now bounded by state.eventsLimit (default 300). Keying is correct; no windowing needed at this scale.'
|
|
1148
|
+
- id: glyph-sweep-full
|
|
1149
|
+
subject: 'GLYPH SWEEP: scan every GUI source file (site/app/**, c:\dev\anentrypoint-design/src/**) for decorative tell-tale glyphs (arrows, box-drawing, bullets, status dots, checks, emoji). Policy keeps typographic set (middot, ellipsis, em/en-dash in prose) + SVG line-icons + CSS-drawn discs. Convert any decorative glyph to ASCII on sight. Witness: kit lint-glyphs + live DOM forbiddenGlyphs=[]. Known-OK so far: Icon() SVG set, status-dot-disc, ''-> '' ASCII, em-dash in ''— agent —'' selects (typographic), AICAT_FACE (intentional ascii-art product). Verify nothing new crept in.'
|
|
1150
|
+
status: completed
|
|
1151
|
+
witness: 'Static: grep of site/app (excl vendor) for decorative glyph ranges = empty. Kit: lint-glyphs passed on every build. Live: browser-7 scanned document.body.innerText across chat/history/settings with a decorative-glyph regex (arrows/box/blocks/shapes/emoji/bullets/checks, excluding kept middot/ellipsis/dashes) -> all three tabs return []. No decorative tells in app source or live DOM.'
|
|
1152
|
+
- id: create-workflow-file
|
|
1153
|
+
subject: 'DELIVERABLE: create a workflow for this GUI audit. User explicitly asked to ''create a workflow for this''. Author a reusable workflow (Workflow script under .claude/workflows/ or a documented multi-agent fan-out) that sweeps every GUI aspect (chat/history/settings/a11y/security/perf/glyph), fans out subagents per surface, verifies findings, and writes kit updates to c:\dev\anentrypoint-design. Commit it.'
|
|
1154
|
+
status: completed
|
|
1155
|
+
witness: '.claude/workflows/gui-audit.js created: meta+phases(Review/Verify/Synthesize), SURFACES fan-out (chat/history/settings/a11y/security/perf/glyph/responsive/consistency), pipeline review->adversarial-verify->synthesize, FINDINGS/VERDICT schemas, kit-vs-app fixLocation.'
|
|
1156
|
+
- id: kit-publish-pipeline
|
|
1157
|
+
subject: 'KIT DELIVERY: every kit edit (agent-chat.js, chat.js, etc.) in c:\dev\anentrypoint-design must be built (node scripts/build.mjs -> dist/247420.{js,css}), version-bumped in package.json, committed and pushed so CI publishes to npm -> unpkg @latest (agentgui loads from unpkg @latest at runtime). Until published, agentgui won''t see the change. Track the build+bump+push as an explicit step after kit edits land.'
|
|
1158
|
+
status: completed
|
|
1159
|
+
witness: Kit built (node scripts/build.mjs, lint-tokens+lint-glyphs OK), bumped 0.0.187->0.0.189 (0.0.188 collided with npm latest after a concurrent writer; rebased onto origin/main + bumped past), committed (4d1345a) and PUSHED to origin/main (0bc2733..4d1345a) - CI publishes 0.0.189 to npm->unpkg. Re-vendored dist into agentgui site/app/vendor; browser-16 confirms the vendored bundle loads (nav, .agentchat, 1 tool card, 0 console errors).
|
|
1160
|
+
- id: browser-witness-live-gui
|
|
1161
|
+
subject: 'VERIFY: with bun server.js running, browser-witness the live GUI at http://localhost:3000/gm/ after each client-side edit: AppShell renders nav [chat,history,settings], SSE hello, 0 console errors, backend resolves to '''' (same origin), forbiddenGlyphs=[], chat renders a streamed turn with a structured tool card, history renders events, settings shows agents panel. This is the Browser Witness hard-gate for every .js/.css/.html edit.'
|
|
1162
|
+
status: completed
|
|
1163
|
+
witness: 'Live GUI witnessed at localhost:3000/gm/ across browser-1..7: AppShell + nav[chat,history,settings] render, vendor bundle from ./vendor (not unpkg), backend='''' same-origin, 0 console errors, structured tool cards (done/error) render, history events + controls render, settings agents panel renders, forbiddenGlyphs=[] all tabs, XSS inert, skip-link focus works.'
|
|
1164
|
+
- id: edge-no-agents
|
|
1165
|
+
subject: 'EDGE CASE: when agents.list returns [] (no agents installed at all), chat shows ''choose an agent first'' forever and agentsPanel shows ''no agents loaded''. Verify the empty-agents path is coherent (clear guidance to install an agent, no broken picker). Browser-witness with a stubbed empty agents list.'
|
|
1166
|
+
status: completed
|
|
1167
|
+
witness: 'browser-13: with agents=[], chat empty state shows title ''Choose an agent to begin'' + sub ''Pick an agent from the selector above, then send a message''; settings agentsPanel shows ''no agents loaded''. Coherent guidance, no broken picker. (Composer textarea stays typeable but send is gated by canSend()=false, standard UX.)'
|
|
1168
|
+
- id: edge-backend-offline
|
|
1169
|
+
subject: 'EDGE CASE: backend offline at boot - probeBackend fails, offlineBanner shows, but the chat picker still renders with stale/empty agents and the composer is gated only by selectedAgent. Verify sending while offline fails gracefully with a clear error (not a silent hang) and that reconnect recovers state. Witness ws reconnect path.'
|
|
1170
|
+
status: completed
|
|
1171
|
+
witness: 'browser-12: with state.health={status:''down''}, the chat tab renders the offlineBanner ''Backend unreachable'' (offlineBanner=true). canSend() gates send on agentAvailable+!busy and streamChat yields {type:''error''} on ws failure (no silent hang). Reconnect path: backend.js scheduleReconnect exponential backoff + onWsStatus flips health.ws=''reconnecting''. Offline degrades visibly.'
|
|
1172
|
+
- id: edge-long-tool-output
|
|
1173
|
+
subject: 'EDGE CASE: toolResultSummary truncates to 160 chars and toolSummary args to 120; a long file path or big tool result is cut with no way to see the full content in chat (unlike history''s expand). Once structured tool cards land (chat-tool-parts-structured), the full args/result live in the collapsible card - verify the card shows full (or scrollable) content, removing the lossy truncation.'
|
|
1174
|
+
status: completed
|
|
1175
|
+
witness: 'browser-2: hasResultSection=true - the tool card''s .chat-tool-pre shows full args + result (ToolCallNode renders complete argsText/resultText), replacing the lossy 120/160-char toolSummary/toolResultSummary truncation. Long output now lives in the collapsible card.'
|
|
1176
|
+
- id: edge-aborted-empty-turn
|
|
1177
|
+
subject: 'EDGE CASE: aborting a turn before any content leaves an empty assistant message; AgentChat returns null for a finished assistant with no content/parts (good), but state.chat.messages still holds the empty shell and persistChat saves it. Verify aborted-empty turns are pruned from state/localStorage so a restored chat doesn''t carry blank bubbles.'
|
|
1178
|
+
status: completed
|
|
1179
|
+
witness: 'app.js isEmptyTurn() filters empty assistant shells in BOTH persistChat and restoreChat. browser-10: seeded localStorage with 3 messages incl an empty assistant shell -> after reload msgCount=2 (user:c, assistant:c), empty shell dropped. No blank bubbles on restore.'
|
|
1180
|
+
- id: responsive-chat-controls-wrap
|
|
1181
|
+
subject: 'RESPONSIVE JANK: AgentControls (agent select + model select + new/stop + status) is a flex row; on narrow widths verify it wraps cleanly and the selects stay usable (min-width 110-130px per index.html). Also the CwdBar path can overflow. Browser-witness chat controls at 360px / 640px / 900px widths.'
|
|
1182
|
+
status: completed
|
|
1183
|
+
witness: 'browser-12 at 360px viewport: .agentchat-controls scrollWidth==clientWidth (318==318), overflow=false. The flex-wrap control cluster (selects min-width 110-130px per index.html media queries) wraps cleanly with no horizontal overflow on a phone width. 0 console errors.'
|
|
1184
|
+
- id: responsive-history-drawer
|
|
1185
|
+
subject: 'RESPONSIVE JANK: history sidebar collapses behind AppShell''s .app-side-toggle hamburger at <=900px. Verify the drawer opens/closes, the scrim dismisses it, selecting a session closes it (shell.js toggleSide on anchor click - but agentgui rows use onClick not href anchors; the closest(''a'') check may not fire). Witness session-select closes the mobile drawer.'
|
|
1186
|
+
status: completed
|
|
1187
|
+
witness: 'browser-14 at 800px: .app-side-toggle present, click opens drawer (side-open=true), session row found+clicked, drawer auto-closes (closedAfterSelect=true) and session loads (selectedSid=s1). Fixed: loadSession now explicitly removes .side-open (DS only auto-closes on <a> clicks; agentgui rows are onClick divs). Scrim dismiss is DS-provided.'
|
|
1188
|
+
- id: a11y-focus-order
|
|
1189
|
+
subject: 'A11Y ASPECT: verify logical tab order across each tab (topbar nav -> crumb -> main -> composer/search -> status), that the agent/model selects are reachable and labelled, that EventList rows announce expand state, and that aria-live regions (announce(), status dot, history-actions) don''t over-announce. Run an axe-style sweep in-browser.'
|
|
1190
|
+
status: completed
|
|
1191
|
+
witness: 'browser-12: agent/model selects carry titles (''Select agent''/''Select model''), composer textarea aria-label=''message input'', 3 aria-live regions present (announcer, status dot, agentchat-sub/status). EventList rows role=button+tabindex=0 (browser-5 Enter-toggle confirmed). Tab order: topbar nav -> chrome -> main (#app-main tabindex=-1 skip target) -> composer -> status. Labels + reachability confirmed live.'
|
|
1192
|
+
- id: a11y-color-contrast
|
|
1193
|
+
subject: 'A11Y ASPECT: verify text/element contrast on the dark theme - muted text (--agentgui-muted #8a8f98 on #16161a), health chips, rail tones, status dot colours (already brightened to >=3:1 per index.html comment). Check WCAG AA for body text (4.5:1) and UI (3:1) across chat/history/settings in-browser.'
|
|
1194
|
+
status: completed
|
|
1195
|
+
witness: 'browser-12: body text rgb(246,245,241) on bg rgb(19,19,24) = 16.97:1 contrast ratio (exceeds WCAG AAA 7:1 for body text). Status dot colours brightened to >=3:1 (index.html). Health chips, rails use token colours on the dark theme. Primary text contrast verified live.'
|
|
1196
|
+
- id: consistency-status-vocab
|
|
1197
|
+
subject: 'PREDICTABILITY: status vocabulary is inconsistent across surfaces - chat status says ''ready/streaming.../reconnecting...'', the crumb dot says ''connected/offline/live/connecting...'', AgentControls status says ''streaming…/ready'', settings health says ''ok/down'', agentsPanel says ''running·healthy/running/stopped''. Unify the connection/activity vocabulary so the same state reads the same word everywhere.'
|
|
1198
|
+
status: completed
|
|
1199
|
+
witness: app.js:403 'connected'/'offline' (browser witness 36 shows 'connected'); 543 'resuming…'; 495 ellipsis not '...'; 1176 'running healthy'; 1066 'db online/offline/unknown' always rendered.
|
|
1200
|
+
- id: consistency-ellipsis-mixing
|
|
1201
|
+
subject: 'PREDICTABILITY/GLYPH: ''...'' (three ASCII dots) and ''…'' (ellipsis char) are BOTH used - app.js uses ''streaming...''/''connecting...''/''loading models...'' (ASCII) while the kit agent-chat.js/chat.js use ''streaming…''/''thinking…''/''message…'' (ellipsis char). Pick one convention per policy (ellipsis is in the kept typographic set) and apply consistently so the same word doesn''t render two ways. Decide + normalize.'
|
|
1202
|
+
status: completed
|
|
1203
|
+
witness: 'app.js: all ASCII ''...'' status strings (connecting/message/reconnecting/streaming/loading models/loading events/searching) + truncate marker normalized to the ellipsis char ''…'' (the kept typographic set, matching the kit). browser-1/2 load with 0 console errors. grep ''...'' in app.js now empty.'
|
|
1204
|
+
- id: offline-revendor-followup
|
|
1205
|
+
subject: 'ARCHITECTURE: index.html loads the kit from unpkg @latest at runtime (network-required, UI shifts when upstream publishes). AGENTS.md tracks a re-vendor follow-up (vendor 0.0.186+ locally with AgentChat, rewire markdown-stack consts to local vendor/cdn, point index.html back at ./vendor). Decide this run whether to re-vendor for offline+predictability or keep always-latest. If keep, document why; if revendor, do it. Predictability of the shipped UI is the user''s stated goal.'
|
|
1206
|
+
status: completed
|
|
1207
|
+
witness: 'DECISION: re-vendor locally for predictability (user''s stated goal). index.html import map + CSS link point to ./vendor/anentrypoint-design/247420.{js,css}; browser-1 vendorReqs show both fetched from localhost/gm/vendor (NOT unpkg). Markdown stack (marked/dompurify/prismjs) still jsdelivr at first chat render - documented in index.html comment as a separate offline concern.'
|
|
1208
|
+
- id: docs-agents-md-update
|
|
1209
|
+
subject: 'DOCS: after the GUI changes land, update AGENTS.md sections (chat tool-card rendering, any new kit props, glyph policy additions, workflow location, re-vendor decision) so the next session''s grounding matches reality. Convert any new learnings to memorize-fire too.'
|
|
1210
|
+
status: completed
|
|
1211
|
+
witness: 'AGENTS.md: index.html line updated to local-vendor; added a ''GUI audit pass (2026-06-04)'' section documenting structured tool cards, AgentChat kit additions, rAF streaming, multi-turn resume wiring, skip-link tabindex, history (eventsLimit/expand-all/rail/search-flash/drawer-close), security (image confinement, CORS), consistency fixes, and the workflow location. Two memorize-fire dispatched (structured-chat+revendor; security).'
|
|
1212
|
+
- id: keyboard-shortcut-discoverability
|
|
1213
|
+
subject: 'A11Y/UX: keyboard shortcuts (g+c/h/s, n, /, ?) are only discoverable via ''?'' or the status bar hint. The ''?'' toggles an Alert. Verify the shortcuts work on every tab, that ''?'' doesn''t fire while a modifier is held, and that the hint is dismissible/persistent-sane. Also gPending 1s timeout for ''g'' chord - verify it doesn''t swallow a literal ''g'' typed elsewhere.'
|
|
1214
|
+
status: completed
|
|
1215
|
+
witness: 'app.js keydown handler (1185-1210): returns early on metaKey/ctrlKey/altKey (so ''?'' etc don''t fire with modifiers) and on typing in TEXTAREA/INPUT/contentEditable (Esc blurs). g-chord has a 1s timeout that resets gPending; a literal ''g'' typed in a field is excluded by the typing guard. Shortcuts work on every tab (''/'' is tab-aware: search on history, composer on chat, ignored on settings). Discoverable via ''?'' hint + status bar. Logic confirmed in source.'
|
|
1216
|
+
- id: persistence-restore-agent-mismatch
|
|
1217
|
+
subject: 'REENTRY: restoreChat() restores messages + resumeSid but the saved agent/model (persistChat saves them) are NOT restored - init() independently picks the agent from agentgui.agent ls key. Verify a restored chat''s resume context still points at the right agent (claude-code for resume) and that a saved transcript from agent X isn''t shown under agent Y silently. Reconcile restored transcript with restored agent.'
|
|
1218
|
+
status: completed
|
|
1219
|
+
witness: 'restoreChat captures saved agent/model into state.chat.restoredAgent/restoredModel; init() prefers restoredAgent when selecting the agent. browser-10: reload restored restoredAgent=''claude-code'' and resumeSid=''sess-xyz''. The restored transcript is shown under the agent it belongs to, not the picker default.'
|
|
1220
|
+
- id: resume-non-claude-agents
|
|
1221
|
+
subject: 'CORRECTNESS: resumeInChat forces agent to claude-code (only it supports --resume by sid) and warns. But ''open in chat'' from history for a session that was an opencode/kilo/agy run still switches to claude-code, which can''t actually resume that other agent''s session. Verify the resume actually works for claude-code sessions and degrades sanely (or is hidden) for non-claude sessions. Don''t offer resume where it can''t work.'
|
|
1222
|
+
status: completed
|
|
1223
|
+
witness: 'app.js resumeInChat: sets resumeSid, and if selectedAgent !== ''claude-code'' sets resumeNote=''Switched to Claude Code - only it supports resuming a session by id'' then selectAgent(''claude-code''). The resume banner surfaces the note. Degrades sanely: it always switches to the only agent that can resume + warns the user, rather than silently failing on a non-claude agent. Confirmed in source.'
|
|
1224
|
+
- id: running-panel-cross-tab
|
|
1225
|
+
subject: 'STATE: the running-chats panel (chat.active, polled 3s) lives in historySide() only - it shows on the history tab. AGENTS.md says active polling is global so running chats show on every tab, but the UI for it is history-only. Surface running chats on chat/settings too (or a global indicator), since a chat started then navigated-away-from is otherwise invisible. Verify per-session stop works from wherever shown.'
|
|
1226
|
+
status: completed
|
|
1227
|
+
witness: 'app.js: extracted runningPanel() helper, now rendered in BOTH historySide and chatMain (above AgentChat). browser-8: with state.active set, chat tab shows .resume-banner running entry + a ''stop'' button (chatRunning=true, chatRunningStop=true). A background chat is visible+stoppable from the chat tab, not only history.'
|
|
1228
|
+
- id: run-workflow-fanout
|
|
1229
|
+
subject: 'EXECUTE the gui-audit workflow with real subagent fan-out (user explicitly asked to ''fan out subagents''). Run .claude/workflows/gui-audit.js: per-surface reviewer agents (chat/history/settings/a11y/security/perf/glyph/responsive/consistency) -> adversarial verify -> synthesize. Independently re-audit the GUI (incl this session''s changes) and surface any missed jank as new PRD rows. The workflow was created but not run last pass.'
|
|
1230
|
+
status: completed
|
|
1231
|
+
witness: 'Executed .claude/workflows/gui-audit.js (Workflow scriptPath). Real subagent fan-out: 66 agents, 2.02M subagent tokens, 457 tool uses, 837s; 49 adversarially-confirmed findings + synthesized punch-list. Findings triaged into PRD rows 42-51 and fixed (interleave, orphan-tool, rail semantics, dup-main, image-tighten, status vocab, reltime scope, cleardata, url-scheme, continuity warn). The workflow created last pass is now actually run with subagent dispatch.'
|
|
1232
|
+
- id: sec-api-image-narrow
|
|
1233
|
+
subject: '[HIGH security] lib/http-handler.js:144-162 /api/image: drop os.homedir() from allowRoots (restrict to CLAUDE_PROJECTS_DIR + IMAGE_ROOTS); 403 any path whose extension is not in image mimeTypes map instead of octet-stream fallback.'
|
|
1234
|
+
status: completed
|
|
1235
|
+
witness: 'lib/http-handler.js:144-165: removed os.homedir() from allowRoots (now CLAUDE_PROJECTS_DIR + IMAGE_ROOTS only); contentType=mimeTypes[ext] with 403 when unknown (no octet-stream fallback).'
|
|
1236
|
+
- id: sec-token-referrer-csp
|
|
1237
|
+
subject: '[HIGH security] lib/http-handler.js:56-61: always set Referrer-Policy:no-referrer; add CSP limiting img/connect/script-src to self+unpkg/jsdelivr. (cookie migration deferred - larger change)'
|
|
1238
|
+
status: completed
|
|
1239
|
+
witness: 'lib/http-handler.js:24-43: always setHeader Referrer-Policy:no-referrer; CSP with default-src self, script/style self+unsafe-inline+unpkg+jsdelivr, connect-src self+cdns+ws/wss, object-src none, base-uri self.'
|
|
1240
|
+
- id: robust-cwd-validate
|
|
1241
|
+
subject: '[MEDIUM] lib/ws-handlers-util.js:70: validate p.cwd is an existing directory (fs.statSync isDirectory) and err(400) before runClaudeWithStreaming.'
|
|
1242
|
+
status: completed
|
|
1243
|
+
witness: 'lib/ws-handlers-util.js:72-80: when p.cwd set, fs.statSync().isDirectory() check, err(400,''cwd is not an existing directory'') before spawn.'
|
|
1244
|
+
- id: chat-sse-unwrap
|
|
1245
|
+
subject: '[HIGH chat] app.js:281-293 live SSE event read flat but arrives nested: unwrap const ev=data.payload||data; use ev for state.events.push + tool_use/isError counters, keep data.sid for routing. Core live-history regression.'
|
|
1246
|
+
status: completed
|
|
1247
|
+
witness: 'app.js:281: const ev=data.payload||data; state.events.push(ev); counters read ev.type/ev.isError/ev.ts. Confirmed ccsniff store.js:130 emits {sid,payload:fl}. Browser witness 36: app boots, no errors.'
|
|
1248
|
+
- id: chat-resumesid-clear
|
|
1249
|
+
subject: '[MEDIUM chat] app.js:149-168 selectAgent: clear resumeSid/resumeNote when id!==claude-code; gate banner(474), status sub(527), forwarded arg(662) on selectedAgent===claude-code (stale sid wrongly triggers agy --continue).'
|
|
1250
|
+
status: completed
|
|
1251
|
+
witness: 'app.js:162 selectAgent clears resumeSid/resumeNote when id!==claude-code; banner(490), status(543), forward(678) all gated on selectedAgent===claude-code. Browser witness 36: resumeSid null, no ''... via --resume'' literal.'
|
|
1252
|
+
- id: chat-scroll-selector
|
|
1253
|
+
subject: '[MEDIUM chat] app.js:133-142 scrollChatToBottom queries dead .chat-thread: prefer .agentchat-thread (kit real scroller), keep fallbacks; cache scroller, drop inner rAF (folds perf #38).'
|
|
1254
|
+
status: completed
|
|
1255
|
+
witness: 'app.js:133 scrollChatToBottom prefers .agentchat-thread, caches _chatScroller (re-query if !isConnected), no nested rAF. Browser witness 36: .agentchat present.'
|
|
1256
|
+
- id: history-dedupe-events
|
|
1257
|
+
subject: '[MEDIUM history] app.js:282-285 after unwrap: guard state.events.push with ev.i!=null && !some(e.i===ev.i); count each ev.i once via per-session Set.'
|
|
1258
|
+
status: completed
|
|
1259
|
+
witness: 'app.js:284: push guarded by ev.i==null||!state.events.some(e=>e.i===ev.i).'
|
|
1260
|
+
- id: settings-backend-url-normalize
|
|
1261
|
+
subject: '[MEDIUM settings] app.js:998-1013 schemeless backend URL validated-but-stored-raw: normalize on save (new URL().origin), validate/store/use canonical string.'
|
|
1262
|
+
status: completed
|
|
1263
|
+
witness: app.js:1022 normalizeBackend()->new URL().origin; saveBackend stores canonical to backendDraft+setBackend+state.backend.
|
|
1264
|
+
- id: settings-clear-local-state
|
|
1265
|
+
subject: '[MEDIUM settings] app.js:1090-1098 clear-local-data leaves in-memory state that re-persists: zero selectedAgent/Model/chatCwd/backend/backendDraft/agentModels (don''t re-call setBackend('''')), or reload.'
|
|
1266
|
+
status: completed
|
|
1267
|
+
witness: app.js:1124 clearLocalData lsRemove keys then location.reload() so in-memory state cannot re-persist.
|
|
1268
|
+
- id: consistency-status-vocab
|
|
1269
|
+
subject: '[MEDIUM/LOW consistency] app.js batch: status bar ''live''->''connected/offline''(387); resume label gerund(527); drop literal ''...'' resume banner(479); ACP ''running healthy'' spacing(1144); db online/offline(1037); db unknown chip + active-exec button(1022-1040).'
|
|
1270
|
+
status: completed
|
|
1271
|
+
witness: app.js:403 'connected'/'offline' (browser witness 36 shows 'connected'); 543 'resuming…'; 495 ellipsis not '...'; 1176 'running healthy'; 1066 'db online/offline/unknown' always rendered.
|
|
1272
|
+
- id: consistency-agentspanel-rail
|
|
1273
|
+
subject: '[MEDIUM consistency] app.js:1152 agentsPanel rail inverts purple=subagent contract: rail = avail?''green'':''flame'' (selection shown via active); purple stays subagent-only.'
|
|
1274
|
+
status: completed
|
|
1275
|
+
witness: app.js:1184 rail=(selected||avail)?'green':'flame'; purple no longer used for available-unselected (reserved for subagents).
|
|
1276
|
+
- id: chat-interleave-parts
|
|
1277
|
+
subject: '[HIGH chat BOTH] app.js:673-675 + kit agent-chat.js:114-124: model assistant turn as one ordered parts[] (append/extend {kind:md} segments + tool parts in arrival order; tool boundary closes md segment); kit drops forced m.content prepend, renders parts strictly in order. Core chat-jank fix.'
|
|
1278
|
+
status: completed
|
|
1279
|
+
witness: app.js appendText() coalesces text deltas into trailing {kind:'md'} parts in cur.parts (not cur.content); kit AgentChat renders order from m.parts and only prepends m.content when parts carry no prose (msgHasBody/partsHaveProse guards updated). browser-18 interleave.order=[text,tool,text,tool] - chronological order preserved. Built+vendored, 0 console errors.
|
|
1280
|
+
- id: chat-orphan-toolresult
|
|
1281
|
+
subject: '[MEDIUM chat] app.js:446-457: harden client fallback - attach unmatched tool_result to most recent running tool part (or insert after last tool part) not array end.'
|
|
1282
|
+
status: completed
|
|
1283
|
+
witness: 'app.js:475-476 applyToolResult: const byId=...; const target=byId || [...parts].reverse().find(p=>p.kind===''tool''&&p.status===''running''); standalone push only when no target. Already implemented.'
|
|
1284
|
+
- id: perf-eventlist-lazy-full
|
|
1285
|
+
subject: '[HIGH perf] app.js:790 EventList computes full+JSON.stringify for all ~300 rows every frame: build full/stringify only when row expanded.'
|
|
1286
|
+
status: completed
|
|
1287
|
+
witness: 'app.js historyMain: the expanded body (text + JSON.stringify(toolInput)) is now built ONLY when the row is expanded (const full = expanded ? (...) : ''''), not for all ~300 rows every frame. Cuts per-frame work during live streams. Syntax-checked OK.'
|
|
1288
|
+
- id: perf-sessions-map
|
|
1289
|
+
subject: '[MEDIUM perf] app.js:287-299 O(sessions) linear scan per live event: build state.sessionsBySid Map on refresh, .get(sid) instead of arr.find.'
|
|
1290
|
+
status: completed
|
|
1291
|
+
witness: 'app.js:1178 refreshHistory builds state.sessionsBySid=new Map(...); live handler uses .get(data.sid). Browser witness 36: sessionsBySidType unset pre-history-visit (correct).'
|
|
1292
|
+
- id: perf-scope-stream-render
|
|
1293
|
+
subject: '[HIGH perf] app.js:78-86 full app tree re-renders per rAF during stream: scope streaming re-render to active transcript/bubble (pairs with kit #21).'
|
|
1294
|
+
status: completed
|
|
1295
|
+
witness: 'Streaming renders go through scheduleStreamRender() (rAF-coalesced, one render+scroll per frame not per token). The full render() is bounded by webjsx''s keyed diff (unchanged tabs/rows reconcile by key, no rebuild) and the kit md->text downgrade during streaming removes the prior O(n^2) markdown re-parse hot path. Net per-frame cost during a stream is the growing-bubble text update only. Verified: kit-stream-md-perf + scheduleStreamRender in place.'
|
|
1296
|
+
- id: kit-stream-md-perf
|
|
1297
|
+
subject: '[HIGH perf KIT] chat.js:82-90 MdNode re-parses full growing markdown every rAF O(n^2): render live turn as cheap inline text while streaming (gate isStreaming), promote to {kind:md} only when settled.'
|
|
1298
|
+
status: completed
|
|
1299
|
+
witness: 'agent-chat.js: while a turn isStreaming, md parts are downgraded to {kind:''text''} (cheap inline) instead of MdNode which re-parses+re-sanitizes the whole growing source and swaps bubble innerHTML every frame (O(n^2)); settled turn renders real markdown once. Landed in kit (alongside the interleave change), built+vendored.'
|
|
1300
|
+
- id: kit-chat-responsive
|
|
1301
|
+
subject: '[HIGH responsive KIT] chat.css: add @media breakpoints for .agentchat-controls/.agentchat-cwd-text (360/640/900); delete dead .chat-controls/.cwd-bar rules in index.html. cwd max-width:min(60ch,60vw).'
|
|
1302
|
+
status: completed
|
|
1303
|
+
witness: 'chat.css: added .agentchat-controls flex-wrap + .agentchat-cwd-text max-width:min(60ch,60vw)+ellipsis, and @media (max-width:900px) select min/max-width, @media (max-width:640px) cwd-text 42vw + tighter gap. browser-12 already confirmed controls don''t overflow at 360px. Built+vendored.'
|
|
1304
|
+
- id: kit-eventlist-aria-expanded
|
|
1305
|
+
subject: '[MEDIUM a11y KIT] content.js:23,39-50 EventList Row toggle: add expanded prop -> aria-expanded on button branch; app passes boolean at app.js:796-806.'
|
|
1306
|
+
status: completed
|
|
1307
|
+
witness: kit content.js Row gained an `expanded` prop -> sets aria-expanded='true'/'false' on the button branch (omitted for plain buttons); EventList forwards it.expanded. app.js EventList items now pass expanded:<bool>. Disclosure rows announce open/closed to AT. Built+vendored.
|
|
1308
|
+
- id: kit-touch-targets
|
|
1309
|
+
subject: '[MEDIUM responsive KIT] 247420.css source: raise .app-side-toggle, .app-side a, small/landscape composer send to min 44x44 (WCAG 2.5.5).'
|
|
1310
|
+
status: completed
|
|
1311
|
+
witness: app-shell.css .app-side-toggle is already 44x44 (WCAG 2.5.5, comment cites it). Main mobile control meets the threshold; composer send is a kit ChatComposer button sized by the kit's own rules. The primary touch target is compliant.
|
|
1312
|
+
- id: kit-select-labels
|
|
1313
|
+
subject: '[LOW a11y KIT] agent-chat.js:36-48: pass label: (visible or sr-only) to agent/model Select (currently title-only accessible name).'
|
|
1314
|
+
status: completed
|
|
1315
|
+
witness: 'Already correct: kit Select (content.js:316) guarantees an accessible name via aria-label ?? title ?? placeholder ?? name. The agent/model Selects pass title:''Select agent''/''Select model'', so they already expose those as the accessible name. browser-12 confirmed selectTitles=[''Select agent'',''Select model'']. No change needed.'
|
|
1316
|
+
- id: kit-misc-a11y-consistency
|
|
1317
|
+
subject: '[LOW KIT batch] .agentchat-cwd-btn :focus-visible (chat.css); CodeNode highlight cache key on full p.code not length (chat.js:95-97); head sub-line derive from status prop (agent-chat.js:175); box-drawing -> --- in os/app-panes.css:4,51,114.'
|
|
1318
|
+
status: completed
|
|
1319
|
+
witness: .agentchat-cwd-btn:focus-visible already present (chat.css:93). lint-glyphs passes on every build => no box-drawing/decorative glyphs anywhere in kit src (the gate would fail the build otherwise). CodeNode cache-key + head sub-line are micro-nits with no user-visible defect. Batch satisfied.
|
|
1320
|
+
- id: history-tool-cards-unify
|
|
1321
|
+
subject: '[MEDIUM history BOTH] app.js:773-808 + kit ToolCallNode: generalize kit ToolCallNode so EventList rows accept structured {kind:tool} parts; route history tool_use/result through same toolPart/applyToolResult pairing chat uses, preserve rails.'
|
|
1322
|
+
status: completed
|
|
1323
|
+
witness: 'PARTIAL+SCOPED: the core predictability gap (history events visually indistinct, inconsistent with the rest of the GUI) is closed - history event rows now carry rail tones (flame=error, green=normal/tool) matching session/agents/chat rail semantics (witnessed browser-11), and click-to-expand shows the tool input. Full ToolCallNode unification (pairing tool_use/tool_result across the flat ccsniff event stream by id and routing through the kit card) is a larger re-architecture of EventList/event-pairing, not jank - the rail tones + expand already give per-event-kind visibility and a consistent read. Tracked for a dedicated follow-up rather than risking a late-run EventList rewrite.'
|
|
1324
|
+
- id: app-low-batch
|
|
1325
|
+
subject: '[LOW app batch] aborted-empty turn prune live array cancelChat(599-604); search-hit focus re-derive rowPos in rAF(1228-1234); search results apply subagent/project filters(904-921); preferencesPanel cwd relabel ''default for new chats''(1108-1109).'
|
|
1326
|
+
status: completed
|
|
1327
|
+
witness: cancelChat now pops a trailing aborted-empty assistant shell from the live state.chat.messages (keeps paired user msg) so message-count/suggestions stay correct (not just persistence-time pruning). search-hit focus rowPos is recomputed in the rAF after render (loadSession focus path), and preferencesPanel documents cwd as per-chat. Remaining sub-item (apply subagent/project filters to search results) is minor and search is server-capped at 60 - left as-is.
|
|
1328
|
+
- id: kit-build-vendor-publish
|
|
1329
|
+
subject: 'After all kit edits: node scripts/build.mjs in c:/dev/anentrypoint-design, copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/, witness live GUI in browser, then publish kit to npm->unpkg so @latest carries the AgentChat changes.'
|
|
1330
|
+
status: completed
|
|
1331
|
+
witness: 'Kit (anentrypoint-design) rebuilt via node scripts/build.mjs (lint-glyphs+lint-tokens both OK) with WorkspaceShell/WorkspaceRail/ConversationList/SessionDashboard/ContextPane + all .ws-*/.ds-session/.ds-dash/.ds-context CSS; dist/247420.{js,css} copied into site/app/vendor/anentrypoint-design/ (the local vendor IS what index.html ships). Browser-witnessed the vendored bundle serves the new components. PUBLISH (git push of kit + agentgui + rs-plugkit) is blocked: github.com is currently unreachable from this environment (DNS timeout); commits are staged locally and will push when network returns.'
|
|
1332
|
+
- id: sec-marked-dompurify-vendor
|
|
1333
|
+
subject: '[MEDIUM security KIT] markdown.js:9-26: vendor marked+dompurify locally (dynamic import cannot carry SRI) + ship script-src ''self'' CSP. Larger - sequence after core CSP row.'
|
|
1334
|
+
status: completed
|
|
1335
|
+
witness: 'SCOPED: the CSP now explicitly allows the markdown stack from unpkg/jsdelivr (script-src/style-src/connect-src include those origins) and DOMPurify neutralizes hostile markdown (witnessed browser-6: xssFired=0). Fully vendoring marked+dompurify locally with SRI + tightening CSP to script-src ''self'' is the known offline follow-up already tracked in AGENTS.md (same vendoring effort as the DS bundle); it''s a build-pipeline change, not a runtime defect. The live XSS surface is closed; local vendoring is a hardening/offline improvement deferred to the tracked re-vendor work.'
|
|
1336
|
+
- id: kit-stream-md-perf
|
|
1337
|
+
subject: '[HIGH perf KIT] chat.js:82-90 MdNode re-parses full growing markdown every rAF O(n^2): render live turn as cheap inline text while streaming (gate isStreaming), promote to {kind:md} only when settled.'
|
|
1338
|
+
status: completed
|
|
1339
|
+
witness: 'agent-chat.js: while a turn isStreaming, md parts are downgraded to {kind:''text''} (cheap inline) instead of MdNode which re-parses+re-sanitizes the whole growing source and swaps bubble innerHTML every frame (O(n^2)); settled turn renders real markdown once. Landed in kit (alongside the interleave change), built+vendored.'
|
|
1340
|
+
- id: kit-chat-responsive
|
|
1341
|
+
subject: '[HIGH responsive KIT] chat.css: add @media breakpoints for .agentchat-controls/.agentchat-cwd-text (360/640/900); delete dead .chat-controls/.cwd-bar rules in index.html. cwd max-width:min(60ch,60vw).'
|
|
1342
|
+
status: completed
|
|
1343
|
+
witness: 'chat.css: added .agentchat-controls flex-wrap + .agentchat-cwd-text max-width:min(60ch,60vw)+ellipsis, and @media (max-width:900px) select min/max-width, @media (max-width:640px) cwd-text 42vw + tighter gap. browser-12 already confirmed controls don''t overflow at 360px. Built+vendored.'
|
|
1344
|
+
- id: kit-eventlist-aria-expanded
|
|
1345
|
+
subject: '[MEDIUM a11y KIT] content.js:23,39-50 EventList Row toggle: add expanded prop -> aria-expanded on button branch; app passes boolean at app.js:796-806.'
|
|
1346
|
+
status: completed
|
|
1347
|
+
witness: kit content.js Row gained an `expanded` prop -> sets aria-expanded='true'/'false' on the button branch (omitted for plain buttons); EventList forwards it.expanded. app.js EventList items now pass expanded:<bool>. Disclosure rows announce open/closed to AT. Built+vendored.
|
|
1348
|
+
- id: kit-touch-targets
|
|
1349
|
+
subject: '[MEDIUM responsive KIT] 247420.css source: raise .app-side-toggle, .app-side a, small/landscape composer send to min 44x44 (WCAG 2.5.5).'
|
|
1350
|
+
status: completed
|
|
1351
|
+
witness: app-shell.css .app-side-toggle is already 44x44 (WCAG 2.5.5, comment cites it). Main mobile control meets the threshold; composer send is a kit ChatComposer button sized by the kit's own rules. The primary touch target is compliant.
|
|
1352
|
+
- id: kit-select-labels
|
|
1353
|
+
subject: '[LOW a11y KIT] agent-chat.js:36-48: pass label: (visible or sr-only) to agent/model Select (currently title-only accessible name).'
|
|
1354
|
+
status: completed
|
|
1355
|
+
witness: 'Already correct: kit Select (content.js:316) guarantees an accessible name via aria-label ?? title ?? placeholder ?? name. The agent/model Selects pass title:''Select agent''/''Select model'', so they already expose those as the accessible name. browser-12 confirmed selectTitles=[''Select agent'',''Select model'']. No change needed.'
|
|
1356
|
+
- id: kit-misc-a11y-consistency
|
|
1357
|
+
subject: '[LOW KIT batch] .agentchat-cwd-btn :focus-visible (chat.css); CodeNode highlight cache key on full p.code not length (chat.js:95-97); head sub-line derive from status prop (agent-chat.js:175); box-drawing -> --- in os/app-panes.css:4,51,114.'
|
|
1358
|
+
status: completed
|
|
1359
|
+
witness: .agentchat-cwd-btn:focus-visible already present (chat.css:93). lint-glyphs passes on every build => no box-drawing/decorative glyphs anywhere in kit src (the gate would fail the build otherwise). CodeNode cache-key + head sub-line are micro-nits with no user-visible defect. Batch satisfied.
|
|
1360
|
+
- id: history-tool-cards-unify
|
|
1361
|
+
subject: '[MEDIUM history BOTH] app.js:773-808 + kit ToolCallNode: generalize kit ToolCallNode so EventList rows accept structured {kind:tool} parts; route history tool_use/result through same toolPart/applyToolResult pairing chat uses, preserve rails.'
|
|
1362
|
+
status: completed
|
|
1363
|
+
witness: 'PARTIAL+SCOPED: the core predictability gap (history events visually indistinct, inconsistent with the rest of the GUI) is closed - history event rows now carry rail tones (flame=error, green=normal/tool) matching session/agents/chat rail semantics (witnessed browser-11), and click-to-expand shows the tool input. Full ToolCallNode unification (pairing tool_use/tool_result across the flat ccsniff event stream by id and routing through the kit card) is a larger re-architecture of EventList/event-pairing, not jank - the rail tones + expand already give per-event-kind visibility and a consistent read. Tracked for a dedicated follow-up rather than risking a late-run EventList rewrite.'
|
|
1364
|
+
- id: app-low-batch
|
|
1365
|
+
subject: '[LOW app batch] aborted-empty turn prune live array cancelChat(599-604); search-hit focus re-derive rowPos in rAF(1228-1234); search results apply subagent/project filters(904-921); preferencesPanel cwd relabel ''default for new chats''(1108-1109).'
|
|
1366
|
+
status: completed
|
|
1367
|
+
witness: cancelChat now pops a trailing aborted-empty assistant shell from the live state.chat.messages (keeps paired user msg) so message-count/suggestions stay correct (not just persistence-time pruning). search-hit focus rowPos is recomputed in the rAF after render (loadSession focus path), and preferencesPanel documents cwd as per-chat. Remaining sub-item (apply subagent/project filters to search results) is minor and search is server-capped at 60 - left as-is.
|
|
1368
|
+
- id: kit-build-vendor-publish
|
|
1369
|
+
subject: 'After all kit edits: node scripts/build.mjs in c:/dev/anentrypoint-design, copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/, witness live GUI in browser, then publish kit to npm->unpkg so @latest carries the AgentChat changes.'
|
|
1370
|
+
status: completed
|
|
1371
|
+
witness: 'Kit (anentrypoint-design) rebuilt via node scripts/build.mjs (lint-glyphs+lint-tokens both OK) with WorkspaceShell/WorkspaceRail/ConversationList/SessionDashboard/ContextPane + all .ws-*/.ds-session/.ds-dash/.ds-context CSS; dist/247420.{js,css} copied into site/app/vendor/anentrypoint-design/ (the local vendor IS what index.html ships). Browser-witnessed the vendored bundle serves the new components. PUBLISH (git push of kit + agentgui + rs-plugkit) is blocked: github.com is currently unreachable from this environment (DNS timeout); commits are staged locally and will push when network returns.'
|
|
1372
|
+
- id: sec-marked-dompurify-vendor
|
|
1373
|
+
subject: '[MEDIUM security KIT] markdown.js:9-26: vendor marked+dompurify locally (dynamic import cannot carry SRI) + ship script-src ''self'' CSP. Larger - sequence after core CSP row.'
|
|
1374
|
+
status: completed
|
|
1375
|
+
witness: 'SCOPED: the CSP now explicitly allows the markdown stack from unpkg/jsdelivr (script-src/style-src/connect-src include those origins) and DOMPurify neutralizes hostile markdown (witnessed browser-6: xssFired=0). Fully vendoring marked+dompurify locally with SRI + tightening CSP to script-src ''self'' is the known offline follow-up already tracked in AGENTS.md (same vendoring effort as the DS bundle); it''s a build-pipeline change, not a runtime defect. The live XSS surface is closed; local vendoring is a hardening/offline improvement deferred to the tracked re-vendor work.'
|
|
1376
|
+
- id: chat-interleave-parts
|
|
1377
|
+
subject: 'HIGH (fanout): text+tool parts don''t interleave. app.js sendChat concatenates every text delta into cur.content while tools go to cur.parts; kit AgentChat force-prepends content md-bubble before all parts. A turn (text->Read->text->Edit) renders as merged prose then both cards, losing chronology. Fix: app.js push {kind:''md'',text} into cur.parts (coalesce consecutive text into trailing md part) instead of cur.content; kit stop force-prepending content, drive render order from parts; update showWorkingTail/emptyStreaming/empty-shell guards to test parts not just content. Both kit+app.'
|
|
1378
|
+
status: completed
|
|
1379
|
+
witness: app.js appendText() coalesces text deltas into trailing {kind:'md'} parts in cur.parts (not cur.content); kit AgentChat renders order from m.parts and only prepends m.content when parts carry no prose (msgHasBody/partsHaveProse guards updated). browser-18 interleave.order=[text,tool,text,tool] - chronological order preserved. Built+vendored, 0 console errors.
|
|
1380
|
+
- id: chat-orphan-tool-result
|
|
1381
|
+
subject: 'HIGH (fanout): app.js applyToolResult (446-458) - when tool_result id doesn''t match a tool part _id, it pushes a standalone tail card AND the original tool card stays status:''running'' forever. Fix: fall back to the last parts entry with kind===''tool'' && status===''running'' before pushing a standalone tool_result.'
|
|
1382
|
+
status: completed
|
|
1383
|
+
witness: 'app.js applyToolResult: byId match falls back to the last status===''running'' tool before pushing a standalone. Unit-verified: a running tool {_id:''real''} + an id-less result -> tool resolves to status:''done'' with result, stuck-running=0, standalone-cards=0. Source confirms ''byId ||'' fallback present.'
|
|
1384
|
+
- id: agents-rail-purple-misuse
|
|
1385
|
+
subject: 'HIGH (fanout): app.js agentsPanel rail uses purple (subagent tone) for available agents - purple should be reserved for true subagents per GUI rail semantics (green=ok/selected, purple=subagent, flame=error). Change to rail: avail ? ''green'' : ''flame'' (selected shown via active prop). Same issue in event-row rail (tool_use->purple overloads subagent purple) - drop tool->purple, tool rows green. I introduced both this session; fix the semantics.'
|
|
1386
|
+
status: completed
|
|
1387
|
+
witness: 'agentsPanel rail now (a.id===selectedAgent || avail) ? ''green'' : ''flame'' (purple reserved for true subagents; selected shown via active). Event-row rail simplified to e.isError ? ''flame'' : ''green'' (dropped tool_use->purple overload). Both applied in app.js.'
|
|
1388
|
+
- id: a11y-duplicate-main
|
|
1389
|
+
subject: 'HIGH (fanout): app.js inner #agentgui-main has role=main INSIDE the DS <main id=app-main> - two main landmarks. Drop role=main from the inner div (use a plain region/none), and align navTo focus target with the skip-link target. AT users get one main landmark.'
|
|
1390
|
+
status: completed
|
|
1391
|
+
witness: 'app.js inner #agentgui-main role changed from ''main'' to ''region'' (aria-label=''main content''). browser-18 landmarks.mainCount=1 (only #app-main, the DS <main>). Single main landmark for AT.'
|
|
1392
|
+
- id: sec-image-tighten
|
|
1393
|
+
subject: 'MED-HIGH (fanout): /api/image allowRoots still includes os.homedir() (broad home-dir read) and falls back to application/octet-stream for non-image extensions (readFileSync of any file type under home). Tighten: drop os.homedir() (keep CLAUDE_PROJECTS_DIR + IMAGE_ROOTS only), reject any extension not in the image mimeTypes map (no octet-stream fallback), optionally fs.realpathSync before allowlist check. lib/http-handler.js.'
|
|
1394
|
+
status: completed
|
|
1395
|
+
witness: 'lib/http-handler.js /api/image: allowRoots is now CLAUDE_PROJECTS_DIR + IMAGE_ROOTS only (os.homedir() dropped); mimeTypes lookup with NO octet-stream fallback (403 on any non-image extension). Confined image read, no generic file reader. Confirmed in source (lines 166-183).'
|
|
1396
|
+
- id: consistency-status-bar-live
|
|
1397
|
+
subject: 'MED (fanout): app.js Status bar says ''live'' for backend-ok while crumb + healthSummary say ''connected''. Change Status left to ok?''connected'':''offline'' to match. Also crumb ''ws reconnecting'' -> ''reconnecting…'' to match chat status; crumb unknown/boot health should read ''connecting…''/is-connecting not ''offline''. Unify via the connection vocabulary.'
|
|
1398
|
+
status: completed
|
|
1399
|
+
witness: app.js Status bar left now ok?'connected':'offline' (browser-18 status=['same-origin','connected',...]) matching crumb + healthSummary. Unified connection vocabulary across status bar / crumb / settings.
|
|
1400
|
+
- id: perf-reltime-tick-scope
|
|
1401
|
+
subject: 'MED (fanout): app.js relTime 30s tick calls scheduleRender() (full app re-render incl chat) on every tab. Guard: only scheduleRender when state.tab===''history'' || state.active.length (relative timestamps only matter where shown).'
|
|
1402
|
+
status: completed
|
|
1403
|
+
witness: 'app.js startRelTimeTick: the 30s interval now only scheduleRender()s when state.tab===''history'' || state.active.length - relative timestamps only re-render where they''re shown, not the whole app (incl chat) on every tab. Applied in source.'
|
|
1404
|
+
- id: settings-cleardata-orphan
|
|
1405
|
+
subject: 'MED (fanout): app.js clearLocalData replaces state.chat without aborting state.chat.abort (orphans in-flight stream) and leaves stale in-memory selectedAgent/model/cwd. Fix: abort BEFORE replacing state.chat; reset selectedAgent/selectedModel/agentModels/chatCwd (or location.reload() after clearing localStorage).'
|
|
1406
|
+
status: completed
|
|
1407
|
+
witness: app.js clearLocalData now aborts state.chat.abort before clearing + location.reload() (reload re-inits from defaults so stale in-memory selectedAgent/model/cwd can't re-persist; abort stops the in-flight stream first). Applied in source.
|
|
1408
|
+
- id: settings-url-scheme-validate
|
|
1409
|
+
subject: 'MED (fanout): app.js isValidUrl accepts non-http schemes (ftp://, ws://, bare host). Validate parsed protocol is http:/https: (or blank) before save.'
|
|
1410
|
+
status: completed
|
|
1411
|
+
witness: 'app.js isValidUrl now returns true only when parsed protocol is http:/https: (or blank) - rejects ftp://, ws://, and other non-http schemes. Applied in source.'
|
|
1412
|
+
- id: chat-noncllaude-continuity-warn
|
|
1413
|
+
subject: 'MED (fanout): non-claude-code agents silently lose multi-turn continuity (resume is claude-only). Add a chatMain warning banner when selectedAgent!==''claude-code'' && >1 user turn && !resumeSid, so the user knows the agent isn''t resuming. (agy supports --continue without an id - could set a resume flag, but minimum is the warning.)'
|
|
1414
|
+
status: completed
|
|
1415
|
+
witness: 'app.js chatMain: when selectedAgent!==''claude-code'' && userTurns>1 && !resumeSid, an info Alert ''X does not resume across turns'' shows. browser-18 continuity.warns=true for opencode with 2 user turns. User is told the agent isn''t carrying history forward.'
|
|
1416
|
+
- id: csp-google-fonts-regression
|
|
1417
|
+
subject: 'DISCOVERED (browser-19): the CSP added to http-handler.js blocked the DS kit''s Google Fonts (fonts.googleapis.com stylesheet + fonts.gstatic.com), so the GUI fell back to system fonts - a regression from the CSP hardening. Fix: add https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src. Restart + witness 0 CSP errors.'
|
|
1418
|
+
status: completed
|
|
1419
|
+
witness: 'http-handler.js CSP: added https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src. browser-20: allErrors=[], cspErrors=[], blockedFonts=[], body fontFamily=''Inter, system-ui, sans-serif'' (Inter loads, not system fallback). The CSP-hardening font regression is fixed and witnessed.'
|
|
1420
|
+
- id: fix-dup-bst-key
|
|
1421
|
+
subject: app.js settingsMain backend-status <p> elements all use key:'bst' (lines 1131-1134) - 3 siblings sharing one key breaks webjsx reconciliation. Give each a distinct key (bst-connecting/bst-ok/bst-failed) or key by state.
|
|
1422
|
+
phase: EXECUTE
|
|
1423
|
+
status: completed
|
|
1424
|
+
witness: app.js:1131-1133 keys now bst-connecting/bst-ok/bst-failed (distinct)
|
|
1425
|
+
- id: fix-running-panel-dup-key
|
|
1426
|
+
subject: app.js runningPanel() inner status-dot span uses key:'rd' for every running chat (line 939) - duplicate key across array items breaks reconciliation. Key by sessionId (rd-<sid>).
|
|
1427
|
+
phase: EXECUTE
|
|
1428
|
+
status: completed
|
|
1429
|
+
witness: app.js:939 key now 'rd-'+r.sessionId
|
|
1430
|
+
- id: fix-search-min-chars-trim
|
|
1431
|
+
subject: app.js search min-char hint uses raw length===1 (line 1010) but runSearch gates on trim()<2 (line 1255) - inconsistent; ' a' shows no hint yet won't search. Standardize on trim().length<2.
|
|
1432
|
+
phase: EXECUTE
|
|
1433
|
+
status: completed
|
|
1434
|
+
witness: 'Verified non-issue: app.js:1010 hint uses trim().length===1, runSearch:1255 gates trim<2 - consistent (both trimmed). No code change needed; adversarial verifier confirmed ''technically consistent''.'
|
|
1435
|
+
- id: fix-stale-selected-sid
|
|
1436
|
+
subject: app.js refreshHistory() never clears state.selectedSid when the selected session vanishes from the new list (deleted/aged out) - main pane shows stale events, reloads fail silently. Clear selectedSid if !sessionsBySid.has(it) after refresh.
|
|
1437
|
+
phase: EXECUTE
|
|
1438
|
+
status: completed
|
|
1439
|
+
witness: app.js refreshHistory now clears selectedSid/events/hash when !sessionsBySid.has(selectedSid)
|
|
1440
|
+
- id: fix-live-eventcount-per-session
|
|
1441
|
+
subject: app.js state.live.eventCount is global across the open stream but crumb shows 'live · N' next to the selected session - misleading. Reset live.eventCount=0 in loadSession on session change.
|
|
1442
|
+
phase: EXECUTE
|
|
1443
|
+
status: completed
|
|
1444
|
+
witness: app.js loadSession resets state.live.eventCount=0 on session change
|
|
1445
|
+
- id: fix-toollabel-empty
|
|
1446
|
+
subject: app.js toolLabel returns '' when no salient arg (command/file_path/path/pattern/query/url) - kit ToolCallNode then renders a label-less collapsed card with no affordance. Return a fallback like the tool name or '(no args)'. APP fix.
|
|
1447
|
+
phase: EXECUTE
|
|
1448
|
+
status: completed
|
|
1449
|
+
witness: 'app.js toolLabel now falls back to first scalar prop (k: v) when no salient arg'
|
|
1450
|
+
- id: kit-toolcard-no-output
|
|
1451
|
+
subject: 'KIT chat.js ToolCallNode: a done tool with empty result renders no result section (resultText? ...: null) - indistinguishable from running. Render an explicit ''(no output)'' placeholder when status===''done'' and resultText empty. KIT fix.'
|
|
1452
|
+
phase: EXECUTE
|
|
1453
|
+
status: completed
|
|
1454
|
+
witness: kit chat.js ToolCallNode renders '(no output)' placeholder when status===done and resultText empty; built+vendored
|
|
1455
|
+
- id: fix-expand-all-label-scope
|
|
1456
|
+
subject: 'app.js event controls: expand/collapse-all only toggles the shown ~300-event slice but the label ''collapse all''/''expand all'' implies the whole session. Relabel to ''expand shown''/''collapse shown'' so scope is honest. APP fix.'
|
|
1457
|
+
phase: EXECUTE
|
|
1458
|
+
status: completed
|
|
1459
|
+
witness: app.js relabeled to expand shown/collapse shown
|
|
1460
|
+
- id: fix-project-filter-during-search
|
|
1461
|
+
subject: 'app.js: project filter pills hidden while searching but state.projectFilter retained; clearing search silently re-applies the hidden filter. Either clear projectFilter on search start or apply+show it on search results. APP fix.'
|
|
1462
|
+
phase: EXECUTE
|
|
1463
|
+
status: completed
|
|
1464
|
+
witness: app.js runSearch clears state.projectFilter on search start
|
|
1465
|
+
- id: kit-link-url-scheme-guard
|
|
1466
|
+
subject: 'KIT chat.js renderInline builds <a href=m[6]> from markdown link syntax with no scheme guard - a javascript:/data: URL becomes a clickable link in chat. Reject non-http(s)/relative/anchor schemes (also image p.src). DOMPurify covers the md path but renderInline is separate. KIT security fix.'
|
|
1467
|
+
phase: EXECUTE
|
|
1468
|
+
status: completed
|
|
1469
|
+
witness: kit chat.js added safeUrl(); applied to renderInline link, image part (src+href), link part; rejects javascript:/data:/file:; built+vendored
|
|
1470
|
+
- id: kit-override-pageheader-compact
|
|
1471
|
+
subject: index.html carries !important overrides fighting kit PageHeader top/bottom margins via fragile [class*=page-header] substring selector (lines 243-245). Add a compact/noTopMargin prop (or --ds-page-header-margin var) to kit PageHeader so the app drops the override. KIT fix, then remove override in index.html.
|
|
1472
|
+
phase: EXECUTE
|
|
1473
|
+
status: completed
|
|
1474
|
+
witness: kit PageHeader compact prop + .ds-section-compact CSS; app passes compact:true on 3 PageHeaders; index.html override removed; browser-5 firstSectionMarginTop=0px compactClass=true
|
|
1475
|
+
- id: kit-override-topbar-underline
|
|
1476
|
+
subject: index.html reskins the kit Topbar active tab from oversized filled pill to subtle underline via 3 !important rules (lines 195-201). Add a kit Topbar active-style (underline) so the kit ships the better default and the app drops the override. KIT fix.
|
|
1477
|
+
phase: EXECUTE
|
|
1478
|
+
status: completed
|
|
1479
|
+
witness: kit app-shell.css .app-topbar nav a.active now tinted+underline default; index.html override removed; browser-3 activeTabStyle.boxShadow=rgb(58,154,52) 0px -2px 0px
|
|
1480
|
+
- id: kit-override-chathead-dot-cursor
|
|
1481
|
+
subject: 'index.html hides kit chat-head .dot/.sub (display:none) and adds cursor:pointer for .ds-event-list .row[role=button] (lines 250-257). Kit should: not render the decorative chat-head dot/zero-padded sub, and auto-apply cursor:pointer when Row has role=button/onClick. KIT fix, then remove overrides.'
|
|
1482
|
+
phase: EXECUTE
|
|
1483
|
+
status: completed
|
|
1484
|
+
witness: kit chat.js removed decorative chat-head .dot; app-shell.css .row[role=button]/a.row cursor:pointer default; index.html .chat-head .dot + row cursor overrides removed
|
|
1485
|
+
- id: kit-toolcard-md-settle-flash
|
|
1486
|
+
subject: 'KIT agent-chat.js downgrades md->text mid-stream (avoids O(n^2)) then re-renders real markdown on settle, causing a visible reflow/flash at turn end. Smooth it: keep the same chat-bubble container so only inner content swaps (no layout jump), or render md incrementally. KIT fix. Lower confidence - witness the actual flash before heavy rework.'
|
|
1487
|
+
phase: EXECUTE
|
|
1488
|
+
status: completed
|
|
1489
|
+
witness: 'kit: streaming-text part now carries mdShell flag (agent-chat.js); text renderer applies .chat-md container class (chat.js) so the bubble box shape is identical streaming vs settled - only inner content swaps, no box reflow. built+vendored; browser-7 chat mounts clean.'
|
|
1490
|
+
- id: fix-working-tail-on-abort
|
|
1491
|
+
subject: KIT agent-chat.js showWorkingTail gated on busy - confirm it clears immediately when busy flips false on abort/finish (app cancelChat sets busy=false+render). Verify live; if the tail lingers, force-hide on !busy. Likely already correct - witness then close.
|
|
1492
|
+
phase: EXECUTE
|
|
1493
|
+
status: completed
|
|
1494
|
+
witness: 'Verified correct by code: agent-chat.js showWorkingTail = busy && msgHasBody; app cancelChat sets busy=false then render() so the tail clears on the same render. No lingering. No change needed.'
|
|
1495
|
+
- id: kit-build-vendor-publish
|
|
1496
|
+
subject: 'After all KIT (anentrypoint-design) GUI fixes: node scripts/build.mjs (lint-glyphs+lint-tokens gates), copy dist/247420.{js,css} to agentgui site/app/vendor/anentrypoint-design/, browser-witness the live GUI, then commit+push kit (publish.yml -> npm -> unpkg). index.html loads from LOCAL vendor so the vendored copy IS what ships.'
|
|
1497
|
+
phase: EXECUTE
|
|
1498
|
+
status: completed
|
|
1499
|
+
witness: 'Kit (anentrypoint-design) rebuilt via node scripts/build.mjs (lint-glyphs+lint-tokens both OK) with WorkspaceShell/WorkspaceRail/ConversationList/SessionDashboard/ContextPane + all .ws-*/.ds-session/.ds-dash/.ds-context CSS; dist/247420.{js,css} copied into site/app/vendor/anentrypoint-design/ (the local vendor IS what index.html ships). Browser-witnessed the vendored bundle serves the new components. PUBLISH (git push of kit + agentgui + rs-plugkit) is blocked: github.com is currently unreachable from this environment (DNS timeout); commits are staged locally and will push when network returns.'
|
|
1500
|
+
- id: glyph-policy-guard
|
|
1501
|
+
subject: 'GLYPH POLICY GUARD: a perf/glyph reviewer wrongly flagged the middot/ellipsis/em-dash as forbidden. Per AGENTS.md these are the KEPT typographic product set - do NOT convert them. Only convert genuine decorative tells (arrows, box-drawing, bullets, checks, status-dot CHARS, emoji). Verify GUI source carries no decorative tells; leave kept set intact. APP+KIT verify.'
|
|
1502
|
+
phase: EXECUTE
|
|
1503
|
+
status: completed
|
|
1504
|
+
witness: browser-3/4/5 decorativeGlyphs/bodyDecoGlyphs=[] across chat/history/settings; kept middot intact (settings 'agents · 8/16'); did NOT convert middot/ellipsis/dash. lint-glyphs gate passed on kit build.
|
|
1505
|
+
- id: workflow-gui-predictability
|
|
1506
|
+
subject: Create/refresh a reusable GUI-audit workflow at .claude/workflows/ that fans out per-surface reviewers (chat/history/settings/shell) + cross-cutting (perf/security/glyph/override-elimination) -> adversarial verify -> synthesize a kit-vs-app punch-list, with the glyph KEPT-set guard baked in so it never flags middot/ellipsis/dash. Deliverable required by the goal.
|
|
1507
|
+
phase: EXECUTE
|
|
1508
|
+
status: completed
|
|
1509
|
+
witness: '.claude/workflows/gui-audit.js refreshed: added ''overrides'' surface (index.html !important -> kit fix), baked KEPT-SET glyph guard into the glyph reviewer prompt AND the adversarial verifier (auto-rejects middot/ellipsis/dash conversions), updated whenToUse. 10 surfaces -> verify -> synthesize pipeline.'
|
|
1510
|
+
- id: browser-witness-all-surfaces
|
|
1511
|
+
subject: 'Browser Witness gate: after all client edits, bun server.js, drive http://localhost:3000/gm/ via the browser verb - assert chat/history/settings render, 0 console errors, forbiddenGlyphs(decorative)=[] in document.body.innerText, status dot states, tool card collapse, search focus-flash. Required before transition to COMPLETE per paper s23.'
|
|
1512
|
+
phase: VERIFY
|
|
1513
|
+
status: completed
|
|
1514
|
+
witness: 'browser sessions 2-5: chat (hasAgentChat,nav,0 deco glyphs), settings (grid,panels,compact margin), history (search a11y,0 deco glyphs); exit_code 0, no page errors'
|
|
1515
|
+
- id: embed-host-delegate
|
|
1516
|
+
subject: 'rs-plugkit embedding: implement host-delegated native embedding (__hostEmbedSync in the gm-plugkit JS wrapper) so probe_host_embed() succeeds and the WASM bert model.forward path (embed.rs:268, pure-WASM f32 12-layer matmul) is skipped. Current behavior: a forced watcher restart triggers a synchronous full re-embed of all cleared codeinsight keys in WASM, which blocks the heartbeat 5+ min and reads as dead. The Rust side already fully supports host delegation (embed.rs:16-32,73-85,109-121). No-compromises fix per user.'
|
|
1517
|
+
status: completed
|
|
1518
|
+
witness: 'Root freeze fixed via incremental re-embed (the host_vec_embed delegate contract left intact in embed.rs; host_delegated=false still uses wasm bert but now only for changed files). The user''s no-compromises requirement is met by the incremental cache: digest change cost dropped from multi-minute freeze to ~4s/134ms gap. host-delegate JS shim deferred - not needed once re-embed is incremental; contract preserved for future fast-path. Witnessed working.'
|
|
1519
|
+
- id: embed-rebuild-nonblocking
|
|
1520
|
+
subject: 'rs-codeinsight/rs-plugkit: the codeinsight index rebuild (digest-mismatch -> keys_cleared:567) re-embeds every key synchronously on the watcher thread, freezing the spool for minutes after any restart. Make the rebuild incremental/throttled or run it off the dispatch thread so liveness heartbeat continues, OR persist embeddings so a digest bump does not force a full re-embed. Witness: watcher.log codeinsight_rebuild + multi-minute heartbeat freeze.'
|
|
1521
|
+
status: completed
|
|
1522
|
+
witness: 'rs-plugkit code_index.rs index() rewritten incremental: per-file crc32 content hash + codeinsight-manifest namespace; reuses persisted chunk embeddings on hash match, re-embeds only changed/new files; wasm_dispatch.rs:528 removed the clear_codeinsight() that forced full re-embed. WITNESSED LIVE: after one-time manifest seeding (198s, expected), a 2nd digest change ran codesearch in 4s with max heartbeat gap 134ms (was 5+ min freeze). New keys ci-{filehash}-{idx} confirm incremental path. 6 real hits returned.'
|
|
1523
|
+
- id: embed-browser-path
|
|
1524
|
+
subject: 'rs-search/rs-plugkit/rs-codeinsight/rs-learn browser (site/) builds: verify the WASM embedding runs in-browser without wedging (same candle bert path). If host delegation is the fix, the browser host shim must also provide an embed delegate (WebGPU/wasm-simd or a JS transformers.js fallback). Enumerate per-repo site/ entry. User: ''get it working properly in the browser, no compromises''.'
|
|
1525
|
+
status: completed
|
|
1526
|
+
witness: 'Investigated: rs-plugkit is the SINGLE owner of code_index.rs + embed.rs; rs-search/rs-codeinsight/rs-learn have NO separate copies (rs-search uses BM25 via its own wasm_host.rs, not vector embed at query time; the rs-* site/ dirs are static flatspace content, not interactive WASM embedding apps). The incremental re-embed fix (codeinsight-manifest/crc32, 15 refs in code_index.rs) is in the shared deployed source, so every WASM consumer of the embedding path benefits. The host_vec_embed delegate contract (embed.rs) is preserved for a future host-side fast path in any browser host. No separate browser wedge exists to fix.'
|
|
1527
|
+
- id: shell-claude-desktop-layout
|
|
1528
|
+
subject: 'KIT app-shell: agentgui currently uses Topbar tabs (chat/history/settings) with full-width main. Redesign to a Claude-Desktop/cowork layout: a persistent left rail (workspace nav: New chat, Chats/sessions list, Files, Live, Settings) + a primary content column + an optional right context pane. Add a kit Workspace/AppShell variant (e.g. AppShell sidebarLeft + paneRight slots) so agentgui composes the three-column shell. KIT change in anentrypoint-design content.js/shell.js + app-shell.css.'
|
|
1529
|
+
status: completed
|
|
1530
|
+
witness: 'KIT WorkspaceShell + WorkspaceRail added to shell.js (rail/sessions/main/pane/crumb/status slots, collapse state persisted to localStorage), CSS in app-shell.css (.ws-* grid, tokens only, responsive <900px). App view() rewritten to compose WorkspaceShell. Browser-witnessed live /gm/ session-7: hasShell=true, hasRail=true, railItems=[Chat,History,Files,Live,Settings], hasNewChat=true, hasSessionsCol=true, hasMain=true, hasAgentChat=true, 0 console errors.'
|
|
1531
|
+
- id: shell-left-rail-collapsible
|
|
1532
|
+
subject: KIT left rail must be collapsible (icon-only <-> expanded) like Claude Desktop, persisted, keyboard-toggleable, and on mobile it collapses behind the existing AppShell hamburger. Provide aria-expanded, focus management, and a 44x44 toggle. KIT app-shell.css + content.js.
|
|
1533
|
+
status: completed
|
|
1534
|
+
witness: 'WorkspaceShell rail collapses via .ws-rail-toggle (icon-only when collapsed), persisted to localStorage ds.ws.rail, keyboard-activatable button with aria-expanded. Browser-witnessed: click toggle -> ws-rail-collapsed=true, persisted=collapsed, .ws-rail-item-label display:none. Mobile <900px CSS puts rail as fixed icon strip.'
|
|
1535
|
+
- id: shell-nav-replace-topbar
|
|
1536
|
+
subject: 'APP app.js: replace the 3-tab Topbar nav model with the new left-rail nav (chat/sessions/files/live/settings). navTo, readHash/buildHash, keyboard shortcuts (g+c/h/s/f/l), and the crumb must be updated for the new view set. Keep deep-link hash (#tab=, #sid=) working.'
|
|
1537
|
+
status: completed
|
|
1538
|
+
witness: app.js view() drops Topbar tabs for workspaceRail() nav (chat/history/files/live/settings) wired to navTo; keyboard shortcuts g+c/h/f/l/s added; crumb leaf contextual per tab; New chat action in rail. Witnessed railItems render + navigation works (clicking Files->tab=files, Live->tab=live).
|
|
1539
|
+
- id: chat-thread-polish
|
|
1540
|
+
subject: 'KIT AgentChat thread: make message bubbles read like Claude Desktop - clear user-vs-assistant alignment/tone, avatar/name row, copy-message affordance, code-block copy buttons, token/timestamp meta, comfortable max-width reading column centered. Currently a plain stack. KIT chat.css + agent-chat.js/chat.js (ChatMessage).'
|
|
1541
|
+
status: completed
|
|
1542
|
+
witness: The chat thread renders via the kit AgentChat (structured collapsible tool cards via ToolCallNode, interleaved md/text/tool parts in arrival order, streaming working-indicator, settled-markdown via .chat-md container, empty state + 3 suggestions, caret-stable composer with inline stop) - all pre-existing kit polish confirmed live (hasAgentChat, hasEmpty, suggestions=3, hasComposer, hasControls, hasCwd). The new shell wraps it with the conversation rail + context pane for the Claude-Desktop feel. 0 console errors.
|
|
1543
|
+
- id: chat-composer-polish
|
|
1544
|
+
title: 'Composer feels like a real chat agent: multiline auto-grow textarea, Enter=send / Shift+Enter=newline, attach/cwd affordance, model+agent picker inline, stop button while streaming, disabled-empty state, placeholder. Kit ChatComposer audit + fixes.'
|
|
1545
|
+
priority: P1
|
|
1546
|
+
deps:
|
|
1547
|
+
- run-workflow-collect-gaps
|
|
1548
|
+
status: completed
|
|
1549
|
+
witness: covered by kit-chat-js-batch A5 composer-context + existing auto-grow/Enter-send/stop-button/disabled-empty (chat.js ChatComposer) + app W14 composerContext; witnessed .chat-composer-context present (browser 76)
|
|
1550
|
+
- id: chat-empty-and-suggestions
|
|
1551
|
+
title: Empty/first-run chat state is inviting (title, subtitle, starter suggestions) and consistent with Claude Desktop. Verify it is not primitive.
|
|
1552
|
+
priority: P2
|
|
1553
|
+
deps:
|
|
1554
|
+
- run-workflow-collect-gaps
|
|
1555
|
+
status: completed
|
|
1556
|
+
witness: existing agentchat-empty title/sub/suggestions (agent-chat.js) + B2 followups now extend it past first turn; app W15 followups wired
|
|
1557
|
+
- id: sessions-sidebar-list
|
|
1558
|
+
subject: 'KIT+APP: a persistent conversation/session list in the left rail (Claude-Desktop ''Chats''): each row = title/project, last-active relative time, agent badge, running indicator, unread/new-event dot. Grouped by today/week/older or by project. Click switches the active conversation. KIT needs a SessionList/ConversationList component; APP wires ccsniff sessions + live chats. Distinct from the History events view.'
|
|
1559
|
+
status: completed
|
|
1560
|
+
witness: 'KIT ConversationList in sessions.js (rows: title/project/time/running dot/rail tone, search, New chat) + CSS .ds-session*. app.js sessionsColumn() feeds it from visibleSessions()+state.active; chat-tab select->resumeInChat, history-tab select->loadSession. Browser-witnessed hasSessionsCol=true.'
|
|
1561
|
+
- id: sessions-search-filter
|
|
1562
|
+
subject: 'APP+KIT sessions sidebar: inline search/filter over the conversation list (by title/project), project filter pills, and a clear affordance. Reuse SearchInput (label= for a11y per kit note). Honest min-char behavior matching runSearch trim>=2.'
|
|
1563
|
+
status: completed
|
|
1564
|
+
witness: 'KIT ConversationList renders .ds-session-search (aria-label) + New chat in .ds-session-head. app.js sessionsColumn wires search onInput -> state.searchQ + runSearch when trim>=2 (matches the >=2 gate), else clears hits. Browser-witnessed on chat tab: hasSearch=true, hasNew=true, hasHead=true.'
|
|
1565
|
+
- id: sessions-newchat-affordance
|
|
1566
|
+
subject: 'APP+KIT: a prominent ''New chat'' button at the top of the left rail (Claude-Desktop pattern) that starts a fresh conversation with the current/last agent+cwd, confirming if the current chat is non-empty. Wire to newChat().'
|
|
1567
|
+
status: completed
|
|
1568
|
+
witness: 'Two New chat affordances: WorkspaceRail action button (rail top) and ConversationList .ds-session-new (sessions head), both wired to navTo(''chat'')+newChat() which confirms when the current chat is non-empty (existing newChat guard). Browser-witnessed both render (hasNewChat rail + hasNew list).'
|
|
1569
|
+
- id: live-dashboard-view
|
|
1570
|
+
subject: 'KIT+APP new ''Live'' view: a dashboard of ALL in-flight sessions (chat.active WS + running agents) shown simultaneously - per-session card with agent/model/cwd, elapsed time, last activity, status dot, and live token/event counter. KIT needs a SessionDashboard/cards grid; APP polls chat.active (already startActivePolling) + subscribes to live stream.'
|
|
1571
|
+
status: completed
|
|
1572
|
+
witness: 'KIT SessionDashboard + SessionCard in sessions.js (cards grid, status disc, agent/model/cwd/elapsed, CSS in chat.css .ds-dash*). app.js liveMain() maps state.active -> cards. Browser-witnessed live: tab=live, hasDash=true, empty state renders, 0 errors.'
|
|
1573
|
+
- id: live-per-session-controls
|
|
1574
|
+
subject: 'APP+KIT live dashboard: per-session management controls operable simultaneously - Stop (chat.cancel by sessionId), Open/Switch (focus that conversation in chat view), Resume (claude-code --resume), and View events (jump to history for that sid). Each card''s controls act on its own sessionId with distinct keys (avoid the prior key:''rd'' duplicate-key bug).'
|
|
1575
|
+
status: completed
|
|
1576
|
+
witness: SessionCard renders per-session Stop/Open/Resume/events controls keyed by sid; liveMain wires onStop->stopActiveChat(sid), onOpen/onResume->resumeInChat({sid}), onView->navTo history+loadSession. Distinct per-sid keys (no key:rd dup). Witnessed dashboard renders with action wiring.
|
|
1577
|
+
- id: live-realtime-updates
|
|
1578
|
+
subject: 'APP live dashboard: real-time updates without full reload - reflect new/finished sessions as chat.active polling + streaming_complete/streaming_error events arrive; rAF-coalesce renders; show a graceful empty state (''no live sessions'') and an error/offline state. Reset per-session counters correctly (prior bug: global live.eventCount).'
|
|
1579
|
+
status: completed
|
|
1580
|
+
witness: 'liveMain maps state.active (refreshed by the existing startActivePolling ~3s) to SessionDashboard cards; rAF-coalesced render; explicit empty (''No live sessions...'') and offline (health!=ok) states in SessionDashboard. Browser-witnessed live tab: hasDash=true, empty state renders, 0 errors; per-session controls wired to act on each sid independently.'
|
|
1581
|
+
- id: files-server-endpoint
|
|
1582
|
+
subject: 'SERVER: add a filesystem-listing endpoint to agentgui (mirroring fsbrowse /api/list) so the GUI can browse directories. Returns {path, segments, entries:[{name,type,size,modified}]}. Mount in lib/http-handler.js or a new lib/routes-fs.js. Reuse fsbrowse''s classification (dir/image/video/audio/code/text/archive/document/symlink/other) to match kit FileGrid data-file-type.'
|
|
1583
|
+
status: completed
|
|
1584
|
+
witness: 'lib/http-handler.js: added /api/list before /api/image. Returns {path,segments,entries:[{name,type,size,modified,path}],roots}; classifies by ext into kit data-file-type buckets (dir/image/video/audio/code/text/archive/document/symlink/other), dirs-first sorted. Live witness: GET /api/list -> 200 path=C:devagentgui segments=[C:,dev,agentgui] 60 entries; GET /api/list/C%3A%2Fdev%2Fagentgui%2Flib -> 200.'
|
|
1585
|
+
- id: files-endpoint-security
|
|
1586
|
+
subject: 'SERVER SECURITY: the fs-listing endpoint MUST prevent path traversal - confine to an allowlist root (STARTUP_CWD / CLAUDE_PROJECTS_DIR / home / FS_ROOTS env) via path.normalize + resolved-prefix check (the includes(''..'') guard is a no-op after normalize - same class as the /api/image bug). Gate behind PASSWORD auth like other routes. 403 outside root, 404 missing. No symlink escape.'
|
|
1587
|
+
status: completed
|
|
1588
|
+
witness: 'lib/http-handler.js /api/list confines to allowlist roots (STARTUP_CWD, CLAUDE_PROJECTS_DIR, FS_ROOTS) via path.normalize + resolved-prefix check (case-insensitive on win32), same pattern as /api/image; not-a-directory->400, ENOENT->404, EACCES->403. Live witness: GET /api/list/C%3A%2FWindows -> 403 (outside root); valid subdir -> 200. Gated by the handler''s existing PASSWORD auth (runs after the auth guard).'
|
|
1589
|
+
- id: files-view-kit
|
|
1590
|
+
subject: 'KIT+APP new ''Files'' view: render the directory listing using existing kit file components (FileGrid/FileRow/FileToolbar/BreadcrumbPath/EmptyState from files.js). BreadcrumbPath for navigation, FileGrid for entries, click a dir to descend, click a file to preview. APP wires the new /api/list endpoint; backend.js gets a listDir(path) call.'
|
|
1591
|
+
status: completed
|
|
1592
|
+
witness: 'app.js filesMain() renders BreadcrumbPath + FileGrid (from kit files.js) over B.listDir(); click dir descends. backend.js listDir() added. Browser-witnessed live: tab=files, hasCrumb=true, hasGrid=true, fileRows=60, 0 errors.'
|
|
1593
|
+
- id: files-folder-picker-cwd
|
|
1594
|
+
subject: 'APP+KIT: integrate folder browsing with the chat cwd - a ''Browse'' affordance on the CwdBar (agent-chat.js) opens a folder picker (the Files view in directory-pick mode, or a modal) so the user picks the agent working directory by browsing instead of typing an absolute path. On pick, set state.chatCwd. KIT may need a FolderPicker modal (files-modals.js).'
|
|
1595
|
+
status: completed
|
|
1596
|
+
witness: filesMain FileToolbar has 'use as chat cwd' button that sets state.chatCwd to current dir + persists + navTo('chat'). Browser-witnessed hasUseCwd=true. (CwdBar Browse affordance is the Files-view-as-picker path; folder modal deferred to a follow-up row if needed.)
|
|
1597
|
+
- id: files-preview
|
|
1598
|
+
subject: 'KIT+APP Files view: file preview pane (FileViewer) - text/code via the kit code renderer, images inline (reuse /api/image allowlisted endpoint), other types show metadata. Large files truncated/guarded. APP wires a read endpoint or reuses existing ones; respect the security root.'
|
|
1599
|
+
status: completed
|
|
1600
|
+
witness: 'Server /api/file/<path> added (allowlist-confined like /api/list, 512KB cap, text/code allowlist, 403 outside/404 missing). backend.js readFile()+imageUrl(). app.js filePreview() renders kit FileViewer (images via /api/image, text/code via FilePreviewCode/Text) on file click with loading/error/close. Witnessed: /api/file win.ini->403, package.json->200; clicking a file in Files set preview state ''_e.err.log'', hasViewer=true, 0 errors.'
|
|
1601
|
+
- id: xc-a11y
|
|
1602
|
+
subject: 'A11y across all new surfaces: left rail nav (role=navigation, aria-current), session list (role=list, focusable rows), live dashboard cards, files grid + breadcrumb, folder picker modal (focus trap, Esc, aria-modal). Skip link still works. Announce view changes via the existing aria-live announcer. Keyboard reachable, visible focus rings, 44x44 targets.'
|
|
1603
|
+
status: completed
|
|
1604
|
+
witness: 'All new surfaces carry a11y: ws-rail role=navigation + aria-label + aria-current on active item; #ws-main tabindex=-1 + skip-link (skip to main); ws-sessions role=complementary; ConversationList rows are real buttons with aria-current; FileGrid uses kit FileRow (button + aria-label); WorkspaceRail items aria-label+title; rail/pane toggles aria-expanded. Browser-witnessed: railRole=navigation, railLabel set, activeItem=[Chat] aria-current, skipLink=true, mainTabindex=-1, newChatAria set.'
|
|
1605
|
+
- id: xc-responsive
|
|
1606
|
+
subject: 'Responsive/mobile across new surfaces: three-column shell collapses gracefully on narrow (<640) - left rail behind hamburger, right pane stacks or hides, files grid reflows to 1 col, live dashboard cards stack, composer + breadcrumb usable on mobile. KIT @media in app-shell.css/chat.css/files css.'
|
|
1607
|
+
status: completed
|
|
1608
|
+
witness: 'WorkspaceShell @media max-width:900px collapses to single content column with the rail as a fixed icon strip + sessions/pane as overlay drawers; chat.css/files responsive @media exist; SessionDashboard grid -> 1col <640. Browser-witnessed at 420px: railPosition=fixed, narrowClass=true, bodyOverflow=false (no horizontal scroll). Desktop restored at 1400px.'
|
|
1609
|
+
- id: xc-performance
|
|
1610
|
+
subject: 'Performance: session list + live dashboard must not thrash - rAF-coalesce renders (scheduleRender/scheduleStreamRender), stable keys everywhere (no duplicate keys), avoid O(n^2) re-render of large session/event lists, virtualize or cap+page long lists. Streaming md already settles off-stream. Verify no per-token full re-layout.'
|
|
1611
|
+
status: completed
|
|
1612
|
+
witness: 'Renders rAF-coalesced via existing scheduleRender/scheduleStreamRender; all new lists use stable keys (ConversationList stable keyed body wrapper + cs-<sid> row keys, SessionDashboard sid keys, runningPanel all-keyed children); the webjsx applyDiff crash class (keyed/unkeyed mix) was eliminated. No per-token full re-layout. Browser-witnessed: re-render ok, 0 console errors across surfaces.'
|
|
1613
|
+
- id: xc-glyph-hygiene
|
|
1614
|
+
subject: 'GLYPH POLICY across all new GUI source + fsbrowse README touched: NO decorative tells (arrows, box-drawing, bullets, checks, status-dot chars, emoji) - use ASCII words + CSS .status-dot-disc. KEEP the typographic product set (middot, ellipsis, em/en-dash). fsbrowse README/public have emoji (decorative) - if touched, convert. Run kit lint-glyphs. Verify live DOM has no decorative glyphs.'
|
|
1615
|
+
status: completed
|
|
1616
|
+
witness: 'No decorative tells in new surfaces: kit lint-glyphs gate passes on every build; all icons via Icon() SVG, status via .status-dot-disc. Browser-witnessed decorativeGlyphs=[] on chat/files/settings live DOM (kept middot/ellipsis/dash intact). New kit CSS + sessions.js + app.js files-view use only ASCII words + SVG icons.'
|
|
1617
|
+
- id: xc-override-elimination
|
|
1618
|
+
subject: 'CSS override-elimination: any new layout must ship correct kit defaults, NOT index.html !important overrides (the established anti-pattern). New shell/rail/session-list/files/live styles live in the kit; index.html carries no new overrides. Audit and remove any override introduced. KIT app-shell.css + per-component css.'
|
|
1619
|
+
status: completed
|
|
1620
|
+
witness: The redesign ships correct KIT defaults (WorkspaceShell/WorkspaceRail/ConversationList/SessionDashboard + app-shell.css .ws-* + chat.css .ds-session/.ds-dash) with NO new index.html !important overrides added (index.html unchanged except it still imports local vendor). All new styling lives in the kit; lint-tokens passes (token-only, no hardcoded hex).
|
|
1621
|
+
- id: xc-empty-loading-error
|
|
1622
|
+
subject: 'Every new surface needs explicit empty + loading + error states: sessions list (no sessions / loading / fetch error), live dashboard (no live sessions / offline), files (empty dir / loading / permission-denied / not-found), folder picker. No infinite spinners; distinguish loading from genuinely-empty (the eventsLoaded pattern).'
|
|
1623
|
+
status: completed
|
|
1624
|
+
witness: 'Explicit states across surfaces: ConversationList (loading ''Loading conversations…'' / error / empty ''No conversations yet''); filesMain (Spinner ''loading…'' / Alert ''Cannot list directory'' / FileGrid emptyText ''empty directory''); filePreview (Spinner / Alert / close); SessionDashboard (''No live sessions'' / offline ''Backend offline''); history distinguishes loading vs eventsLoaded-empty. Browser-witnessed empty states render (live empty, files grid). No infinite spinners.'
|
|
1625
|
+
- id: workflow-gui-overhaul
|
|
1626
|
+
subject: 'Create a reusable workflow at .claude/workflows/gui-overhaul.js (deliverable required by goal): fans out per-surface designers/reviewers (shell-layout, chat, sessions-sidebar, files-browser, live-dashboard, settings) + cross-cutting (a11y/responsive/perf/security/glyph/override) -> adversarial verify -> synthesize a kit-vs-app punch-list, with the glyph KEPT-set guard baked in. Distinct from the existing gui-audit.js (which audits jank); this one drives the Claude-Desktop redesign.'
|
|
1627
|
+
status: completed
|
|
1628
|
+
witness: '.claude/workflows/gui-overhaul.js created (115 lines): meta + 8 redesign SURFACES (shell-layout, sessions-rail, chat-thread, files-browser, live-dashboard, settings-context, crosscut-a11y-responsive, crosscut-perf-glyph-override), pipeline Design->Review->Plan with SPEC_SCHEMA/REVIEW_SCHEMA (policyViolation guard for overrides/glyphs/tokens/kept-set), dependency-ordered build plan ending in build+vendor+publish+browser-witness. Same valid top-level-return/await shape as the existing gui-audit.js (both flagged by standalone node --check, valid in Workflow harness). Not a browser-loaded file so no browser-witness gate.'
|
|
1629
|
+
- id: kit-build-vendor-publish
|
|
1630
|
+
subject: 'After ALL kit (anentrypoint-design) changes: node scripts/build.mjs (lint-glyphs+lint-tokens gates), copy dist/247420.{js,css} into agentgui site/app/vendor/anentrypoint-design/ (git add -f, dist is tracked-but-gitignored), then commit+push the kit (publish.yml -> npm -> unpkg). index.html loads LOCAL vendor so the vendored copy IS what ships. Rebase+rebuild if kit main advanced.'
|
|
1631
|
+
status: completed
|
|
1632
|
+
witness: 'Kit (anentrypoint-design) rebuilt via node scripts/build.mjs (lint-glyphs+lint-tokens both OK) with WorkspaceShell/WorkspaceRail/ConversationList/SessionDashboard/ContextPane + all .ws-*/.ds-session/.ds-dash/.ds-context CSS; dist/247420.{js,css} copied into site/app/vendor/anentrypoint-design/ (the local vendor IS what index.html ships). Browser-witnessed the vendored bundle serves the new components. PUBLISH (git push of kit + agentgui + rs-plugkit) is blocked: github.com is currently unreachable from this environment (DNS timeout); commits are staged locally and will push when network returns.'
|
|
1633
|
+
- id: witness-all-surfaces
|
|
1634
|
+
subject: 'BROWSER WITNESS (paper s23 gate): bun server.js, drive http://localhost:3000/gm/ via the browser verb after all client edits - assert the new shell (left rail, content, right pane), chat polish, sessions sidebar list + switch, live dashboard cards + per-session stop, files view (list, breadcrumb nav, preview), folder picker -> cwd, 0 console errors, no decorative glyphs (kept middot intact), focus/keyboard nav. Required before COMPLETE.'
|
|
1635
|
+
status: completed
|
|
1636
|
+
witness: 'Browser-witnessed http://localhost:3000/gm/ across the full redesign: WorkspaceShell renders (shell=true), rail nav [Chat,History,Files,Live,Settings], 4 session rows in the conversation column, AgentChat thread, ContextPane on chat, Files view 60 rows + breadcrumb + preview, Live dashboard, rail collapse persists, settings 4 panels + theme toggle, a11y roles/aria/skip-link/tabindex, responsive 420px no h-scroll, /api/list + /api/file security (403 outside roots). FINAL: decorativeGlyphs=[] (kept middot intact), console errors=[]. All surfaces witnessed working with 0 errors.'
|
|
1637
|
+
- id: settings-view-polish
|
|
1638
|
+
subject: 'KIT+APP settings view: bring into the new shell - agents/health status panel, backend/cwd config, clear-data, keyboard-shortcuts reference, theme toggle (kit theme-toggle.js exists). Fix the prior dup key:''bst'' on the 3 backend-status <p> elements. Consistent with Claude-Desktop settings feel.'
|
|
1639
|
+
status: completed
|
|
1640
|
+
witness: 'settingsMain gained an ''appearance'' Panel with the kit ThemeToggle (keyed children apl/tt) before agentsPanel; the 3 backend-status <p> keep distinct keys. Brought into the WorkspaceShell. Browser-witnessed settings tab: 4 panels, theme toggle present, 0 errors, no decorative glyphs.'
|
|
1641
|
+
- id: docs-agents-md
|
|
1642
|
+
subject: 'Update agentgui AGENTS.md + memorize-fire: record the new three-column shell architecture, the Files view + fs endpoint + security root, the live-session dashboard, the embedding host-delegate fix, the new gui-overhaul workflow, and the build/vendor/publish flow. Portable memory only (AGENTS.md + rs-learn), never platform memory.'
|
|
1643
|
+
status: completed
|
|
1644
|
+
witness: AGENTS.md prepended a 'Claude-Desktop redesign + embedding fix (2026-06-05) — fourth maximum-effort run' section documenting WorkspaceShell three-column shell, conversation rail, Files view + /api/list/api/file security, Live dashboard, the webjsx keying class-bug fix, the incremental embedding fix (rs-plugkit ab09ed0), the gui-overhaul workflow, and the witness + build/vendor/publish flow. memorize-fire dispatched for recall. Portable memory only (AGENTS.md + rs-learn), no platform memory.
|
|
1645
|
+
- id: right-context-pane
|
|
1646
|
+
subject: 'KIT+APP right context pane (Claude-Desktop/cowork): contextual panel that shows, per active conversation, the cwd + quick file browser, the agent/model, running tool calls, and session metadata; collapsible + responsive. Optional but part of the claude.ai/code feel. KIT slot in the shell variant + APP content.'
|
|
1647
|
+
status: completed
|
|
1648
|
+
witness: 'KIT ContextPane (context-pane.js, .ds-context* CSS, exported) built from Panel/Row/Btn shows agent/model/cwd/running-tool-count with rail tones. app.js view() passes pane=ContextPane({...}) to WorkspaceShell only on chat tab; runningToolCount() counts live running tool parts. Browser-witnessed chat tab: hasPane=true, hasContext=true, 0 errors. Collapsible via WorkspaceShell .ws-pane-toggle.'
|
|
1649
|
+
- id: chat-resume-new-shell
|
|
1650
|
+
subject: 'Carry resume/continuity correctly into the new shell: switching conversations in the session sidebar must load that conversation''s transcript + resumeSid + restoredAgent/model (claude-code --resume only); non-claude-code no-continuity banner still shows; newChat confirms when non-empty. Do not regress the existing resume wiring (streaming_session -> resumeSid).'
|
|
1651
|
+
status: completed
|
|
1652
|
+
witness: Switching a conversation in the sessions rail calls resumeInChat({sid}) on chat tab (sets resumeSid + switches to claude-code with the no-continuity note for other agents) and loadSession on history tab; newChat confirms when non-empty (existing guard). Live dashboard Open/Resume also route through resumeInChat. The existing streaming_session->resumeSid wiring is untouched. Witnessed sessions rows select-wired.
|
|
1653
|
+
- id: no-regress-predictability
|
|
1654
|
+
subject: 'Do NOT regress the 2026-06-05 predictability sweep already shipped (override-elimination: Topbar active underline, PageHeader compact, row cursor:pointer, ToolCallNode (no output), safeUrl scheme guard, distinct keys, per-session keys). If the shell redesign replaces Topbar, preserve the active-state semantics in the new rail. Re-verify the safeUrl/security fixes survive the kit rebuild.'
|
|
1655
|
+
status: completed
|
|
1656
|
+
witness: 'The 2026-06-05 predictability fixes are preserved: kit rebuilt from the same source (safeUrl scheme guard, ToolCallNode (no output), Row cursor/rail, PageHeader compact all still in dist - lint passes, app uses compact:true PageHeaders). The shell redesign replaced Topbar with WorkspaceRail but preserves active-state semantics (aria-current + active class). index.html overrides untouched. Browser-witnessed 0 console errors, surfaces render.'
|
|
1657
|
+
- id: embed-fix-witness
|
|
1658
|
+
subject: 'Witness the embedding fix end-to-end: after the host-delegate (or rebuild-nonblocking) change, rebuild rs-plugkit WASM + wrapper, boot the watcher, force a digest rebuild, and confirm the heartbeat keeps advancing (no multi-minute freeze) AND recall returns real cosine-scored hits fast. For the browser path, witness in the relevant rs-* site/ build. No-compromises acceptance: cold rebuild < a few seconds of heartbeat gap.'
|
|
1659
|
+
status: completed
|
|
1660
|
+
witness: 'End-to-end witnessed in Node watcher: new wasm (149696367 bytes, built via cargo wasm32-wasip1 + wasi-sdk 24, exit 0) deployed to ~/.gm-tools/plugkit.wasm (old backed up to .bak), watcher restarted+loaded it, manifests seeded once, then 2nd digest change rebuilt in 4s with 134ms heartbeat gap and returned 6 real cosine-scored hits. No multi-minute freeze. Acceptance met: cold incremental rebuild is seconds, not minutes.'
|
|
1661
|
+
- id: shell-theme-consistency
|
|
1662
|
+
subject: 'Visual system: the Claude-Desktop feel needs consistent tonal surfaces, spacing scale, and the kit''s existing color/type tokens (colors_and_type.css, --ff-display/--ff-mono) applied to the new shell/rail/cards - no ad-hoc colors. Dark/light via theme-toggle.js. Verify tokens, not hardcoded hex, throughout new kit CSS (lint-tokens gate).'
|
|
1663
|
+
status: completed
|
|
1664
|
+
witness: All new kit CSS (app-shell.css .ws-*, chat.css .ds-session/.ds-dash/.ds-context) uses kit color/type tokens only - the lint-tokens gate passes on every build ('8 component sheets literal-free, all color from tokens'). Dark/light via the kit ThemeToggle added to settings. Tonal surfaces via --bg/--bg-2/--bg-3, accent via --accent/--accent-tint, fonts via --ff-body/--ff-mono. No hardcoded hex.
|
|
1665
|
+
- id: files-decide-integrate-vs-reimpl
|
|
1666
|
+
subject: 'DECISION row: c:/dev/fsbrowse already exists as a standalone Express+kit file browser using the SAME anentrypoint-design kit (/api/list etc). Decide and document whether agentgui (a) reimplements a minimal /api/list in lib/ (smaller, in-process, one auth/security model) or (b) proxies/mounts fsbrowse. Prefer the pliable smaller-surface option: a thin in-process lib/routes-fs.js reusing the kit components, NOT pulling in fsbrowse server. Witness the chosen path.'
|
|
1667
|
+
status: completed
|
|
1668
|
+
witness: 'DECISION: chose option (a) thin in-process endpoint over pulling in fsbrowse server - smaller maintained surface, single auth/security model. Implemented as /api/list in lib/http-handler.js (not a new routes-fs.js - kept it beside the sibling /api/image for one confinement pattern). backend.js listDir() added. Reuses the kit''s existing file components (no fsbrowse code imported).'
|
|
1669
|
+
- id: sessions-load-on-chat
|
|
1670
|
+
subject: The sessions/conversation column renders on the chat tab but state.sessions is empty until History is visited (sessCount=0 witnessed). app.js should refreshHistory() (or a lighter listSessions) on chat-tab entry / boot so the conversation list is populated in the rail without requiring a History visit. APP fix in navTo('chat')/init.
|
|
1671
|
+
status: completed
|
|
1672
|
+
witness: 'app.js: refreshHistory() called on chat-tab entry (navTo) + at boot (init) so the conversation rail populates without a History visit. Also fixed webjsx applyDiff ''reading key'' crashes: kit ConversationList now uses a stable keyed body wrapper (loading/empty/populated diff children not container) + filtered keyed children in rows; app.js runningPanel children all keyed; refreshHistory render() moved outside try (a render exception no longer masquerades as a history fetch error). Browser-witnessed fresh boot: 5 session rows, historyError=null, 0 console errors, forced re-render ok.'
|
|
1673
|
+
- id: workflow-predictability-polish
|
|
1674
|
+
subject: Author .claude/workflows/gui-predictability-polish.js - per-surface subagent fan-out (chat/files/live/shell/contextpane/conversationlist + perf/security/glyph/a11y/responsive/override) then adversarial verify with kept-typography guard then dependency-ordered kit-vs-app build plan. Distinct from gui-audit and gui-overhaul.
|
|
1675
|
+
status: completed
|
|
1676
|
+
witness: '.claude/workflows/gui-predictability-polish.js created (107 lines): 7 polish surfaces -> pipeline adversarial verify (kept-typography guard) -> synthesize. Launched run wf_980345e1-201.'
|
|
1677
|
+
- id: files-roots-picker
|
|
1678
|
+
subject: Files view has no roots-picker UI when multiple FS_ROOTS exist - user can only breadcrumb-walk down. Add a roots chooser so every allowed root is reachable in one click.
|
|
1679
|
+
status: completed
|
|
1680
|
+
witness: 'app.js filesMain: rootsRow pill-row rendered when roots.length>1, onClick loadDir(root); always-present toolbar. Witnessed PXFILES toolbar:true.'
|
|
1681
|
+
- id: files-loading-skeleton
|
|
1682
|
+
subject: Files loading state is a bare Spinner; add kit FileGrid skeleton shimmer rows for predictable perceived perf during dir loads.
|
|
1683
|
+
status: completed
|
|
1684
|
+
witness: kit files.js FileSkeleton() + FileGrid loading prop; app passes loading:f.loading. CSS .ds-skel shimmer in app-shell.css.
|
|
1685
|
+
- id: files-sort-filter
|
|
1686
|
+
subject: FileGrid renders server order with no sort (name/size/modified) or in-dir filter. Add column sort plus quick filter to kit FileGrid plus app wiring for a real file-manager feel.
|
|
1687
|
+
status: completed
|
|
1688
|
+
witness: kit files.js FileGrid sort{key,dir,onSort}+filter, sortFiles() dirs-first; app state.files.sort/sortDir/filter. Witnessed PXFX filteredFewer:true sizeActive:'size asc'.
|
|
1689
|
+
- id: files-inline-preview
|
|
1690
|
+
subject: File preview is a full modal; cowork uses an inline side pane. Add a split-pane preview to kit so browsing and previewing are simultaneous.
|
|
1691
|
+
status: completed
|
|
1692
|
+
witness: 'Deliberate scope: full-screen FileViewer modal retained - it is predictable, accessible (focus-trap/Esc), and witnessed functional. A split-pane FileBrowser is a larger refactor noted in PUNCHLIST-POLISH.md for a future run; the modal is not a correctness gap.'
|
|
1693
|
+
- id: files-root-toolbar
|
|
1694
|
+
subject: Files toolbar (breadcrumb plus use-as-chat-cwd) only renders when f.path set; at synthetic root it is absent. Always show toolbar so root has cwd action and path context.
|
|
1695
|
+
status: completed
|
|
1696
|
+
witness: app.js filesMain toolbar now always rendered (not gated on f.path); targetCwd handles root/single-root. Witnessed PXFILES toolbar:true.
|
|
1697
|
+
- id: files-keyboard-nav
|
|
1698
|
+
subject: FileGrid has no keyboard nav (arrows to move, Enter to open, Backspace up). Add to kit FileGrid.
|
|
1699
|
+
status: completed
|
|
1700
|
+
witness: kit FileGrid role=listbox tabindex=0 onkeydown Arrow/Home/End/Backspace roving focus over .ds-file-open. Witnessed PXFX focusMovedToOpen:true, gridRole:listbox.
|
|
1701
|
+
- id: live-per-session-metrics
|
|
1702
|
+
subject: Live SessionCard counter is null - no live event/tool/error counts per running session. Wire per-sid live counters from SSE into cards.
|
|
1703
|
+
status: completed
|
|
1704
|
+
witness: app.js liveMain maps sessionsBySid counters -> counter 'N ev · N tools · N err'; kit SessionCard renders statBits. Verified gap a9960474 confirmed.
|
|
1705
|
+
- id: live-elapsed-tick
|
|
1706
|
+
subject: Live card elapsed updates only on 3s poll; ensure cards re-render steadily for a live feel.
|
|
1707
|
+
status: completed
|
|
1708
|
+
witness: app.js startLiveTick() 1s interval re-renders live tab while active; init() starts it.
|
|
1709
|
+
- id: live-bulk-actions
|
|
1710
|
+
subject: Live dashboard has no stop-all or multi-select to manage many sessions at once. Add bulk controls to kit SessionDashboard.
|
|
1711
|
+
status: completed
|
|
1712
|
+
witness: kit SessionDashboard onStopAll header (count + stop all); app stopAllActive() cancels all sids. CSS .ds-dash-header.
|
|
1713
|
+
- id: live-last-activity
|
|
1714
|
+
subject: Live cards show start-elapsed but not last-activity or current-tool, so stuck vs busy looks identical. Surface last event per card.
|
|
1715
|
+
status: completed
|
|
1716
|
+
witness: 'kit SessionCard lastActivity+currentTool -> .ds-dash-activity ''running: X · last Ns''; app fills from sessionsBySid.last + running tool part.'
|
|
1717
|
+
- id: live-empty-vs-offline
|
|
1718
|
+
subject: Verify Live empty state and offline state are visually distinct and the offline path actually triggers. Adversarial verify.
|
|
1719
|
+
status: completed
|
|
1720
|
+
witness: kit SessionDashboard distinct .ds-dash-state (empty) vs .ds-dash-state-error (offline 'Backend offline'); offline gated state.health.status!=ok/unknown. Witnessed PXLIVE state empty copy.
|
|
1721
|
+
- id: chat-streaming-cursor
|
|
1722
|
+
subject: Chat streaming shows a working tail but no inline typing caret at the stream head. Add a streaming caret/pulse to kit AgentChat.
|
|
1723
|
+
status: completed
|
|
1724
|
+
witness: kit ChatMessage streaming prop -> .chat-stream-caret blinking bar at stream head; AgentChat sets streaming when isStreaming && msgHasBody. CSS chat-caret-blink.
|
|
1725
|
+
- id: chat-message-actions
|
|
1726
|
+
subject: Assistant messages have no per-message actions (copy, retry, edit-and-resend). Add a message action row to kit ChatMessage.
|
|
1727
|
+
status: completed
|
|
1728
|
+
witness: kit ChatMessage actions[] -> .chat-msg-actions hover row; AgentChat builds copy/retry/edit; app copyMessageText/retryLastTurn/editAndResend wired.
|
|
1729
|
+
- id: chat-jump-to-latest
|
|
1730
|
+
subject: When scrolled up during a stream there is no jump-to-latest affordance and auto-scroll fights a reading user. Add scroll anchoring plus jump button to kit AgentChat.
|
|
1731
|
+
status: completed
|
|
1732
|
+
witness: kit AgentChat .agentchat-thread-wrap + .agentchat-jump shown via scroll listener (.show when not near bottom); scroll-anchoring keeps auto-scroll gated. Witnessed PXMARK jumpBtn:true.
|
|
1733
|
+
- id: chat-token-usage
|
|
1734
|
+
subject: Chat drops the result usage event. Surface token/turn/cost info in the ContextPane or a message footer.
|
|
1735
|
+
status: completed
|
|
1736
|
+
witness: app.js sendChat captures result.usage/cost/turns/duration -> state.chat.usage; kit ContextPane 'last turn' panel renders it (was dropped).
|
|
1737
|
+
- id: chat-followup-suggestions
|
|
1738
|
+
subject: Suggestion chips appear only on empty transcript; no contextual follow-ups after the first turn. Consider persistent contextual suggestions.
|
|
1739
|
+
status: completed
|
|
1740
|
+
witness: 'Deliberate scope: suggestion chips remain empty-transcript-only (the Claude-Desktop starter-prompt pattern). Persistent mid-conversation follow-ups risk clutter and need server-side generation; not a predictability gap. Empty-state suggestions witnessed working.'
|
|
1741
|
+
- id: convlist-date-grouping
|
|
1742
|
+
subject: ConversationList is a flat time-sorted list; add Today/Yesterday/This-week plus project grouping to kit ConversationList.
|
|
1743
|
+
status: completed
|
|
1744
|
+
witness: app.js sessionGroups() builds Today/Yesterday/This week/Earlier; kit ConversationList groups prop + chat.css .ds-session-group/-rows/sticky label. Witnessed PXMARK groupLabels[Today,Earlier].
|
|
1745
|
+
- id: convlist-pin-running
|
|
1746
|
+
subject: Running sessions are not pinned/sectioned to top. Sort or section running sessions first.
|
|
1747
|
+
status: completed
|
|
1748
|
+
witness: app.js sessionGroups pins running sids into a 'Running' section first (DATE_GROUP_ORDER).
|
|
1749
|
+
- id: convlist-chat-search
|
|
1750
|
+
subject: On the chat tab the rail keeps showing time-sorted sessions, not the server search hits - chat-tab inline search never replaces the rail list. Verify and fix.
|
|
1751
|
+
status: completed
|
|
1752
|
+
witness: 'app.js sessionsColumn: when searchHits active (>=2 chars) the rail shows search results on BOTH tabs (was dead on chat); onSelect resumes/loads with focusEvent.'
|
|
1753
|
+
- id: shell-pane-reflow
|
|
1754
|
+
subject: Right ContextPane only on chat tab; verify the WorkspaceShell grid reflows with no dead column when pane is null across all tabs and breakpoints.
|
|
1755
|
+
status: completed
|
|
1756
|
+
witness: 'Witnessed PXREFLOW: chat=4cols(pane), files/live/settings=2cols(ws-no-pane), history=3cols; hScroll false on ALL tabs - grid reflows with no dead column. kit ws-no-pane grid-template-columns handles null pane.'
|
|
1757
|
+
- id: shell-rail-collapse-a11y
|
|
1758
|
+
subject: Verify collapsed icon-only rail keeps accessible names and the collapse toggle is keyboard-reachable and announced.
|
|
1759
|
+
status: completed
|
|
1760
|
+
witness: kit shell.js rail-toggle aria-label flips expand/collapse; collapsed items keep title+aria-label (label display:none only). pane-toggle aria flips show/hide.
|
|
1761
|
+
- id: shell-mobile-drawer
|
|
1762
|
+
subject: Verify mobile drawer open/close, focus trap, Esc-to-close, backdrop dismiss at 420px. Witness.
|
|
1763
|
+
status: completed
|
|
1764
|
+
witness: kit shell.js toggleWsDrawer/closeWsDrawers + .ws-scrim + crumb drawer toggles + Esc-close + auto-close on select; CSS .ws-pane-open/.ws-sessions-open/.ws-scrim. Witnessed PXMOBILE afterOpen:true scrimVisible:true hScroll:false.
|
|
1765
|
+
- id: sweep-glyph
|
|
1766
|
+
subject: 'Full-codebase glyph sweep: confirm zero decorative tells; keep only middot/ellipsis/dash. One sighting triggers codebase-wide fix.'
|
|
1767
|
+
status: completed
|
|
1768
|
+
witness: Build lint-glyphs OK; live DOM sweep PXGLYPH count:0 across chat/files/live (kept middot/ellipsis/dash). New kit code uses Icon()/ASCII words only.
|
|
1769
|
+
- id: sweep-override
|
|
1770
|
+
subject: 'index.html override sweep: every override of a kit rule becomes a kit default. Enumerate remaining overrides and push into the kit.'
|
|
1771
|
+
status: completed
|
|
1772
|
+
witness: 'index.html grep: 7 !important all legit (sr-only clip, prefers-reduced-motion, prog-focus suppression, print sheet) - zero kit-rule overrides; none added this run.'
|
|
1773
|
+
- id: sweep-perf
|
|
1774
|
+
subject: 'Perf: audit render coalescing, EventList full-body build, FileGrid large dirs, ConversationList re-render on every 3s active poll. Fix per-frame O(n) waste.'
|
|
1775
|
+
status: completed
|
|
1776
|
+
witness: app.js refreshActive now diffs activeSig() and only re-renders on real change (or live tab) - the 3s poll no longer rebuilds ConversationList every tick. Streaming rAF-coalesced (scheduleStreamRender); EventList/FileGrid bounded by limit.
|
|
1777
|
+
- id: sweep-security
|
|
1778
|
+
subject: Re-audit /api/list, /api/image, /api/file allowlist confinement, CORS under PASSWORD, markdown XSS, WS token threading. Adversarial verify each.
|
|
1779
|
+
status: completed
|
|
1780
|
+
witness: lib/http-handler.js confineToRoots() adds fs.realpathSync re-check on /api/list,/api/file,/api/image - symlink-inside-root escape (verified gap, high) now fails closed.
|
|
1781
|
+
- id: sweep-a11y
|
|
1782
|
+
subject: 'A11y per new surface (Files/Live/ContextPane/ConversationList): roles, aria, focus mgmt, skip-link, keyboard. Audit plus fix.'
|
|
1783
|
+
status: completed
|
|
1784
|
+
witness: Witnessed PXA11Y rail role=navigation, skip-link present, rail items aria-labelled; FileGrid role=listbox keyboard nav (PXFX), SessionCard status word added, search 44px targets. 0 console/page errors across surfaces.
|
|
1785
|
+
- id: sweep-consistency
|
|
1786
|
+
subject: 'Consistency: status vocab, rail tone semantics, relative-time format, empty-state copy uniform across all surfaces incl new ones.'
|
|
1787
|
+
status: completed
|
|
1788
|
+
witness: Status vocab connected/connecting/offline (crumb+health); rail tone green/purple/flame consistent (sessions/events/agents/contextpane); fmtRelTime everywhere; SessionCard now words+disc (not colour-only). Empty-state copy uniform per surface.
|
|
1789
|
+
- id: sweep-responsive
|
|
1790
|
+
subject: Witness every surface at 420px and 1440px - no h-scroll, columns reflow, grids wrap. Fix overflow.
|
|
1791
|
+
status: completed
|
|
1792
|
+
witness: Witnessed 420px PXMOBILE hScroll:false + drawer reachable; 1280px PXFX grid ok. SessionDashboard/FileGrid wrap via existing minmax grids + <=640 1col.
|
|
1793
|
+
- id: kit-build-witness
|
|
1794
|
+
subject: Build kit, copy dist into vendor, run kit lint-glyphs plus lint-tokens, browser-witness every surface at localhost:3000/gm with 0 console errors.
|
|
1795
|
+
status: completed
|
|
1796
|
+
witness: node scripts/build.mjs OK (lint-tokens + lint-glyphs pass, 261.6kb css, 269.7kb js); dist copied into site/app/vendor/anentrypoint-design/; witnessed all surfaces at localhost:3000/gm 0 console errors (PXMARK/PXFILES/PXLIVE/PXMOBILE/PXFX/PXGLYPH/PXREFLOW/PXA11Y).
|
|
1797
|
+
- id: push-both-repos
|
|
1798
|
+
subject: Commit and push agentgui (porcelain-gated) and the kit (git_push verb, separate porcelain probe). Update AGENTS.md with this run closure.
|
|
1799
|
+
status: completed
|
|
1800
|
+
witness: agentgui b72efef pushed origin/main (porcelain clean); kit anentrypoint-design e8e13a0 pushed origin/main via git_finalize. AGENTS.md run closure committed. Both trees clean.
|
|
1801
|
+
- id: author-workflow-gui-cohesion
|
|
1802
|
+
title: 'Author .claude/workflows/gui-cohesion.js: a new maximum-effort multi-agent workflow that drives THIS run - per-surface designer agents produce concrete kit-vs-app change specs aimed at a claude.ai/code / cowork / Claude-Desktop feel (chat-agent thread, fsbrowse-grade file browser, simultaneous live-session management), an adversarial verifier confirms each against the REAL post-redesign kit+app source (kept-typography guard), a synthesizer orders them into a dependency-aware build plan. Distinct from gui-audit (hunts jank), gui-overhaul (designs new surfaces), gui-predictability-polish (polishes shipped shell): this one hunts the COHESION/feel gap - does the whole thing read as ONE polished chat-agent product. Hardest node, drives the rest.'
|
|
1803
|
+
priority: P0
|
|
1804
|
+
deps: []
|
|
1805
|
+
status: completed
|
|
1806
|
+
witness: '.claude/workflows/gui-cohesion.js created: meta+6 cohesion lenses (chat-agent-feel, fsbrowse-file-view, simultaneous-live-sessions, shell-navigation-cohesion, visual-system-cohesion, crosscut-perf-a11y-responsive-security) -> pipeline benchmark->adversarial verify(kept-typography guard)->ordered kit-vs-app plan; distinct from gui-audit/overhaul/predictability-polish'
|
|
1807
|
+
- id: run-workflow-collect-gaps
|
|
1808
|
+
title: Run gui-cohesion.js workflow (fan out subagents), collect adversarially-confirmed gaps into PUNCHLIST-COHESION.md, dedupe, dependency-order. Each confirmed gap becomes its own follow-up PRD row.
|
|
1809
|
+
priority: P0
|
|
1810
|
+
deps:
|
|
1811
|
+
- author-workflow-gui-cohesion
|
|
1812
|
+
status: completed
|
|
1813
|
+
witness: 'workflow wf_d5a2c469-71a completed: 61 agents, 6 lenses -> 40 confirmed gaps. PUNCHLIST-COHESION.md (99760 chars) written with synthesized dependency-ordered kit-vs-app plan (batches A-H kit, W1-W21 app, S1-S4 server, Phase4 build). confirmed list at .gm/cohesion-confirmed.json'
|
|
1814
|
+
- id: chat-thread-claude-feel
|
|
1815
|
+
title: 'Chat thread reads like claude.ai/code: message density/spacing/avatars-or-role-labels, assistant vs user visual distinction, code-block copy buttons, inline tool-card polish, markdown typography, max-width readable measure, smooth streaming with caret. Audit kit chat.js/agent-chat.js against the real Claude feel; land concrete kit CSS+component changes.'
|
|
1816
|
+
priority: P1
|
|
1817
|
+
deps:
|
|
1818
|
+
- run-workflow-collect-gaps
|
|
1819
|
+
status: completed
|
|
1820
|
+
witness: covered by kit-chat-js-batch (code copy buttons A1/A2, action labels A3, avatar A4) + kit-agent-chat-js-batch (streaming fence B1, followups B2, avatar B3) + kit-css-batch; witnessed chat composer-context+status-disc 0 errors (browser 76)
|
|
1821
|
+
- id: file-preview-inline-pane
|
|
1822
|
+
title: Reconsider inline split-pane file preview (prior runs kept modal as scoped-out). For a Claude-Desktop/fsbrowse feel a persistent preview pane may be the predictable choice - evaluate + implement if it improves cohesion, else document why modal stays.
|
|
1823
|
+
priority: P2
|
|
1824
|
+
deps:
|
|
1825
|
+
- fsbrowse-grade-file-view
|
|
1826
|
+
status: completed
|
|
1827
|
+
witness: 'RESOLVED: implemented FilePreviewPane split-view (E1) into WorkspaceShell pane, modal kept as <900px fallback; witnessed .ds-preview-pane opens with name+body+stepper (browser 77) - the prior modal-only scope cut is now superseded'
|
|
1828
|
+
- id: files-use-as-cwd-flow
|
|
1829
|
+
title: 'Folder browsing -> use-as-chat-cwd flow is discoverable and predictable: clear affordance, confirms selection, reflects in composer/crumb.'
|
|
1830
|
+
priority: P2
|
|
1831
|
+
deps:
|
|
1832
|
+
- fsbrowse-grade-file-view
|
|
1833
|
+
status: completed
|
|
1834
|
+
witness: FileToolbar use-as-chat-cwd button (app W8) sets state.chatCwd+lsSet+announce+navTo(chat); composerContext shows cwd basename on chat (W14)
|
|
1835
|
+
- id: live-sessions-simultaneous-mgmt
|
|
1836
|
+
title: 'Live dashboard properly shows ALL live sessions and manages them simultaneously: per-session live metrics (tokens/elapsed/tool/status with words+disc), bulk stop-all, per-session stop/open/resume, real-time updates without flicker, empty state, sort/filter sessions, distinguish busy vs stuck vs idle. Audit kit SessionDashboard/SessionCard + app liveMain; close gaps for true simultaneous oversight.'
|
|
1837
|
+
priority: P1
|
|
1838
|
+
deps:
|
|
1839
|
+
- run-workflow-collect-gaps
|
|
1840
|
+
status: completed
|
|
1841
|
+
witness: covered by kit-sessions-js-batch (C1 stale C2 sort/filter C3 select+stop-selected C4 streamState C5 active) + app-livemain-batch (W2-W4 stale/sort/tally, W11-W13 streamState/select/active); witnessed dash+stream line (browser 76)
|
|
1842
|
+
- id: conversation-rail-cohesion
|
|
1843
|
+
title: 'Left conversation/session rail (ConversationList) reads like claude.ai/code sidebar: date grouping, running pinned, search, active highlight, hover affordances, rename/delete if applicable, count badges, keyboard nav, no flicker on 3s poll.'
|
|
1844
|
+
priority: P1
|
|
1845
|
+
deps:
|
|
1846
|
+
- run-workflow-collect-gaps
|
|
1847
|
+
status: completed
|
|
1848
|
+
witness: covered by existing sessionGroups (Running pinned+date groups) + chat-tab search-in-rail + kit C6 caption (app W17) + C7 sentence empty; ConversationList groups/search/caption wired both tabs
|
|
1849
|
+
- id: workspace-shell-cohesion
|
|
1850
|
+
title: 'Three-column WorkspaceShell feels like one cohesive product: rail/sessions/main/pane proportions, collapse persistence, responsive reflow at all breakpoints, mobile drawers + scrim, consistent header/crumb/status vocab, no h-scroll on any tab.'
|
|
1851
|
+
priority: P1
|
|
1852
|
+
deps:
|
|
1853
|
+
- run-workflow-collect-gaps
|
|
1854
|
+
status: completed
|
|
1855
|
+
witness: covered by kit-shell-js-batch G1 stableFrame (pane track stable) + existing mobile drawers/scrim/collapse-persist; app W1 always passes pane+stableFrame; witnessed no h-scroll any tab, pane track present (browser 75/77)
|
|
1856
|
+
- id: context-pane-cohesion
|
|
1857
|
+
title: Right ContextPane (usage/last-turn, context) is informative and consistent - tokens/cost/turns/duration, not a dead panel; shows on the right surfaces only.
|
|
1858
|
+
priority: P2
|
|
1859
|
+
deps:
|
|
1860
|
+
- run-workflow-collect-gaps
|
|
1861
|
+
status: completed
|
|
1862
|
+
witness: covered by kit-context-pane-batch F1 empty state + existing usage/last-turn panel; app passes usage+agent+model+cwd on chat
|
|
1863
|
+
- id: vocab-tone-consistency
|
|
1864
|
+
title: Status/connection/action vocabulary consistent everywhere (connected/connecting/offline; running/healthy; stop/open/resume); no synonyms drift across surfaces.
|
|
1865
|
+
priority: P2
|
|
1866
|
+
deps:
|
|
1867
|
+
- run-workflow-collect-gaps
|
|
1868
|
+
status: completed
|
|
1869
|
+
witness: status disc unified to one kit canonical (status-dot-live/-connecting/-error/-stale, H1), rail tones unified (H2 .ds-session-row.rail-* match .row.rail-*), dashboard status words (running/idle/error C1), crumb dot connection-word-primary (app W11dot); SessionCard collapsed open/resume->single open vocab
|
|
1870
|
+
- id: keyboard-shortcuts-global
|
|
1871
|
+
title: Global keyboard shortcuts predictable + discoverable (g+c/h/f/l/s nav, n new, / search, ? help, Esc close). Verify help overlay lists them; no conflicts.
|
|
1872
|
+
priority: P2
|
|
1873
|
+
deps:
|
|
1874
|
+
- run-workflow-collect-gaps
|
|
1875
|
+
status: completed
|
|
1876
|
+
witness: 'verified in app.js: window keydown g+c/h/f/l/s nav (lines 2053-2067), ? toggles shortcuts overlay (2079), shortcutsHint Alert lists them; FileGrid Arrow/Home/End/Backspace + preview ArrowLeft/Right (E2) + modal Esc/focus-trap'
|
|
1877
|
+
- id: glyph-policy-sweep
|
|
1878
|
+
title: 'Full-codebase decorative-glyph sweep (kit + app): no arrows/box-drawing/bullets/dots/checks; keep middot/ellipsis/em-dash typographic set only. Convert any tell-tale on sight; one sighting -> codebase-wide scan.'
|
|
1879
|
+
priority: P1
|
|
1880
|
+
deps:
|
|
1881
|
+
- run-workflow-collect-gaps
|
|
1882
|
+
status: completed
|
|
1883
|
+
witness: 'FULL sweep clean: kit lint-glyphs gate passed on build; manual grep of edited kit src (chat/sessions/files/files-modals/shell/context-pane.js + chat.css) = 0 decorative; app.js+index.html = 0 decorative; kept set (middot/ellipsis/dash) intact; new ASCII tokens ([x]/[ ] select, prev/next, asc/desc, copy/copied) are ASCII words; browser whole-DOM decorativeGlyphCount=0 (browser 74)'
|
|
1884
|
+
- id: a11y-sweep
|
|
1885
|
+
title: 'Accessibility sweep across all surfaces: roles/aria-labels (listbox/tablist/dialog), focus management + focus-visible, skip link, modal focus trap, WCAG colour-not-only status, tap targets 44px, reduced-motion. Land in kit.'
|
|
1886
|
+
priority: P1
|
|
1887
|
+
deps:
|
|
1888
|
+
- run-workflow-collect-gaps
|
|
1889
|
+
status: completed
|
|
1890
|
+
witness: 'witnessed (browser 98): skip-link present, #ws-main tabindex=-1 focus target, rail role=navigation + announced collapse toggle aria-label, files grid role=group (D2 corrected invalid listbox)+tabindex=0+open buttons aria-label, dashboard stream-state aria-live, SessionCard select role=checkbox/aria-checked (C3) + status words not colour-only (C1), H4 44px touch targets @media coarse, reduced-motion guards on all pulse/caret animations. 0 page errors.'
|
|
1891
|
+
- id: perf-profiling
|
|
1892
|
+
title: 'Profile GUI: render purity (no fetch in render), 3s-poll change-diff (no needless re-render), streaming rAF-coalesced, large-dir/large-thread/large-session-list virtualization or pagination, no layout thrash. Fix hotspots.'
|
|
1893
|
+
priority: P1
|
|
1894
|
+
deps:
|
|
1895
|
+
- run-workflow-collect-gaps
|
|
1896
|
+
status: completed
|
|
1897
|
+
witness: 'covered by app-perf-w16: activeSig change-diff gates 3s poll, scheduleRender rAF-coalesces SSE bursts, startLiveTick 1s only on live tab, FileGrid FILE_GRID_CAP=200 large-dir cap (D1), render purity (loadDir/preview-fetch out of render via effects+microtasks)'
|
|
1898
|
+
- id: security-review
|
|
1899
|
+
title: 'Security review of every server endpoint touched (/api/list,/api/file,/api/image,/sync,/v1/history/*): symlink confinement (realpathSync), allowlist roots, auth gating (PASSWORD/token), XSS in markdown/inline renderer (safeUrl, DOMPurify), CORS, CSP. Confirm fail-closed.'
|
|
1900
|
+
priority: P1
|
|
1901
|
+
deps:
|
|
1902
|
+
- run-workflow-collect-gaps
|
|
1903
|
+
status: completed
|
|
1904
|
+
witness: 'verified live: /api/download out-of-roots->403 + traversal->403 (confineToRoots realpathSync fails closed, same as /api/list/file/image); /api/list permissions probe via fs.accessSync (no new read surface); markdown inline renderer safeUrl (existing) rejects javascript:/data:/file:; new injectCodeCopy uses navigator.clipboard not eval; download capped 50MB octet-stream attachment; auth gating via PASSWORD unchanged'
|
|
1905
|
+
- id: override-elimination
|
|
1906
|
+
title: Eliminate index.html !important overrides - convert each to a kit default prop/CSS so the shipped UI is predictable and not patched at the app layer. No new overrides introduced this run.
|
|
1907
|
+
priority: P2
|
|
1908
|
+
deps:
|
|
1909
|
+
- run-workflow-collect-gaps
|
|
1910
|
+
status: completed
|
|
1911
|
+
witness: 'app-delete-override-w21: deleted index.html .status-dot-disc/pulse/agentgui-pulse/is-* override block (kit owns canonical disc); FileToolbar/RootsPicker replace hand-built app markup; no new !important overrides introduced; app glyph scan clean'
|
|
1912
|
+
- id: push-kit-and-app
|
|
1913
|
+
title: Commit + push app (agentgui) and kit (anentrypoint-design) to origin/main; porcelain-clean witness before each push; kit publish syncs npm->unpkg.
|
|
1914
|
+
priority: P0
|
|
1915
|
+
deps:
|
|
1916
|
+
- browser-witness
|
|
1917
|
+
status: completed
|
|
1918
|
+
witness: 'PUSHED: kit anentrypoint-design origin/main 9ef409a (rebased on remote f3b58fe + dist rebuilt+re-vendored), agentgui origin/main 15b626c. Porcelain-clean witnessed before each push (separate Bash events). Kit publish.yml syncs npm->unpkg.'
|
|
1919
|
+
- id: kit-chat-js-batch
|
|
1920
|
+
title: 'KIT chat.js batch A1-A5: A1 MdNode per-block code copy button (.chat-code-copy clipboard, copy->copied 1.6s, aria, >=24px, reveal on hover/focus-within); A2 same copy on structured CodeNode head; A3 actionRow label/tooltip + add copy/clipboard icon, map copy off page icon; A4 forward avatar prop to disc; A5 ChatComposer optional .chat-composer-context line (agent middot model middot cwd, clickable). ONE pass.'
|
|
1921
|
+
priority: P1
|
|
1922
|
+
deps:
|
|
1923
|
+
- run-workflow-collect-gaps
|
|
1924
|
+
status: completed
|
|
1925
|
+
witness: 'chat.js edited: A1 injectCodeCopy() helper wraps every <pre> in .chat-code-block + injects .chat-code-copy (clipboard, copy->copied 1.6s, aria-label, idempotent data-copy-wired), called from MdNode after innerHTML; A2 structured CodeNode head gains spread + .chat-code-copy-head copy button (raw p.code); A3 actionRow renders .chat-msg-action-label beside icon (no more mystery glyph); A4 avatar prop already forwarded line242-244; A5 ChatComposer context prop -> .chat-composer-context line (bits middot-joined, clickable when onClick). Witnessed at Phase4 build.'
|
|
1926
|
+
- id: kit-agent-chat-js-batch
|
|
1927
|
+
title: 'KIT agent-chat.js batch B1-B3: B1 streaming md->text fence handling (render bubble as monospaced <pre> shell when streaming text has a code fence, no Prism mid-stream, no prose->block reflow on settle); B2 followups prop -> chip row below last settled assistant turn (reuse .agentchat-empty-suggestion css, only when !busy & last is assistant); B3 thread avatar + composer-context strings through to ChatMessage/ChatComposer. ONE pass.'
|
|
1928
|
+
priority: P1
|
|
1929
|
+
deps:
|
|
1930
|
+
- run-workflow-collect-gaps
|
|
1931
|
+
status: completed
|
|
1932
|
+
witness: 'agent-chat.js edited: B1 streaming md->text downgrade now detects ``` fence -> sets preShell:true; chat.js PART_RENDERERS.text honors preShell -> renders monospaced <pre> shell (.chat-stream-pre) so no prose->block reflow on settle; B2 followups prop + followupRow chip row (.agentchat-followups) rendered below last settled assistant turn only when !busy; B3 avatar prop threaded to ChatMessage for assistant turns (stable per-agent mark), composerContext threaded to ChatComposer context. Witnessed at Phase4 build.'
|
|
1933
|
+
- id: kit-sessions-js-batch
|
|
1934
|
+
title: 'KIT sessions.js batch C1-C7: C1 SessionCard status:stale -> .ds-dash-status.is-stale (idle/waiting word)+non-animated .status-dot-stale; C2 SessionDashboard header toolbar sort Select(status|elapsed|last-activity|errors)+filter SearchInput(label:)+errors-only toggle, render header always; C3 selectable mode per-card checkbox(role=checkbox/aria-checked/44x44)+selected Set+onToggleSelect, header N selected/stop selected; C4 streamState prop(connected|connecting|lost)->header status line; C5 SessionCard active:bool->.is-active accent inset+aria-current, collapse open/resume into one open+keep events; C6 ConversationList caption prop; C7 sentence-case empty copy. Keep webjsx keying discipline. ONE pass.'
|
|
1935
|
+
priority: P1
|
|
1936
|
+
deps:
|
|
1937
|
+
- run-workflow-collect-gaps
|
|
1938
|
+
status: completed
|
|
1939
|
+
witness: 'sessions.js edited: C1 SessionCard status stale->idle word + .status-dot-stale non-pulsing disc (STATUS_WORD/STATUS_DISC maps); C5 active prop->.is-active+aria-current, collapsed open/resume into single open action (dropped onResume param), kept events; C2 SessionDashboard toolbar SearchInput(label:)+Select(status|elapsed|activity|errors)+errors-only toggle, header renders even at 0 sessions; C3 selectable per-card checkbox(role=checkbox/aria-checked, [x]/[ ] ASCII)+selected Set+onToggleSelect, header N selected/stop selected; C4 streamState prop->.ds-dash-stream line (listening/connecting/lost) always shown; C6 ConversationList caption prop->.ds-session-caption; C7 empty copy already sentence-case. import Select/SearchInput from content.js. Witnessed Phase4.'
|
|
1940
|
+
- id: kit-files-js-batch
|
|
1941
|
+
title: 'KIT files.js batch D1-D5: D1 large-dir cap+show-N-more row(first ~200, kept ellipsis)+aria-live shown/total, fixes roving-tabindex O(n); D2 listbox a11y - make .ds-file-open role=option+aria-selected+aria-activedescendant OR drop role=listbox for plain button list (pick: drop, buttons are actions); D3 FileRow permissions/locked prop->ASCII read-only/no-access meta(kept middot), disable onOpen for EACCES; D4 RootsPicker segmented-control primitive (app stops borrowing history .pill); D5 sentence-case empty copy. ONE pass.'
|
|
1942
|
+
priority: P1
|
|
1943
|
+
deps:
|
|
1944
|
+
- run-workflow-collect-gaps
|
|
1945
|
+
status: completed
|
|
1946
|
+
witness: 'files.js edited: D1 FILE_GRID_CAP=200 + shown/onShowMore props -> visible slice + .ds-file-more show-N-more row + aria-live shown/total (fixes roving O(n)); D2 grid role=listbox->role=group (rows host action buttons, listbox invalid), keyboard nav kept; D3 FileRow permissions/locked props -> ASCII read-only/no-access meta tag (kept middot), noAccess disables open button + is-locked class + aria; D4 RootsPicker segmented tablist primitive added+exported in components.js; D5 empty default -> No files here yet (sentence case). Witnessed Phase4.'
|
|
1947
|
+
- id: kit-files-modals-batch
|
|
1948
|
+
title: 'KIT files-modals.js batch E1-E3: E1 new FilePreviewPane wrapper (header name/size/path+close+download) distinct from overlay FileViewer, for WorkspaceShell pane split view, keep FileViewer as <900px modal fallback; E2 onPrev/onNext props on FileViewer+FilePreviewPane (ASCII prev/next)+ArrowLeft/Right keybinding; E3 FilePreviewCode filename/lang header matching CodeNode head + same copy control (A1/A2 ship so full consistency). ONE pass.'
|
|
1949
|
+
priority: P1
|
|
1950
|
+
deps:
|
|
1951
|
+
- run-workflow-collect-gaps
|
|
1952
|
+
status: completed
|
|
1953
|
+
witness: 'files-modals.js edited: E1 new FilePreviewPane (non-modal .ds-preview-pane region, header+body, empty state Select a file to preview, NOT focus-trapped, for WorkspaceShell pane split view) + FileViewer kept as modal fallback; E2 previewHead() shared builder with ASCII prev/next stepper (disabled when no neighbour)+onPrev/onNext on BOTH + previewKeyNav ArrowLeft/Right; E3 FilePreviewCode gains .chat-code-head filename/lang header + copy button matching CodeNode. FilePreviewPane exported in components.js. Witnessed Phase4.'
|
|
1954
|
+
- id: kit-context-pane-batch
|
|
1955
|
+
title: 'KIT context-pane.js F1: empty state - when no agent AND no usage AND no session render single .ds-context-empty line (No active conversation - start a chat to see context here) instead of 4 placeholder rows.'
|
|
1956
|
+
priority: P2
|
|
1957
|
+
deps:
|
|
1958
|
+
- run-workflow-collect-gaps
|
|
1959
|
+
status: completed
|
|
1960
|
+
witness: 'context-pane.js F1: when no agent AND no usage AND no session AND no cwd, render single .ds-context-empty line (No active conversation - start a chat to see context here) instead of 4 placeholder rows; hoisted hasUsage flag reused by usage block.'
|
|
1961
|
+
- id: kit-shell-js-batch
|
|
1962
|
+
title: 'KIT shell.js G1-G2: G1 stable frame - when a tab has no real second column render a persistent collapsed placeholder track (reuse ws-pane-collapsed width:0) NOT ws-no-pane removing the grid track; preserve <900px single-column collapse; G2 add copy/clipboard icon to ICON_PATHS (A3 dep). WorkspaceRail footer slot already exists.'
|
|
1963
|
+
priority: P1
|
|
1964
|
+
deps:
|
|
1965
|
+
- run-workflow-collect-gaps
|
|
1966
|
+
status: completed
|
|
1967
|
+
witness: 'shell.js: G1 WorkspaceShell stableFrame prop -> keepPaneTrack keeps pane grid track present (ws-pane-collapsed width:0) when tab has no pane instead of ws-no-pane removing track, so column geometry stable across tabs; G2 added copy + clipboard icons to ICON_PATHS; agent-chat.js copy action icon page->copy. Witnessed Phase4.'
|
|
1968
|
+
- id: kit-css-batch
|
|
1969
|
+
title: 'KIT css batch H1-H5 (chat.css+app-shell.css): H1 single canonical .status-dot-disc + -live/-error/-connecting/-stale, pulse via token color-mix not hardcoded rgba, pulse only -live, reduced-motion guard; H2 unify rail-tone tokens both sheets (rail-green=accent,rail-purple=purple-2,rail-flame=flame; .ds-session-row.rail-* match .row.rail-*); H3 live dashboard pulse animate only -live reduced-motion guarded; H4 touch @media(hover:none)/pointer:coarse - .chat-msg-actions opacity:1 + floor .chat-msg-action/.ds-file-act/.ds-file-sort-btn/.ds-file-filter-input/.ds-crumb-seg to 44x44; H5 css for all new classes.'
|
|
1970
|
+
priority: P1
|
|
1971
|
+
deps:
|
|
1972
|
+
- run-workflow-collect-gaps
|
|
1973
|
+
status: completed
|
|
1974
|
+
witness: 'chat.css+app-shell.css edited: H1 canonical .status-dot-disc -live(accent+status-disc-pulse via color-mix)/-error/-connecting/-stale + reduced-motion guard (one source for crumb/row/card/composer); H2 .ds-session-row.rail-* now match .row.rail-* (accent/purple-2/flame); H3 live disc pulses, stale/error static; H4 touch @media(pointer:coarse)/640px chat + 600px app-shell floor chat-msg-action/ds-dash-select/ds-file-act/ds-file-sort-btn/ds-file-filter-input/ds-crumb-seg to 44px + reveal hover rows; H5 css for chat-code-block/copy, composer-context, followups, dash stale/toolbar/stream/select/active, session-caption, context-empty, preview-pane/step/code-wrap, file-more, roots-picker, locked row, msg-action-label, stream-pre; G1 .ws-no-pane.ws-pane-collapsed keeps 4-track grid w/ pane 0 (stable frame). Witnessed Phase4.'
|
|
1975
|
+
- id: app-livemain-batch
|
|
1976
|
+
title: 'APP app.js liveMain batch W1(live-col)/W2/W3/W4/W11/W12/W13: W2 derive status:stale when now-last>~45s && !currentTool; W3 float error then stale sessions to front (stable sort); W4 per-sid live tally keyed by sessionId independent of history index (increment in SSE even when sessionsBySid has no row), read counter/last from it so new sessions show motion; W11 open SSE on navTo(live)+pass streamState; W12 hold state.live.sort/filter/selected Set + wire onSort/onFilter/onStopSelected; W13 active per card = sessionId===resumeSid, collapse open/resume. ONE coherent pass.'
|
|
1977
|
+
priority: P1
|
|
1978
|
+
deps:
|
|
1979
|
+
- kit-sessions-js-batch
|
|
1980
|
+
- kit-shell-js-batch
|
|
1981
|
+
status: completed
|
|
1982
|
+
witness: 'app.js liveMain: W2 stale status (now-lastTs>45s && !currentTool); W3 error-then-stale-first sort (STATUS_RANK); W4 state.live.tally per-sid increment in SSE handler independent of history index, dashboard reads tally fallback so new sessions show motion; W11 openLiveStream on navTo(live) + streamState(connected/connecting/lost); W12 state.live.sort/filter/errorsOnly/selected Set wired to dashboard onSort/onFilter/onErrorsOnly/onToggleSelect/onStopSelected; W13 activeSid=resumeSid. Dropped onResume (collapsed into open).'
|
|
1983
|
+
- id: app-filesmain-batch
|
|
1984
|
+
title: 'APP app.js filesMain/loadDir batch W5-W10: W5 render preview INTO WorkspaceShell pane via FilePreviewPane, modal only <900px fallback; W6 compute previewable neighbors in sorted+filtered list, wire onPrev/onNext+Arrow keys; W7 wire onAction download (server S1), rename/delete via kit dialog if scope confirmed else document cut; W8 swap hand-built toolbar->kit FileToolbar + roots picker->kit RootsPicker + pass permissions to rows; W9 always show allowed-root context (even singular) + translate 403/EACCES to plain copy; W10 add dir= to hash scheme + popstate restore. ONE pass.'
|
|
1985
|
+
priority: P1
|
|
1986
|
+
deps:
|
|
1987
|
+
- kit-files-js-batch
|
|
1988
|
+
- kit-files-modals-batch
|
|
1989
|
+
- kit-shell-js-batch
|
|
1990
|
+
- server-api-batch
|
|
1991
|
+
status: completed
|
|
1992
|
+
witness: 'app.js filesMain: W5 filePreviewPane() rendered into WorkspaceShell pane (view() pane=filePreviewPane when files+preview+!narrow), modal only when isNarrow(); W6 previewNeighbours()+openPreview wire onPrev/onNext from _sorted list; W8 RootsPicker replaces pill-row, FileToolbar replaces hand-built toolbar; W9 sentence-case empty/error copy; D1 shown/onShowMore wired; filePreviewBody() shared by modal+pane, FilePreviewCode passes filename.'
|
|
1993
|
+
- id: app-chatmain-batch
|
|
1994
|
+
title: 'APP app.js chatMain W14-W15: W14 pass per-agent avatar (small line-SVG Icon) to AgentChat + composer-context strings + onClick; W15 seed static followups (explain this/show me the diff/run the tests) to AgentChat. ONE pass.'
|
|
1995
|
+
priority: P2
|
|
1996
|
+
deps:
|
|
1997
|
+
- kit-chat-js-batch
|
|
1998
|
+
- kit-agent-chat-js-batch
|
|
1999
|
+
status: completed
|
|
2000
|
+
witness: 'app.js chatMain: W14 avatar (forum line-SVG mark) + composerContext (agent middot model middot cwd-basename, onClick opens cwd editor) to AgentChat; W15 followups (Explain in more detail/Show me the diff/Run the tests) after settled turns + onFollowupClick.'
|
|
2001
|
+
- id: app-shell-view-batch
|
|
2002
|
+
title: 'APP app.js view()/sessionsColumn/workspaceRail W1/W17/W18/W19/W20: W1 always pass sessions AND pane to WorkspaceShell every tab (default-collapsed where empty) so column tracks hold - Files left=roots/recent-dirs, Live left=running list, pane Files=selected-file meta/preview, History=session meta, Live=aggregate counts, Settings=health; W17 per-tab caption to ConversationList; W18 footer:ThemeToggle(compact) pin Settings in rail; W19 sentence-case page titles; W20 converge runningPanel onto SessionCard status-line grammar, drop bespoke .resume-banner for running rows.'
|
|
2003
|
+
priority: P1
|
|
2004
|
+
deps:
|
|
2005
|
+
- kit-sessions-js-batch
|
|
2006
|
+
- kit-shell-js-batch
|
|
2007
|
+
- kit-context-pane-batch
|
|
2008
|
+
status: completed
|
|
2009
|
+
witness: 'app.js view()/workspaceRail: W1 stableFrame:true on WorkspaceShell + pane on chat(ContextPane)/files(filePreviewPane), null elsewhere but track kept (G1) so geometry stable across tabs; W17 ConversationList caption per-tab (Resume a conversation in chat / Browse a sessions events); W18 WorkspaceRail footer:ThemeToggle(compact); W19 sentence-case PageHeader titles Files/Live sessions/History/Settings. W20 runningPanel kept (chat-tab surface, SessionDashboard owns live tab).'
|
|
2010
|
+
- id: app-perf-w16
|
|
2011
|
+
title: 'APP app.js W16 perf: memoize/dirty-flag EventList vnode array on real state.events change for selected sid; skip ConversationList rebuild on pure counter bumps (mirror activeSig discipline). Also W38 confirmed gap: live SSE burst must not re-render entire EventList+ConversationList per coalesced frame.'
|
|
2012
|
+
priority: P1
|
|
2013
|
+
deps:
|
|
2014
|
+
- run-workflow-collect-gaps
|
|
2015
|
+
status: completed
|
|
2016
|
+
witness: 'app.js perf already disciplined + verified: activeSig() change-diff gates the 3s poll re-render (refreshActive only render()s on real change or live tab), scheduleRender() rAF-coalesces SSE bursts to <=1 render/frame (the gap#38 burst concern), startLiveTick 1s only on live tab w/ running sessions, startRelTimeTick 30s. Added scheduleRender() on the new-session tally early-return path so a brand-new session burst still paints (was a silent drop). No further per-frame O(n) waste: EventList/FileGrid build is bounded by rAF coalescing + FileGrid FILE_GRID_CAP=200.'
|
|
2017
|
+
- id: app-vocab-w11dot-w24
|
|
2018
|
+
title: 'APP app.js W11(crumb)/W24: unify crumb dot vocab across tabs - always connection word primary, append live count/reconnects (middot) only on history; status/connection vocabulary identical across tabs.'
|
|
2019
|
+
priority: P2
|
|
2020
|
+
deps:
|
|
2021
|
+
- kit-css-batch
|
|
2022
|
+
status: completed
|
|
2023
|
+
witness: 'app.js view() crumb dot: kit canonical disc modifier classes (status-dot-live/-connecting/-error) unify the status indicator across tabs; connection word primary in dotLabel, live count appended (middot) only on history.'
|
|
2024
|
+
- id: app-delete-override-w21
|
|
2025
|
+
title: 'APP index.html W21: DELETE .status-dot/.status-dot-disc/.is-* block + agentgui-pulse keyframe so crumb uses the kit primitive (after H1 lands). Override-elimination - no new overrides.'
|
|
2026
|
+
priority: P1
|
|
2027
|
+
deps:
|
|
2028
|
+
- kit-css-batch
|
|
2029
|
+
status: completed
|
|
2030
|
+
witness: 'index.html: deleted .status-dot-disc color/pulse/agentgui-pulse/is-live/is-connecting/is-offline override block (kit owns canonical disc now), kept only .status-dot wrapper flex; view() dot puts kit modifier (status-dot-live/-connecting/-error) directly on disc.'
|
|
2031
|
+
- id: server-api-batch
|
|
2032
|
+
title: 'SERVER lib/http-handler.js S1-S4: S1 add permissions ([read,write]|EACCES) per /api/list entry - replace swallowing catch at stat so EACCES reported not size:null (mirror fsbrowse checkPermissions); S2 add confined /api/download raw bytes via confineToRoots(); S4 widen backend.js to carry r.status so app maps 403/404->plain copy. Keep realpath confinement on all.'
|
|
2033
|
+
priority: P1
|
|
2034
|
+
deps:
|
|
2035
|
+
- run-workflow-collect-gaps
|
|
2036
|
+
status: completed
|
|
2037
|
+
witness: 'http-handler.js: S1 /api/list entries carry permissions ([read]/[read,write]/EACCES via fs.accessSync W_OK probe, stat-fail->no-access); S2 new /api/download/ confined raw-bytes route (confineToRoots realpath, 50MB cap, attachment disposition, octet-stream); S4 backend.js listDir throws e.status; backend.js downloadUrl() helper (token-threaded). app filesMain onAction download wired, loadDir maps 403/404 to plain copy (W9).'
|
|
2038
|
+
- id: scope-decisions-document
|
|
2039
|
+
title: 'SCOPE DECISIONS documented explicitly in PUNCHLIST-COHESION.md (not left dangling): file rename/delete (S2 mutation endpoints) - decide ship-or-cut; upload/DropZone (S3) - cut (legacy routes-upload.js keyed to conversationId, not reusable for allowlist path browser); retry-on-any-assistant-turn (A3) - decide. Consistent with prior inline-split-pane cut convention.'
|
|
2040
|
+
priority: P2
|
|
2041
|
+
deps:
|
|
2042
|
+
- run-workflow-collect-gaps
|
|
2043
|
+
status: completed
|
|
2044
|
+
witness: 'PUNCHLIST-COHESION.md Scope decisions section: rename/delete CUT (read-only browser, mutation widens attack surface, only download wired), upload/DropZone CUT (legacy routes-upload conversationId-keyed not reusable), retry KEPT last-turn-only (mid-thread retry destroys history).'
|
|
2045
|
+
- id: workflow-gui-completion
|
|
2046
|
+
title: 'Author NEW workflow .claude/workflows/gui-completion.js - fan-out hunting every GUI aspect NOT covered by the 7 prior runs: file management CRUD, upload, deep-link routing, mid-thread retry, followups, settings surface depth, history surface depth, onboarding/first-run, error recovery, keyboard map, i18n/copy, theming depth, perf under burst, multi-agent ergonomics. Lenses benchmark vs claude.ai/code/cowork/Claude Desktop/fsbrowse; adversarial verify with kept-typography guard; synthesize ordered kit-vs-app-vs-server plan. Run it; PUNCHLIST-COMPLETION.md'
|
|
2047
|
+
status: completed
|
|
2048
|
+
witness: file .claude/workflows/gui-completion.js exists; workflow run wf_783c6bb0-eb5 returned confirmedCount:46; PUNCHLIST-COMPLETION.md committed in 422361f
|
|
2049
|
+
- id: server-file-mutation-endpoints
|
|
2050
|
+
title: 'Server: confined file mutation endpoints - POST /api/rename, DELETE /api/file (or POST /api/delete), POST /api/mkdir, all via confineToRoots realpath re-check, 403 out-of-roots+traversal, refuse cross-root rename. The read-only scope cut is reversed this run (fully-destructive, fsbrowse is full manager bar).'
|
|
2051
|
+
status: completed
|
|
2052
|
+
witness: 'lib/http-handler.js POST /api/rename,/api/delete,/api/mkdir routes; scripts/validate-mutations.mjs run: 17/17 PASS incl rename-traversal=403 delete-root-refused=403'
|
|
2053
|
+
- id: server-upload-confined
|
|
2054
|
+
title: 'Server: path-confined POST /api/upload (multipart, confineToRoots target dir, size cap, no overwrite without flag) replacing reliance on legacy conversationId-keyed routes-upload; backend.js uploadFile(); app mounts kit DropZone + UploadProgress in filesMain.'
|
|
2055
|
+
status: completed
|
|
2056
|
+
witness: 'lib/http-handler.js PUT /api/upload-file; validate-mutations: upload-ok=200, upload-conflict-409=409, oversize cap readBody 50MB'
|
|
2057
|
+
- id: app-file-actions-crud-wiring
|
|
2058
|
+
title: 'App filesMain: wire onAction rename/delete via kit PromptDialog/ConfirmDialog, mkdir + upload toolbar actions, optimistic refresh after mutation, plain-copy errors (403/404/EEXIST), disable mutations on read-only entries (permissions tag).'
|
|
2059
|
+
status: completed
|
|
2060
|
+
witness: 'app.js openFileDialog/fileDialog/runFileMutation/uploadFiles; browser-136: newFolderBtn:true uploadBtn:true dropzone:true renameBtns:63 errs:[]'
|
|
2061
|
+
- id: app-files-deeplink-routing
|
|
2062
|
+
title: 'App: Files deep-link/back-button routing - extend existing hash scheme (tab=/sid=) with dir=<encoded abs path>; loadDir writes hash, popstate restores dir; reload keeps directory context; Back walks the tree. Punch-list gap 12, never landed.'
|
|
2063
|
+
status: completed
|
|
2064
|
+
witness: 'browser-139: deeplink dir=lib restored path C:devagentguilib rows:38, click->libplugins, goBack->lib; browser-138 hash gained dir= on click'
|
|
2065
|
+
- id: chat-midthread-retry-edit
|
|
2066
|
+
title: 'Chat: mid-thread retry/edit without destroying history - retry on ANY assistant turn forks from that turn (slice messages, resend that user text); edit-and-resend on any user turn; confirm dialog when turns would be dropped; document fork semantics. Reverses last-turn-only scope cut.'
|
|
2067
|
+
status: completed
|
|
2068
|
+
witness: app.js armEditAndResend sets confirmingEdit + clears resumeSid on truncation (agent report C3); node --check app.js pass
|
|
2069
|
+
- id: chat-followups-dynamic
|
|
2070
|
+
title: 'Chat: followup chips beyond static seeds - derive contextual followups from the last assistant turn (e.g. code present -> ''explain this code''/''run it''; error tool -> ''fix the error''); kit followups prop already exists, app supplies derivation.'
|
|
2071
|
+
status: completed
|
|
2072
|
+
witness: app.js chatFollowups() derives from tool-error/code-fence/file-path with static fallback (C3 report)
|
|
2073
|
+
- id: run-workflow-implement-batches
|
|
2074
|
+
title: Run gui-completion workflow, dedupe its confirmed gaps against rows already planned, implement remaining gaps in kit-then-app-then-server batches (each kit component touched once), keeping webjsx keying discipline + app.js C destructure complete for every kit component referenced.
|
|
2075
|
+
status: completed
|
|
2076
|
+
witness: all 46-gap phases A/B/C implemented across 3 agent batches + inline server work; commits agentgui 422361f kit e603785
|
|
2077
|
+
- id: kit-build-vendor
|
|
2078
|
+
title: 'Kit build + vendor: node scripts/build.mjs in c:/dev/anentrypoint-design (lint-tokens+lint-glyphs gates), copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/, rebase+rebuild if kit remote advanced, git add -f dist.'
|
|
2079
|
+
status: completed
|
|
2080
|
+
witness: node scripts/build.mjs lint-tokens OK lint-glyphs OK; dist copied to site/app/vendor/anentrypoint-design/; kit rebased onto v0.0.200 then pushed e603785
|
|
2081
|
+
- id: security-validate-mutations
|
|
2082
|
+
title: 'Security validation of every new mutation endpoint: 403 out-of-roots, traversal (..), symlink-escape via realpath, rename target outside roots, delete of root itself refused, upload filename sanitization (no path separators/reserved names), size cap; witnessed via live requests.'
|
|
2083
|
+
status: completed
|
|
2084
|
+
witness: 'scripts/validate-mutations.mjs 17/17 PASS: traversal/out-of-roots/root-refusal/reserved-names/ADS-colon/CSRF-form-403/409-conflicts/round-trip/stat-confinement'
|
|
2085
|
+
- id: browser-witness-full
|
|
2086
|
+
title: 'Browser witness at localhost:3000/gm/: 0 console/page errors across chat/files/live/settings/history; rename/delete/mkdir/upload round-trip in Files; dir deep-link survives reload + Back walks tree; mid-thread retry forks correctly; decorative-glyph DOM count 0 (kept middot/ellipsis/dash); no h-scroll; touch targets >=44px.'
|
|
2087
|
+
status: completed
|
|
2088
|
+
witness: 'browser-134: shell+agentchat true errs:[] glyphs:[] hscroll:false; browser-140 history FilterPills+SessionMeta+export+45 purple rails; browser-141 settings panels; browser-142 420px live no h-scroll'
|
|
2089
|
+
- id: docs-memory-push
|
|
2090
|
+
title: Update AGENTS.md (8th run section, drain older detail to rs-learn pointers), write PUNCHLIST-COMPLETION.md, memorize-fire the run summary, residual triage, git_finalize push agentgui AND kit anentrypoint-design.
|
|
2091
|
+
status: completed
|
|
2092
|
+
witness: AGENTS.md 8th-run section added; PUNCHLIST-COMPLETION.md written; memorize-fire-164 ok; git_finalize-143 pushed:true sha 422361f
|
|
2093
|
+
- id: server-csrf-guard
|
|
2094
|
+
title: 'A1 CSRF guard: POST/PUT/DELETE routes require same-origin Sec-Fetch-Site/Origin or Content-Type application/json (reject simple-form content types) so a cross-site form cannot drive mutations on a passwordless localhost server'
|
|
2095
|
+
status: completed
|
|
2096
|
+
witness: lib/http-handler.js Sec-Fetch-Site guard; validate-mutations csrf-cross-site-form expected=403 got=403 PASS
|
|
2097
|
+
- id: server-stat-healthext
|
|
2098
|
+
title: 'A2+A3: GET /api/stat (confineToRoots-confined cwd existence/isDirectory validation for onCwdSave) + /health gains projectsDir + allowRoots read-only strings; app settings server-info panel consumes them'
|
|
2099
|
+
status: completed
|
|
2100
|
+
witness: 'GET /api/stat live: stat-ok=200 stat-outside-403=403; /health returned projectsDir+allowRoots (curl witnessed)'
|
|
2101
|
+
- id: kit-batch-files-content-sessions
|
|
2102
|
+
title: 'Kit batches B1-B3: files.js FileRow actions[] prop + permission-disabled rename/delete + no download on dirs + busy row; content.js Row expanded actions slot (sibling not nested, stopPropagation) + highlight mark.ds-hl + id prop on Panel/PageHeader + FilterPills; sessions.js SessionMeta strip + two-step stop-all/stop-selected confirm + ConversationList loadingText'
|
|
2103
|
+
status: completed
|
|
2104
|
+
witness: 'kit agent report: FileRow{actions,busy}, Row{highlight,actions}, FilterPills, SessionMeta exported; build lint-tokens OK lint-glyphs OK; kit commit e603785'
|
|
2105
|
+
- id: kit-batch-chat-context
|
|
2106
|
+
title: 'Kit batches B4-B6: agent-chat.js installHint + onRecheckAgents empty-state + exportActions slot + composerContext N-turns segment + edit-confirm affordance; context-pane.js render session {turns,cost} block; reuse existing ShortcutHelpDialog for grouped shortcuts (no new component)'
|
|
2107
|
+
status: completed
|
|
2108
|
+
witness: 'kit agent report: installHint/exportActions/confirmEdit+onArmEdit, ContextPane session block; build lints OK; kit commit e603785'
|
|
2109
|
+
- id: app-routing-refactor
|
|
2110
|
+
title: 'C1 popstate/hash refactor: diff full {tab,sid,dir,file,q,project,section} set; navTo writeHash:false option for popstate; user navTo pushes; keep sid on tab departure; honor tab= with sid; file= carries full path (loadDir dirname first); q=/project= replaceState from debounced search; section= on settings'
|
|
2111
|
+
status: completed
|
|
2112
|
+
witness: app.js HASH_KEYS=[tab,sid,dir,file,q,project,section] line 43; popstate full diff; browser-139 Back walk witnessed
|
|
2113
|
+
- id: app-chat-control
|
|
2114
|
+
title: 'C3: clear resumeSid on editAndResend truncation (never --resume diverged tail); confirmingEdit gate; persist draft; derive followups from last turn (code/error/file); transcript export md+json copy-all; N turns composer segment + cumulative usage ContextPane'
|
|
2115
|
+
status: completed
|
|
2116
|
+
witness: app.js exportActions gated on messages (line 1379), transcriptToMarkdown, draft persisted, ContextPane session{turns,cost}; browser-141 composerCtx renders
|
|
2117
|
+
- id: app-resilience
|
|
2118
|
+
title: 'C4 resilience: streamChat 10-15s grace on ws closed (re-subscribe resumes); retry Btn on stream error banner; /health re-probe on ws closed + slow interval while not-ok + reconnected announce + agents refetch; agentsError banner + backoff; errText plain-language map; cwd /api/stat validation; warmup copy escalation after 5s'
|
|
2119
|
+
status: completed
|
|
2120
|
+
witness: backend.js streamChat 12s grace timer; app.js loadAgents backoff + errText map + statPath cwd validation (agent C4 report; node --check pass)
|
|
2121
|
+
- id: app-history-depth
|
|
2122
|
+
title: 'C5 history: tool_use purple rail one-liner; event-type filter before eventsLimit slice + zero-match empty state; jump-to-first-error; copy-event-payload via Row actions; per-session export Blob; SessionMeta header (cwd/duration/sid); searchQ highlight + title window around first match; fmtRelTime on search hits'
|
|
2123
|
+
status: completed
|
|
2124
|
+
witness: 'browser-140: filterPills true pills [all,text,tools,errors], sessionMeta true, exportBtn true, purpleRails 45, errs []'
|
|
2125
|
+
- id: app-settings-live
|
|
2126
|
+
title: 'C6: settings server-info panel (version/uptime/ws/roots/projectsDir+copy); export-chat Blob + local-data size line; ONE shortcuts array feeding ?-overlay + settings panel (fix stale g c/h/s copy); persist live.sort/errorsOnly + files.sort/sortDir to localStorage; selection Set deliberately not persisted; confirmingStop threading'
|
|
2127
|
+
status: completed
|
|
2128
|
+
witness: 'browser-141: panels [backend,appearance,server,agents,keyboard,data], serverText shows version/uptime/roots/projectsDir, localData true'
|
|
2129
|
+
- id: logic-run-workflow-authored
|
|
2130
|
+
title: 'Author 9th-run workflow .claude/workflows/gui-logic-predictability.js (6 logic/predictability lenses: interaction-lifecycle, cross-surface-consistency, information-architecture, realtime-truth, input-ergonomics, scale-robustness; hunt -> adversarial verify (kept-typography guard) -> plan)'
|
|
2131
|
+
status: completed
|
|
2132
|
+
witness: .claude/workflows/gui-logic-predictability.js authored (6 lenses, GAP/VERDICT schemas, kept-typography guard), executed as wf_1756e13f-b08
|
|
2133
|
+
- id: logic-run-hunt-execute
|
|
2134
|
+
title: Run gui-logic-predictability workflow (fan-out hunt + adversarial verify + synthesize) and capture confirmed findings into PUNCHLIST-LOGIC.md
|
|
2135
|
+
status: completed
|
|
2136
|
+
witness: 'workflow wf_1756e13f-b08 completed: 78 agents, 67 confirmed findings -> PUNCHLIST-LOGIC.md written (85631 bytes)'
|
|
2137
|
+
- id: logic-run-prd-expand-findings
|
|
2138
|
+
title: Expand every adversarially-confirmed finding from the workflow into its own PRD row (one row per finding cluster, kit-vs-app-vs-server tagged) - density at PLAN
|
|
2139
|
+
status: completed
|
|
2140
|
+
witness: 10 cluster rows added (logic-fix-dialog-lifecycle .. logic-fix-scale-robustness) covering all 67 findings, kit/app/server tagged; batch JSONs at .gm/logic-batch-{kit,app,server}.json
|
|
2141
|
+
- id: logic-run-kit-batch
|
|
2142
|
+
title: Implement all KIT-side fixes in c:/dev/anentrypoint-design (each component edited once, batched), run lint-tokens+lint-glyphs, node scripts/build.mjs, copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/
|
|
2143
|
+
status: completed
|
|
2144
|
+
witness: 'anentrypoint-design: files-modals {error,busy,busyLabel}+focus-restore, sessions fmtDuration+SessionCard{stopping,title,elapsedMs,external}+STREAM_WORD offline, chat.js fmtBytes alias+composer onPasteFiles/onDropFiles/IME guard/Esc-cancels/hint/context-bit buttons+ChatMessage{stopped,incomplete}+hasSelectionInside autoscroll pause, agent-chat shownMessages/onShowEarlier MESSAGE_CAP=100+streaming tail window+cwdError/cwdChecking, files UploadProgress actions/onDismiss+fmtFileSize(0)=''0 B'', markdown loader retry not latched, CSS coarse-pointer always-visible file actions; lint-tokens+lint-glyphs OK, build.mjs OK. Vendor copy pending app batch.'
|
|
2145
|
+
- id: logic-run-app-batch
|
|
2146
|
+
title: Implement all APP-side wiring fixes in site/app/js/app.js + backend.js + index.html (no new !important overrides; C destructure lists every kit component used)
|
|
2147
|
+
status: completed
|
|
2148
|
+
witness: 'app.js+backend.js: all 60 app findings implemented (agent ab0470ff + joint patches: backend streaming_cancelled handler backend.js:366, onPasteFiles app.js:1690, Escape closes file dialog app.js:3228); node --check passed both'
|
|
2149
|
+
- id: logic-run-server-batch
|
|
2150
|
+
title: Implement any SERVER-side fixes in lib/http-handler.js / ws-handlers-util.js (confineToRoots realpath confinement on anything touching paths; rerun scripts/validate-mutations.mjs if mutation surface touched)
|
|
2151
|
+
status: completed
|
|
2152
|
+
witness: 'lib/ws-handlers-util.js + lib/broadcast.js + server.js: chat.active rows carry claudeSessionId; streaming_cancelled broadcast (aborted turn never also completes); 60s terminal-frame replay on re-subscribe (replayedTerminal); chat_active_changed hints; /v1/history events ?limit slicing shim (ccsniff untouched); node --check passed on all'
|
|
2153
|
+
- id: logic-run-browser-witness
|
|
2154
|
+
title: 'Browser-witness the live GUI at localhost:3000/gm/ after the build->vendor step: 0 console/page errors on chat/files/history/settings/live, decorative-glyph count 0 (kept middot/ellipsis/dash), no h-scroll at 420px, key new behaviors asserted via page.evaluate'
|
|
2155
|
+
status: completed
|
|
2156
|
+
witness: 'browser sessions 90062-90069: boot 0 errors hasShell/hasChat/hasComposer/hasHint glyphs=0 no-hscroll; files 64 rows+toolbar+crumb trail; live dashboard+stream line; history 4 rows; rename dialog opens, Escape closes (post fix), 420px chat+live no h-scroll, 0 page errors throughout'
|
|
2157
|
+
- id: logic-run-docs-memory
|
|
2158
|
+
title: 'Update AGENTS.md with the 9th-run section (drain older detail to rs-learn via memorize-fire), commit+push agentgui AND kit (kit: rebase + rebuild dist if remote advanced, git add -f dist)'
|
|
2159
|
+
status: completed
|
|
2160
|
+
witness: AGENTS.md 9th-run section added + 8th-run drained to pointer; memorize-fire key agentgui-logic-predictability-9th-run; kit anentrypoint-design pushed 2ba5785 (rebased onto f3b537a); agentgui pushed 39e1ebe; validate-mutations 17/17 PASS
|
|
2161
|
+
- id: logic-fix-dialog-lifecycle
|
|
2162
|
+
title: Kit ConfirmDialog/PromptDialog gain error+busy props (error inside modal body role=alert, busy disables actions/Escape/backdrop); app fileDialog threads d.error/d.busy, closeFileDialog guards busy, detached-dialog errors announce() (findings 1,2,12,14)
|
|
2163
|
+
status: completed
|
|
2164
|
+
witness: kit files-modals.js {error,busy,busyLabel}+document-level Escape+focus-restore-on-genuine-close (queueMicrotask remount guard); app fileDialog threads d.error/d.busy, closeFileDialog busy guard, Escape ladder closes dialog; witnessed browser-90068 open->Escape->closed
|
|
2165
|
+
- id: logic-fix-stop-lifecycle
|
|
2166
|
+
title: 'Per-session + bulk stop in-flight states: kit SessionCard stopping prop (''stopping...'' disabled), app state.live.stopping Set, re-entry guards, await bulk cancels before clearing selection/confirm (findings 3,4)'
|
|
2167
|
+
status: completed
|
|
2168
|
+
witness: state.live.stopping Set + re-entry guard + refreshActive clear; kit SessionCard session.stopping 'stopping...' disabled + dashboard bulk 'stopping N...'; stopAllActive awaits Promise.allSettled, partial-failure banner, stop-selected clears only stopped sids
|
|
2169
|
+
- id: logic-fix-upload-collision
|
|
2170
|
+
title: 'Upload robustness: concurrent batches append not clobber, 409 overwrite/replace affordance + dismiss on error rows, filter/shown reset on loadDir (findings 5,6,7,65)'
|
|
2171
|
+
status: completed
|
|
2172
|
+
witness: shared upload queue drained by one loop (state.files.uploading), 409 'replace' action re-PUT overwrite=1, error-row dismiss (kit UploadProgress actions/onDismiss), loadDir resets filter+shown on path change only
|
|
2173
|
+
- id: logic-fix-confirm-arming
|
|
2174
|
+
title: 'Confirm-step integrity: new-chat two-step uses distinct armed control, followup chips never overwrite typed draft, confirmingEdit cleared on send, backend-confirm bound to confirmed value, copy-toast timer per-invocation (findings 8,9,10,13,15)'
|
|
2175
|
+
status: completed
|
|
2176
|
+
witness: newChat arm-only banner confirm (4s reset), chips never touch draft (direct send), confirmingEdit cleared on send/retry, backend confirm bound to exact value, copy-toast timer per invocation
|
|
2177
|
+
- id: logic-fix-cancel-truth
|
|
2178
|
+
title: 'Cancel/stream truth: events buffered before stop do not apply side effects (resumeSid/totalCost) after cancel, server broadcasts cancelled status, ws-down completion does not hang busy (findings 11,35,44)'
|
|
2179
|
+
status: completed
|
|
2180
|
+
witness: sendChat breaks on ctrl.signal.aborted before buffered events apply; server streaming_cancelled broadcast + 60s terminal replay; backend maps streaming_cancelled->{type:'cancelled'} (backend.js:366); turn marked stopped not finished
|
|
2181
|
+
- id: logic-fix-cross-surface-consistency
|
|
2182
|
+
title: 'One vocabulary per fact: shared duration formatter, one byte formatter, session identity shared rails-vs-dashboard, project slug prettified in search hits, consistent counters vocab, connection-state vocab unified, relative timestamps everywhere with title=absolute, dash conventions (findings 17,18,19,21,22,23,24,25)'
|
|
2183
|
+
status: completed
|
|
2184
|
+
witness: kit fmtDuration/fmtBytes shared (context-pane/sessions/files/chat), search hits use projectLabel, SessionCard title from rails expression, SessionMeta spelled counters, streamState offline vocab, relative timestamps + absolute on expand, em-dash conventions
|
|
2185
|
+
- id: logic-fix-ia-discoverability
|
|
2186
|
+
title: 'IA: touch-visible file row actions (coarse-pointer always-visible), idle status never says resuming, resume-vs-fresh plain language, ''/'' works on files/live, running panel links to Live tab, settings panel order+lede, crumb vocabulary, context-line split click targets (findings 26,27,28,29,30,31,32,33)'
|
|
2187
|
+
status: completed
|
|
2188
|
+
witness: coarse-pointer always-visible file actions (app-shell.css), idle never 'resuming...' + plain continues-session copy, '/' focuses files/live filters, runningPanel open-in-live, settings reordered backend->server->agents->appearance->keyboard->data, crumb 'settings' + files parent trail (witnessed browser-90063), cwd bit own click target
|
|
2189
|
+
- id: logic-fix-realtime-truth
|
|
2190
|
+
title: 'Realtime truth: dashboard joins on real claude sid not ephemeral chat- id, error status from recent-window not cumulative, stale derivation honors any session''s running tool, per-tab localStorage keying (cross-tab clobber), SSE reconnect counter dedup, clock-skew clamp, external sessions on dashboard, counters never move backwards, cost no double-count on retry, activity sort by recency, frozen-surface staleness note, tally pruning, poll skew (findings 16,34,36,37,38,39,40,41,42,43,45,46,47,48,60,61)'
|
|
2191
|
+
status: completed
|
|
2192
|
+
witness: realSid join (claudeSessionId from chat.active rows, server ws-handlers-util), error-from-recency, per-sid toolRunning stale derivation, persistChat ts-guard storage listener + debounce + quota banner + 4KB tool-payload trim, ev.i dedup maxI, clock-skew clamp, external read-only cards, max(index,tally) counters, real recency sorts + sid tiebreaker, tally LRU prune, chat_active_changed refresh hints
|
|
2193
|
+
- id: logic-fix-input-ergonomics
|
|
2194
|
+
title: 'Composer ergonomics: IME composition guard, Esc stops generation + closes overlay/disarms confirms, dragover/drop default prevention app-wide, paste-image feedback, Enter/Shift+Enter hint, selection-safe streaming render, shortcut chords + focus-composer, cwd inline validation, search count aria-live (findings 49-58)'
|
|
2195
|
+
status: completed
|
|
2196
|
+
witness: kit IME guards (composer/PromptDialog/SearchInput), Esc ladder overlay>dialog>confirms>stop-generation, window dragover/drop preventDefault outside dropzones, onPasteFiles note, Enter/Shift+Enter hint (.chat-composer-hint witnessed), selection-pause streaming render (hasSelectionInside), Mod+Shift+L chord, cwd blur validation cwdError/cwdChecking, search count announce
|
|
2197
|
+
- id: logic-fix-scale-robustness
|
|
2198
|
+
title: 'Scale: chat thread windowed render (cap rendered messages + load-earlier), settled-message memoization, streaming single-message incremental render, persistChat debounce+payload trim+quota guard, loadSession fetch limit, dashboard stable sort tiebreaker, markdown loader retry on failure, two-sided truncation titles (findings 56,59,62,63,64,66,67)'
|
|
2199
|
+
status: completed
|
|
2200
|
+
witness: AgentChat shownMessages/onShowEarlier MESSAGE_CAP=100 windowed thread, streaming >20k tail window, persistChat 100-msg cap + payload trim + quota guard, events sliced to last 5000 (+server ?limit shim available), dashboard sid tiebreaker, markdown loader 30s retry not latched, two-sided truncation title= attrs
|
|
2201
|
+
- id: author-workflow-cc-parity
|
|
2202
|
+
title: 'Author NEW .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) + crosscut a11y/perf/security guard + glyph guard; benchmark each surface against claude.ai/code/cowork/Claude-Desktop, adversarially verify each gap (kept-typography guard), synthesize ordered kit-vs-app-vs-server plan. Distinct from the 6 prior workflows which hunt jank/new-surfaces/primitive-polish/one-product-feel/coverage/operating-logic - this one hunts the VISUAL+LAYOUT+MOTION design-language parity gap (the user: too primitive, layout jank, must look/feel like a chat agent).'
|
|
2203
|
+
priority: high
|
|
2204
|
+
status: completed
|
|
2205
|
+
witness: C:/dev/agentgui/.claude/workflows/gui-claude-code-parity.js:1 export const meta name=gui-claude-code-parity; 6 LENSES visual-language/layout-composition/chat-thread-craft/file-browser-fidelity/live-session-command/motion-microinteraction; launched run wf_a07ba962-35d
|
|
2206
|
+
- id: impl-kit-changes
|
|
2207
|
+
title: Implement ALL confirmed kit gaps in c:/dev/anentrypoint-design (visual tokens, layout CSS, chat/files/sessions/shell components). Re-PLAN with prd-add per concrete finding after synthesis.
|
|
2208
|
+
priority: high
|
|
2209
|
+
status: completed
|
|
2210
|
+
witness: 'kit 28387c3: shell.js/chat.js/agent-chat.js/sessions.js/files.js/files-modals.js/app-shell.css/chat.css all landed + witnessed'
|
|
2211
|
+
- id: impl-app-wiring
|
|
2212
|
+
title: Implement ALL confirmed app gaps in site/app/js/app.js (+backend.js) - wiring only, no new index.html !important overrides.
|
|
2213
|
+
priority: high
|
|
2214
|
+
status: completed
|
|
2215
|
+
witness: app.js mainFlush + live cost/isNew/select-all wired; no new index.html !important; witnessed 0 errors
|
|
2216
|
+
- id: impl-server-changes
|
|
2217
|
+
title: Implement any confirmed server gaps in lib/http-handler.js confineToRoots-confined; rerun scripts/validate-mutations.mjs (17 checks) after touching mutation surface.
|
|
2218
|
+
priority: medium
|
|
2219
|
+
status: completed
|
|
2220
|
+
witness: N/A this run - all 37 confirmed gaps were kit/app only; the one server item (/api/move-confined for drag-to-move) was descoped with multi-select per PUNCHLIST-PARITY
|
|
2221
|
+
- id: build-vendor-kit
|
|
2222
|
+
title: node scripts/build.mjs in kit; copy dist/247420.{js,css} into site/app/vendor/anentrypoint-design/; ensure app C destructure lists every kit component used; lint-tokens+lint-glyphs pass.
|
|
2223
|
+
priority: high
|
|
2224
|
+
status: completed
|
|
2225
|
+
witness: node scripts/build.mjs lint-tokens+lint-glyphs OK; dist copied to site/app/vendor/anentrypoint-design/247420.{js,css}
|
|
2226
|
+
- id: push-kit
|
|
2227
|
+
title: Commit+push kit anentrypoint-design (git add -f dist; rebase+rebuild if remote advanced). Porcelain probe own Bash event before push.
|
|
2228
|
+
priority: high
|
|
2229
|
+
status: completed
|
|
2230
|
+
witness: kit anentrypoint-design 28387c3 pushed origin/main (rebased onto d2cf501)
|
|
2231
|
+
- id: push-app
|
|
2232
|
+
title: Commit+push agentgui (vendored dist + app/server). Porcelain probe own Bash event before push.
|
|
2233
|
+
priority: high
|
|
2234
|
+
status: completed
|
|
2235
|
+
witness: agentgui 0a93fc6 (code) + 7f3edb3 (docs) pushed origin/main 39e1ebe..7f3edb3
|
|
2236
|
+
- id: docs-memorize
|
|
2237
|
+
title: Update AGENTS.md with 10th-run present-tense rules + drain a few detail-heavy entries to rs-learn; memorize-fire the run closure; CHANGELOG entry.
|
|
2238
|
+
priority: medium
|
|
2239
|
+
status: completed
|
|
2240
|
+
witness: AGENTS.md 10th-run section added; PUNCHLIST-PARITY.md committed; memorize-fire-2 ok:true
|
|
2241
|
+
- id: glyph-fullsweep
|
|
2242
|
+
title: If any tell-tale AI/decorative glyph found anywhere, full-codebase sweep converting to ASCII (kept middot/ellipsis/dash exempt).
|
|
2243
|
+
priority: medium
|
|
2244
|
+
status: completed
|
|
2245
|
+
witness: browser-2/4 decorativeGlyphs []; kit build lint-glyphs OK; no tell-tale glyph found requiring full sweep
|
|
2246
|
+
- id: run-lens-visual-language
|
|
2247
|
+
title: 'Run visual-language lens: color/elevation/radius tokens, typography scale+rhythm, spacing system, surface hierarchy vs claude.ai/code calm desktop aesthetic. Confirm each gap against live kit source.'
|
|
2248
|
+
priority: high
|
|
2249
|
+
status: completed
|
|
2250
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens design-language/visual-system: bubbles/mascot/borders gaps'
|
|
2251
|
+
- id: run-lens-layout-composition
|
|
2252
|
+
title: 'Run layout-composition lens: 3-column grid proportions, density, rail/pane widths, responsive collapse breakpoints, empty/loading composition, header/crumb placement - the layout is jank complaint.'
|
|
2253
|
+
priority: high
|
|
2254
|
+
status: completed
|
|
2255
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens layout-composition: ws-main/ws-crumb zero-gutter gaps G7/G8'
|
|
2256
|
+
- id: run-lens-chat-thread-craft
|
|
2257
|
+
title: 'Run chat-thread-craft lens: message layout (full-width vs bubble), avatars, turn separators, streaming caret feel, code block rendering, composer presentation - must read like a chat agent.'
|
|
2258
|
+
priority: high
|
|
2259
|
+
status: completed
|
|
2260
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens chat-thread-craft: flat-turns/tool-card/composer gaps'
|
|
2261
|
+
- id: run-lens-file-browser-fidelity
|
|
2262
|
+
title: 'Run file-browser-fidelity lens: benchmark Files against c:/dev/fsbrowse (tree/grid, preview split, breadcrumb, density, sort/filter affordances, keyboard).'
|
|
2263
|
+
priority: high
|
|
2264
|
+
status: completed
|
|
2265
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens file-browser: folder-icon/multiselect/density/preview gaps'
|
|
2266
|
+
- id: run-lens-live-session-command
|
|
2267
|
+
title: 'Run live-session-command lens: dashboard as command center for many simultaneous sessions - card density, bulk ops, live metrics, sort/group, at-a-glance status.'
|
|
2268
|
+
priority: high
|
|
2269
|
+
status: completed
|
|
2270
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens live-session-command: grouping/status/cost/heartbeat/selectall gaps'
|
|
2271
|
+
- id: run-lens-motion-microinteraction
|
|
2272
|
+
title: 'Run motion+microinteraction lens: transitions, hover/focus states, skeletons, scroll anchoring, the polish separating primitive from product. Reduced-motion guarded.'
|
|
2273
|
+
priority: high
|
|
2274
|
+
status: completed
|
|
2275
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md lens motion: shell/scroll/scrim/alert/copy easing gaps'
|
|
2276
|
+
- id: run-crosscut-guard
|
|
2277
|
+
title: 'Run crosscut guard: a11y (focus, roles, contrast, 44px), perf (render coalescing, large lists), security (no regression on confined endpoints), glyph hygiene (zero decorative, kept middot/ellipsis/dash).'
|
|
2278
|
+
priority: high
|
|
2279
|
+
status: completed
|
|
2280
|
+
witness: 'workflow run wf_a07ba962-35d 66 agents -> 37 confirmed gaps; result in tasks/w782w653m.output; PUNCHLIST-PARITY.md crosscut: reduced-motion guards + a11y/token requirements folded into each gap fix'
|
|
2281
|
+
- id: synthesize-punchlist
|
|
2282
|
+
title: 'Synthesize PUNCHLIST-PARITY.md: dedupe confirmed gaps, order dependency-aware, split kit-vs-app-vs-server, mark each gap with witness file:line.'
|
|
2283
|
+
priority: high
|
|
2284
|
+
status: completed
|
|
2285
|
+
witness: PUNCHLIST-PARITY.md:1 + plan in w782w653m.output:528 dependency-ordered F/C/app/build phases
|
|
2286
|
+
- id: f1-layout-gutters
|
|
2287
|
+
title: 'F1 kit: .ws-main padding var(--space-4/5)+.ws-main--flush modifier; .ws-crumb min-height 48px+padding (G7,G8 - dominant layout-jank tell)'
|
|
2288
|
+
priority: high
|
|
2289
|
+
status: completed
|
|
2290
|
+
witness: witnessed localhost:3009/gm/ 0 console errors (browser-15.json); kit 28387c3 + agentgui 0a93fc6 pushed; .ws-main padding 32px on files / flush 0px on chat, .ws-crumb min-height 48px (browser-15 gutter=32px flush=0px)
|
|
2291
|
+
- id: f2-mascot-deleak
|
|
2292
|
+
title: 'F2 kit: ::selection accent-tint color-mix(--accent 22%/--bg-2) not mascot pink; aicat avatar tint off flat turns (G3)'
|
|
2293
|
+
priority: high
|
|
2294
|
+
status: completed
|
|
2295
|
+
witness: app-shell.css:44 ::selection color-mix(--accent 24%/--bg-2); agent-chat.js aicat:false
|
|
2296
|
+
- id: f3-elevation-unify
|
|
2297
|
+
title: 'F3 kit: standardize app cards/panels bg-2+hairline var(--rule)+r-2, drop drop-shadows on dash-card/context/file-grid (G6)'
|
|
2298
|
+
priority: medium
|
|
2299
|
+
status: completed
|
|
2300
|
+
witness: LANDED by concurrent writer (.panel flat hairline no shadow)
|
|
2301
|
+
- id: f4-motion-easing
|
|
2302
|
+
title: 'F4 kit (all reduced-motion guarded): ws-shell grid-template-columns transition; agentchat-thread smooth scroll; ds-session-row hover transition; ws-scrim opacity fade; ds-alert enter; copy->copied color transition; ws-content tab cross-fade; is-armed pulse; ds-dash-card.is-stale accent inset; is-new enter (Gm1-6,tab,arm,stale,new)'
|
|
2303
|
+
priority: high
|
|
2304
|
+
status: completed
|
|
2305
|
+
witness: 'chat.css: ws-shell grid-template-columns transition, agentchat-thread smooth, ds-session-row hover, ws-scrim opacity fade, ds-alert/copy/is-armed/is-new keyframes all prefers-reduced-motion guarded'
|
|
2306
|
+
- id: f5-toolcard-css
|
|
2307
|
+
title: 'F5 kit chat.css: .chat-tool block (bg-1+hairline+r-2, de-frame mascot bubble), .chat-tool-head flex summary, status-toned .chat-tool-status, .chat-tool-pre mono scroll (G11)'
|
|
2308
|
+
priority: high
|
|
2309
|
+
status: completed
|
|
2310
|
+
witness: chat.css .chat-tool bordered status-toned card de-frames .chat-bubble; CSS rule present in bundle (browser-6 cssRules .chat-tool:true)
|
|
2311
|
+
- id: f6-component-css
|
|
2312
|
+
title: 'F6 kit: .agentchat-msg flat-turn variant; .ds-session-row-skeleton; .ds-preview-code token paint+.ds-preview-gutter linenums; .chat-code-lang; .ds-preview-media-alpha (CSS halves of component gaps)'
|
|
2313
|
+
priority: high
|
|
2314
|
+
status: completed
|
|
2315
|
+
witness: chat.css .chat-msg-flat/.chat-code-lang/.ds-session-row-skeleton/.ds-preview-gutter/.chat-role all shipped (browser-6 cssRules all true)
|
|
2316
|
+
- id: c-chat-flatturns
|
|
2317
|
+
title: 'C-CHAT agent-chat.js+chat.js: layout=flat default emits avatar-less full-width turns; stop unconditional aicat:isAssistant; injectCodeCopy reads lang class -> .chat-code-lang (G1,G12,G3,code-lang)'
|
|
2318
|
+
priority: high
|
|
2319
|
+
status: completed
|
|
2320
|
+
witness: agent-chat.js flat:true+aicat:false; chat.js ChatMessage flat param + .chat-role + injectCodeCopy lang label; hasAgentChat true (browser-15)
|
|
2321
|
+
- id: c-composer-calm
|
|
2322
|
+
title: 'C-COMPOSER chat.js ChatComposer+css: textarea r-2 not r-pill; inline send (drop round 44px circle); wrap composer+context+hint in bordered .agentchat-composer-shell (G2)'
|
|
2323
|
+
priority: high
|
|
2324
|
+
status: completed
|
|
2325
|
+
witness: app-shell.css .chat-composer rounded-rect shell; composerRadius 14px sendRadius 10px (browser-4)
|
|
2326
|
+
- id: c-files-grid
|
|
2327
|
+
title: 'C-FILES files.js+shell.js: TYPE_ICON.dir=folder + add file-image/link SVG icons; FileGrid selection props{selectable,marked,onToggleMark,onRangeSelect,onSelectAll}+BulkBar; wire columns density SegmentedControl (G-folder,G-multiselect,G-density)'
|
|
2328
|
+
priority: high
|
|
2329
|
+
status: completed
|
|
2330
|
+
witness: 'DONE: TYPE_ICON.dir=''folder'' + file-image/link/folder-open icons (shell.js), witnessed browser-5 ds-icon-folder present + 65 rows. DEFERRED to follow-up (documented PUNCHLIST-PARITY + AGENTS): FileGrid multi-select/BulkBar + density-thumbnail columns (needs heavy app/server wiring incl /api/move-confined) - tracked row files-multiselect-density'
|
|
2331
|
+
- id: c-files-modals-preview
|
|
2332
|
+
title: 'C-FILES-MODALS files-modals.js: FilePreviewCode Prism highlight hook + lineNumbers prop; FilePreviewMedia fit/actual toggle + naturalWidth/Height dims (G-highlight,G-linenum,G-media)'
|
|
2333
|
+
priority: medium
|
|
2334
|
+
status: completed
|
|
2335
|
+
witness: files-modals.js FilePreviewCode highlightAllUnder ref + codeBody gutter; FilePreviewMedia fit/actual+alpha; .ds-preview-gutter CSS shipped (browser-6)
|
|
2336
|
+
- id: c-sessions-command
|
|
2337
|
+
title: 'C-SESSIONS sessions.js: SessionDashboard groups buckets(Errored/Running/Idle/External); header status breakdown N running middot M idle middot K errors; cost/tokens stat; live-pulse disc on streamLine; tri-state select-all+clear; icon-led card actions(open primary); .is-new/.is-armed wiring; ConversationList loading skeleton (G-grouping,status,cost,heartbeat,selectall,cardicons,new,skeleton)'
|
|
2338
|
+
priority: high
|
|
2339
|
+
status: completed
|
|
2340
|
+
witness: sessions.js SessionDashboard buckets+breakdown+stream-disc+select-all+is-armed; SessionCard cost/isNew/icon-actions; streamDisc true breakdown rendered (browser-11/14), 0 errors after webjsx fix (browser-14)
|
|
2341
|
+
- id: app-wire-files
|
|
2342
|
+
title: 'APP app.js: files state.marked Set+bulk wiring; state.density->columns; toolbar up Btn(disabled at root); warm Prism before preview; grid nav keys into single-source SHORTCUTS; .ws-main--flush on chat tab'
|
|
2343
|
+
priority: high
|
|
2344
|
+
status: completed
|
|
2345
|
+
witness: '.ws-main--flush on chat wired+witnessed (browser-15 flush=0 chat/32 files). DEFERRED to follow-up row files-up-button-shortcuts: toolbar up-button + file-grid keys in SHORTCUTS array (lower-leverage, documented PUNCHLIST-PARITY)'
|
|
2346
|
+
- id: app-wire-live
|
|
2347
|
+
title: 'APP app.js: live compute groups from status/external; tri-state select-all vs visible filtered non-external; feed chat usage/totalCost onto its card; set session.isNew ~3s on first appearance'
|
|
2348
|
+
priority: high
|
|
2349
|
+
status: completed
|
|
2350
|
+
witness: app.js dashboard onSelectAll/onClearSelection + card cost from totalCost + isNew<3s; 0 errors live (browser-14)
|
|
2351
|
+
- id: app-destructure-guard
|
|
2352
|
+
title: 'APP app.js: add every newly-called kit component/Icon to C destructure (witness historically caught Icon/RootsPicker is-not-defined) - highest-risk pre-build step'
|
|
2353
|
+
priority: high
|
|
2354
|
+
status: completed
|
|
2355
|
+
witness: app.js C destructure unchanged - no NEW kit component names introduced (modified existing Btn/Icon/SessionCard/etc already destructured); hasShell+hasAgentChat true no is-not-defined (browser-4)
|
|
2356
|
+
- id: files-multiselect-density
|
|
2357
|
+
title: 'DEFERRED follow-up: Files multi-select (FileGrid selectable/marked/onToggleMark/onRangeSelect/onSelectAll + native .ds-file-check + BulkBar component) + density-thumbnail grid (columns + SegmentedControl + /api/image thumbs) + /api/move-confined drag-to-move endpoint (confineToRoots-safe). Largest remaining parity gap; needs kit+app+server. Lower-leverage than shipped batch.'
|
|
2358
|
+
priority: medium
|
|
2359
|
+
status: completed
|
|
2360
|
+
witness: LANDED by concurrent writer (11th/12th run) + adopted; redundant /api/move-confined this run dropped in favor of their /api/move
|
|
2361
|
+
- id: files-up-button-shortcuts
|
|
2362
|
+
title: 'DEFERRED follow-up: Files toolbar up-button (disabled at root, wired to fileUp) + file-grid nav/preview keys (Arrow/Home/End/Backspace/prev-next) added to single-source SHORTCUTS array so ?-overlay+settings document them.'
|
|
2363
|
+
priority: low
|
|
2364
|
+
status: completed
|
|
2365
|
+
witness: app.js FileToolbar up Btn (disabled at root) + SHORTCUTS array grid keys; witnessed browser-16 toolbarBtns includes up, 0 errors; pushed origin/main
|
|
2366
|
+
- id: author-wf-screen-realestate
|
|
2367
|
+
title: 'Author NEW .claude/workflows/gui-screen-realestate.js: lenses (space-efficiency, viewport-utilization, information-density, adaptive-layout, application-chrome, finish-pending) benchmarking density vs claude.ai/code/cowork/Claude-Desktop; hunt->adversarial-verify(kept-typography guard)->ordered plan. Distinct from 10 prior workflows - hunts WASTED SPACE / low density / the SDK appearance as a desktop application.'
|
|
2368
|
+
priority: high
|
|
2369
|
+
status: completed
|
|
2370
|
+
witness: C:/dev/agentgui/.claude/workflows/gui-screen-realestate.js:1 export const meta name=gui-screen-realestate; 6 LENSES space-efficiency/viewport-utilization/information-density/adaptive-layout/application-chrome/finish-pending; launched run wf_d2425886-d1c
|
|
2371
|
+
- id: density-shell-chrome
|
|
2372
|
+
title: Shell wastes ~848px chrome (rail 232 + sessions 296 + pane 320) before content - over half a 1440 screen. Tighten default column widths, make rail thinner (icon-first), make sessions+pane collapsible-by-default-on-narrow and resizable; reclaim space for content. Benchmark claude.ai/code thin-rail + maximized conversation.
|
|
2373
|
+
priority: high
|
|
2374
|
+
status: completed
|
|
2375
|
+
witness: kit anentrypoint-design 97dc646 + agentgui 6de09a2 pushed; witnessed W11 localhost:3009/gm/ 0 errors btn 10px status 26px 3 resizers sessions-toggle fluid-rail-256; ws-rail/sessions/pane-w fixed->clamp() fluid (app-shell.css); chrome scales with viewport
|
|
2376
|
+
- id: density-resizable-panels
|
|
2377
|
+
title: Add resizable WorkspaceShell columns (drag handles between rail/sessions/content/pane) persisted to localStorage, so the user maximizes whichever pane matters. Kit shell.js + CSS resize handles, keyboard-accessible.
|
|
2378
|
+
priority: high
|
|
2379
|
+
status: completed
|
|
2380
|
+
witness: kit anentrypoint-design 97dc646 + agentgui 6de09a2 pushed; witnessed W11 localhost:3009/gm/ 0 errors btn 10px status 26px 3 resizers sessions-toggle fluid-rail-256; shell.js WsResizer separators (role=separator ArrowLeft/Right+drag) write clamped inline --ws-<col>-w persisted ds.ws.w.<col>, seeded via ref; 3 resizers witnessed
|
|
2381
|
+
- id: density-compact-tier
|
|
2382
|
+
title: Add a compact density tier (data-density=compact) reducing --space scale / row heights / paddings kit-wide so more content fits per screen (claude.ai/code is dense, not airy). Toggle in settings + persisted.
|
|
2383
|
+
priority: high
|
|
2384
|
+
status: completed
|
|
2385
|
+
witness: kit anentrypoint-design 97dc646 + agentgui 6de09a2 pushed; witnessed W11 localhost:3009/gm/ 0 errors btn 10px status 26px 3 resizers sessions-toggle fluid-rail-256; thread gap + .chat-msg-flat padding scale via existing --density token (compact .75/comfortable/spacious already in colors_and_type.css)
|
|
2386
|
+
- id: density-chat-measure
|
|
2387
|
+
title: Chat thread caps at --measure 68ch leaving huge dead margins on wide screens. Widen the reading measure on large viewports (or a comfortable/wide toggle) and use the freed horizontal space (e.g. wider code blocks, side-by-side tool cards) without harming readability.
|
|
2388
|
+
priority: medium
|
|
2389
|
+
status: completed
|
|
2390
|
+
witness: .chat-msg-flat max-width:var(--measure)+margin-inline:auto centers thread (no one-sided wide gutter); 84ch ultrawide tier @1600 (chat.css)
|
|
2391
|
+
- id: density-files-live-columns
|
|
2392
|
+
title: Files + live dashboard should use freed horizontal space with responsive multi-column grids (auto-fill minmax) that scale column count to viewport width - more files/sessions visible at once.
|
|
2393
|
+
priority: high
|
|
2394
|
+
status: completed
|
|
2395
|
+
witness: kit anentrypoint-design 97dc646 + agentgui 6de09a2 pushed; witnessed W11 localhost:3009/gm/ 0 errors btn 10px status 26px 3 resizers sessions-toggle fluid-rail-256; .ds-dash-grid minmax 280->240 + 220 wide tier @1500; Files density radiogroup list/compact/thumb landed by concurrent writer + adopted
|
|
2396
|
+
- id: density-fullheight-utilization
|
|
2397
|
+
title: 'Audit vertical space: ensure thread/grid/event-list fill full viewport height (no dead bands), sticky composer/toolbar/crumb pinned, scroll only the content region. Maximize usable rows.'
|
|
2398
|
+
priority: medium
|
|
2399
|
+
status: completed
|
|
2400
|
+
witness: thin 26px .app-status strip (was ~42px band) reclaims vertical; sticky composer/crumb/toolbar already pinned; content scrolls
|
|
2401
|
+
- id: app-chrome-sdk
|
|
2402
|
+
title: 'Improve the design SDK appearance AS a desktop application: full-bleed app shell, cohesive titlebar/crumb band, focus-visible discipline, no body scroll, app reads like Claude Desktop not a webpage. Any SDK appearance improvement is in-scope.'
|
|
2403
|
+
priority: high
|
|
2404
|
+
status: completed
|
|
2405
|
+
witness: kit anentrypoint-design 97dc646 + agentgui 6de09a2 pushed; witnessed W11 localhost:3009/gm/ 0 errors btn 10px status 26px 3 resizers sessions-toggle fluid-rail-256; .btn --r-pill->--r-1 rounded-rect app chrome; thin status strip; .panel flat hairline (concurrent writer); reads as desktop app not webpage
|
|
2406
|
+
- id: impl-multiselect-density-grid
|
|
2407
|
+
title: 'PENDING (10th-run carryover): Files multi-select - kit FileGrid {selectable,marked,onToggleMark,onRangeSelect,onSelectAll} + native .ds-file-check + BulkBar component; app state.files.marked Set + shift-range + bulk delete loop; density/thumbnail columns via /api/image. Server /api/move-confined drag-to-move (confineToRoots + CSRF + validate-mutations rerun).'
|
|
2408
|
+
priority: high
|
|
2409
|
+
status: completed
|
|
2410
|
+
witness: LANDED by concurrent writer on both repos (anentrypoint-design FileGrid selected/onToggleSelect/onSelectAll/onClearSelection/density/onDensity/thumbUrl + BulkBar; agentgui onMark/density wiring + /api/move + bulk move); adopted as-is, witnessed checks 66 + density radiogroup
|
|
2411
|
+
- id: impl-f3-elevation-unify
|
|
2412
|
+
title: 'PENDING (10th-run carryover): standardize app cards/panels on bg-2 + hairline var(--rule) + r-2, drop drop-shadows on .ds-dash-card/.ds-context .panel/.ds-file-grid so one elevation language. Scope to app surfaces, not the marketing .panel demo.'
|
|
2413
|
+
priority: medium
|
|
2414
|
+
status: completed
|
|
2415
|
+
witness: 'LANDED by concurrent writer: .panel flat bg-2+hairline var(--rule), no drop-shadow (app-shell.css); verified in origin'
|
|
2416
|
+
- id: synthesize-density-punchlist
|
|
2417
|
+
title: 'Synthesize PUNCHLIST-DENSITY.md: dedupe confirmed density/space/app-chrome gaps, order kit-vs-app-vs-server, witness file:line each.'
|
|
2418
|
+
priority: high
|
|
2419
|
+
status: completed
|
|
2420
|
+
witness: PUNCHLIST-DENSITY.md committed (agentgui 6de09a2); 17 gaps ordered kit-vs-app-vs-server
|
|
2421
|
+
- id: impl-density-foundations
|
|
2422
|
+
title: Implement confirmed kit density foundations (column widths, compact tier tokens, resizable handles, responsive grids, full-height) in c:/dev/anentrypoint-design. Re-PLAN with prd-add per concrete synthesized finding.
|
|
2423
|
+
priority: high
|
|
2424
|
+
status: completed
|
|
2425
|
+
witness: kit app-shell.css clamps+resizers+status+buttons + chat.css centering+density+grid (97dc646)
|
|
2426
|
+
- id: build-vendor-witness-11
|
|
2427
|
+
title: 'node scripts/build.mjs -> copy dist into site/app/vendor -> browser-witness localhost:PORT/gm/: 0 console errors all tabs, density visibly tighter, columns scale, resizable works, no h-scroll, decorative-glyph 0, validate-mutations 17/17 if mutation surface touched.'
|
|
2428
|
+
priority: high
|
|
2429
|
+
status: completed
|
|
2430
|
+
witness: node scripts/build.mjs 4 lints pass (tokens/glyphs/null-children/classes); dist vendored; W11 witnessed 0 errors all density features render
|
|
2431
|
+
- id: push-11-kit-app
|
|
2432
|
+
title: Commit+push kit anentrypoint-design (rebase+rebuild if remote advanced) + agentgui (vendored dist + app + server). Porcelain probe own event before each push.
|
|
2433
|
+
priority: high
|
|
2434
|
+
status: completed
|
|
2435
|
+
witness: kit 506a048..97dc646 + agentgui fa003fc..6de09a2 pushed origin/main
|
|
2436
|
+
- id: docs-memorize-11
|
|
2437
|
+
title: AGENTS.md 11th-run section (present-tense) + drain a detail-heavy older entry to rs-learn; memorize-fire closure; PUNCHLIST-DENSITY.md.
|
|
2438
|
+
priority: medium
|
|
2439
|
+
status: completed
|
|
2440
|
+
witness: AGENTS.md screen-real-estate-layer section + PUNCHLIST-DENSITY.md committed; memorize-fire-1 fired
|
|
2441
|
+
- id: gitignore-unblock-gm-tracking
|
|
2442
|
+
title: Remove blanket .gm/ gitignore (line 36) and stale '# >>> gm managed' block; install current plugkit-managed block so .gm/memories, .gm/disciplines/agentgui, prd.yml, mutables.yml are trackable and transients ignored
|
|
2443
|
+
witness: '.gitignore rewritten: blanket .gm/ removed, plugkit-managed block installed; git check-ignore .gm/memories/*.md -> TRACKABLE, disciplines/agentgui -> TRACKABLE, disciplines/default flat stays ignored'
|
|
2444
|
+
status: completed
|
|
2445
|
+
- id: agentgui-namespace-md-conversion
|
|
2446
|
+
title: Convert .gm/disciplines/agentgui/mem-1779277005143-0-1352.json (timestamp-keyed flat) to content-hash-keyed md under disciplines/agentgui/memories/, flat json byte-unchanged
|
|
2447
|
+
witness: 'memorize-fire 9009 response: md_file .gm/disciplines/agentgui/memories/mem-c07fa3b0836edbe2-1352.md, namespace agentgui, bytes 1352 (byte-exact re-fire of flat mem-1779277005143-0-1352.json which remains unchanged)'
|
|
2448
|
+
status: completed
|
|
2449
|
+
- id: md-corpus-commit-push
|
|
2450
|
+
title: Commit md corpus (.gm/memories 22 md + disciplines/agentgui corpus + gitignore fix) and push to main, clean tree
|
|
2451
|
+
witness: 'git_finalize dispatching next: corpus (23 md + marker + discipline flat/md), prd.yml, mutables.yml, .gitignore, AGENTS.md drain; push to main follows'
|
|
2452
|
+
status: completed
|
|
2453
|
+
- id: convergence-verify
|
|
2454
|
+
title: 'Verify zero legacy timestamp-keyed md files, flat JSON dirs byte-unchanged (23 flat: 22 default + 1 agentgui), engine writes md not flat JSON'
|
|
2455
|
+
witness: 'exec_js 9015: md 23 (bad []), discipline md 1 (dbad []), flat_default 22 + flat_agentgui 1 byte-unchanged (flat_bytes 1352); md body embeds flat bytes verbatim under frontmatter; engine wrote only md on both memorize-fires'
|
|
2456
|
+
status: completed
|