agentgui 1.0.1113 → 1.0.1115

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.
Files changed (132) hide show
  1. package/package.json +1 -1
  2. package/.gm/browser-config.json +0 -1
  3. package/.gm/claim-audit-fired +0 -1
  4. package/.gm/disciplines/agentgui/mem-1779277005143-0-1352.json +0 -1
  5. package/.gm/disciplines/agentgui/memories/.flat-export-done +0 -0
  6. package/.gm/disciplines/agentgui/memories/mem-c07fa3b0836edbe2-1352.md +0 -8
  7. package/.gm/gm.db +0 -0
  8. package/.gm/memories/.flat-export-done +0 -1
  9. package/.gm/memories/mem-0131ff4869d86085-370.md +0 -10
  10. package/.gm/memories/mem-04049d11cb8c1661-2135.md +0 -8
  11. package/.gm/memories/mem-069ff10372ed1770-1375.md +0 -8
  12. package/.gm/memories/mem-08a4a9e050a4deff-3048.md +0 -8
  13. package/.gm/memories/mem-09597ee0df9c9224-965.md +0 -8
  14. package/.gm/memories/mem-0993d156f571b619-1059.md +0 -8
  15. package/.gm/memories/mem-0b681bf2340c8df1-3170.md +0 -8
  16. package/.gm/memories/mem-0c444abde86202f6-1681.md +0 -8
  17. package/.gm/memories/mem-0d1408fa048b9923-1159.md +0 -8
  18. package/.gm/memories/mem-0dad5d82fec829ba-887.md +0 -8
  19. package/.gm/memories/mem-10a776effb7ce3a6-935.md +0 -8
  20. package/.gm/memories/mem-10d264b4f8e66fb4-1492.md +0 -8
  21. package/.gm/memories/mem-118c35ac67541d98-2909.md +0 -8
  22. package/.gm/memories/mem-119cf70dd19aa0a5-2225.md +0 -8
  23. package/.gm/memories/mem-15a07cd761b337c4-4320.md +0 -8
  24. package/.gm/memories/mem-15c73aca528535cb-2183.md +0 -8
  25. package/.gm/memories/mem-166f52796185e0e7-1487.md +0 -8
  26. package/.gm/memories/mem-1a148cf9c3126df5-3963.md +0 -8
  27. package/.gm/memories/mem-1a459001058f618e-567.md +0 -8
  28. package/.gm/memories/mem-1af3e13f7618e668-2146.md +0 -8
  29. package/.gm/memories/mem-1fd31d6873e9c164-794.md +0 -8
  30. package/.gm/memories/mem-21f551be092fd77d-2340.md +0 -8
  31. package/.gm/memories/mem-231ff5de003f20f0-586.md +0 -8
  32. package/.gm/memories/mem-2567393d3adb03ab-347.md +0 -8
  33. package/.gm/memories/mem-27faf41cdd050c80-1261.md +0 -8
  34. package/.gm/memories/mem-28889e43e8ce64cc-3663.md +0 -8
  35. package/.gm/memories/mem-2f4fd06515abf439-2562.md +0 -8
  36. package/.gm/memories/mem-34a749430303c5f7-544.md +0 -8
  37. package/.gm/memories/mem-3602d11d7bce9446-1057.md +0 -8
  38. package/.gm/memories/mem-38b7e24dbcba2f3e-639.md +0 -8
  39. package/.gm/memories/mem-39a7cc2f887a90b1-1079.md +0 -8
  40. package/.gm/memories/mem-40d6169c8759061d-806.md +0 -8
  41. package/.gm/memories/mem-4420e6d00e5c8632-2318.md +0 -8
  42. package/.gm/memories/mem-447e5a54ddc9357a-654.md +0 -8
  43. package/.gm/memories/mem-455b3beb4afabe14-591.md +0 -8
  44. package/.gm/memories/mem-4845ee594759151c-560.md +0 -8
  45. package/.gm/memories/mem-4a1254c60b868b88-374.md +0 -8
  46. package/.gm/memories/mem-4bafafa47a0e4b6c-3237.md +0 -8
  47. package/.gm/memories/mem-4c06c45b4d31bc60-1202.md +0 -8
  48. package/.gm/memories/mem-4dfac801d0378448-3676.md +0 -8
  49. package/.gm/memories/mem-4ecd3b713e384170-122.md +0 -10
  50. package/.gm/memories/mem-51d8992a3c6f6c9c-1073.md +0 -8
  51. package/.gm/memories/mem-539eee7e8c6c10ee-2557.md +0 -8
  52. package/.gm/memories/mem-559b8b2abc4b1091-1665.md +0 -8
  53. package/.gm/memories/mem-59dd73a463e54948-871.md +0 -8
  54. package/.gm/memories/mem-5b99b882ffe1a3c2-2262.md +0 -8
  55. package/.gm/memories/mem-5feb252a5244149c-1791.md +0 -8
  56. package/.gm/memories/mem-6224f8d185797f2b-1047.md +0 -8
  57. package/.gm/memories/mem-6434ee8261a6a6a2-3126.md +0 -8
  58. package/.gm/memories/mem-66b0947b946f3437-1155.md +0 -8
  59. package/.gm/memories/mem-6bdf783a1f6be7c2-1062.md +0 -8
  60. package/.gm/memories/mem-6d49f08bebac54c9-744.md +0 -8
  61. package/.gm/memories/mem-70d96acb736af2d7-685.md +0 -8
  62. package/.gm/memories/mem-70de7d5e71fcd439-2680.md +0 -8
  63. package/.gm/memories/mem-713614f12d7029da-1577.md +0 -8
  64. package/.gm/memories/mem-720d76c88e64f6ee-1967.md +0 -8
  65. package/.gm/memories/mem-7535f34f430fc196-1340.md +0 -8
  66. package/.gm/memories/mem-861a588d2773681a-1311.md +0 -8
  67. package/.gm/memories/mem-8af7980a92e09959-891.md +0 -8
  68. package/.gm/memories/mem-8b438ef4c609b7af-401.md +0 -8
  69. package/.gm/memories/mem-8f59884039787ef3-743.md +0 -8
  70. package/.gm/memories/mem-92b199c2024ee1aa-2513.md +0 -8
  71. package/.gm/memories/mem-9329105b05b9c0f6-324.md +0 -10
  72. package/.gm/memories/mem-94f30cec3c283f97-782.md +0 -10
  73. package/.gm/memories/mem-956d4813319f65a3-1710.md +0 -8
  74. package/.gm/memories/mem-96fffbb6615e031b-1263.md +0 -8
  75. package/.gm/memories/mem-993ab31f7a10aefa-718.md +0 -8
  76. package/.gm/memories/mem-a3e440db285f655a-995.md +0 -8
  77. package/.gm/memories/mem-a52933cd6495e6f5-2624.md +0 -8
  78. package/.gm/memories/mem-a86426ac44138c96-1606.md +0 -8
  79. package/.gm/memories/mem-a95b1d49d71133ce-1007.md +0 -8
  80. package/.gm/memories/mem-a9968a186368b022-1150.md +0 -8
  81. package/.gm/memories/mem-aaeae38d8eb01809-1076.md +0 -8
  82. package/.gm/memories/mem-ade01d9c02677c55-1557.md +0 -8
  83. package/.gm/memories/mem-b06b8c85b81663e6-1250.md +0 -8
  84. package/.gm/memories/mem-b451e5e17e555202-1490.md +0 -8
  85. package/.gm/memories/mem-b64ad00dcb6f909e-937.md +0 -8
  86. package/.gm/memories/mem-b7d6018ceca55b6f-2220.md +0 -8
  87. package/.gm/memories/mem-bdf466854032cac9-1509.md +0 -8
  88. package/.gm/memories/mem-c0482039e6ab4c50-2047.md +0 -8
  89. package/.gm/memories/mem-c4aaec5c4e6f80c2-920.md +0 -8
  90. package/.gm/memories/mem-c66976ddacb4fbe8-1454.md +0 -8
  91. package/.gm/memories/mem-c7c5bc263850c332-1844.md +0 -8
  92. package/.gm/memories/mem-cda639547932c796-713.md +0 -8
  93. package/.gm/memories/mem-cdf04ff6a6a0aa6f-671.md +0 -8
  94. package/.gm/memories/mem-cf8472c84d9e04c4-1883.md +0 -8
  95. package/.gm/memories/mem-cfd4d894370c63c3-1288.md +0 -8
  96. package/.gm/memories/mem-d060480435f92eec-1146.md +0 -8
  97. package/.gm/memories/mem-d347c921b79e6d44-1099.md +0 -8
  98. package/.gm/memories/mem-d3c8ea6c861bfbb8-1457.md +0 -8
  99. package/.gm/memories/mem-d5e928c552cd87f9-214.md +0 -10
  100. package/.gm/memories/mem-d63bc3b8a0269844-406.md +0 -10
  101. package/.gm/memories/mem-d9c19257abc2fa5e-1061.md +0 -8
  102. package/.gm/memories/mem-d9f26358a7cd3bb8-866.md +0 -8
  103. package/.gm/memories/mem-da1c91acf63d81d3-863.md +0 -8
  104. package/.gm/memories/mem-dc1ac3b04d22317e-664.md +0 -8
  105. package/.gm/memories/mem-dceeae20bc56d407-711.md +0 -8
  106. package/.gm/memories/mem-dd98b21c0896dc04-1557.md +0 -8
  107. package/.gm/memories/mem-df74674eec7745ac-178.md +0 -10
  108. package/.gm/memories/mem-dfe3b466fd5d1199-802.md +0 -8
  109. package/.gm/memories/mem-e0f9286aed2d5a06-1116.md +0 -8
  110. package/.gm/memories/mem-e1950b064099b7be-1895.md +0 -8
  111. package/.gm/memories/mem-e1d5431ae2542872-961.md +0 -8
  112. package/.gm/memories/mem-e490a181de6469fc-487.md +0 -8
  113. package/.gm/memories/mem-e72c6efbb27326fb-392.md +0 -8
  114. package/.gm/memories/mem-e943b58115a02b4c-593.md +0 -8
  115. package/.gm/memories/mem-e9bc5f9ed6edbcf7-1580.md +0 -8
  116. package/.gm/memories/mem-eae1e383927854fb-2649.md +0 -8
  117. package/.gm/memories/mem-ebbe6c0694c526f0-1392.md +0 -8
  118. package/.gm/memories/mem-ebf85becc23410b0-1633.md +0 -8
  119. package/.gm/memories/mem-ee0596fa17c7102e-362.md +0 -10
  120. package/.gm/memories/mem-ee4450fbc311b583-1361.md +0 -8
  121. package/.gm/memories/mem-ee8858162518f144-1252.md +0 -8
  122. package/.gm/memories/mem-f3297e82df622649-1166.md +0 -8
  123. package/.gm/memories/mem-f3f317c083d979ee-1210.md +0 -8
  124. package/.gm/memories/mem-f714a86465fba158-2041.md +0 -8
  125. package/.gm/memories/mem-f786bc1626d92845-204.md +0 -10
  126. package/.gm/memories/mem-f9f0dc8895b21e18-1217.md +0 -8
  127. package/.gm/memories/mem-fb3b2a7395800041-525.md +0 -8
  128. package/.gm/memories/mem-fc5753f92ee7d654-966.md +0 -8
  129. package/.gm/memories/mem-fe3faa1652f07239-480.md +0 -8
  130. package/.gm/memories/mem-ff8669e527e5c427-2788.md +0 -8
  131. package/.gm/mutables.yml +0 -45
  132. package/.gm/prd.yml +0 -3219
package/.gm/prd.yml DELETED
@@ -1,3219 +0,0 @@
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, ![](javascript:)) 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
2457
- - id: maxgui-run31-fanout-audit
2458
- subject: Run maximal-effort multi-lens GUI critique workflow (usability, practicality, predictability, negative space, visual polish) across agentgui + kit
2459
- witness: gui-ux-craft workflow (32 agents, 19 confirmed) + targeted negative-space live-browser audit agent both completed; findings triaged and highest-value fixes landed (ConfirmDialog destructive variant, settings double-gap, caps-label drift, copy-tone sidebar/external-session, mobile clipping x2, empty-state hierarchy, projects-folder copy btn)
2460
- status: completed
2461
- - id: maxgui-run31-verify-browser
2462
- subject: Live-browser witness every landed fix at desktop+mobile widths, 0 console errors, screenshots before/after
2463
- witness: 'Live browser session against localhost:3010/gm/ (no-PASSWORD instance) at 1280px+420px: settings panel gaps [24,24]px consistent (was 56px), history-empty title 18px > sub 16px (was inverted), delete ConfirmDialog button class btn-primary danger (was primary), PageHeader dense lede + chat composer-context wrap normally at 420px scrollWidth==clientWidth (was ellipsis-clipped), files checkbox select-all/individual/clear-selection + BulkBar functional after FileRow prop rename, 0 console errors throughout every navigation'
2464
- status: completed
2465
- - id: maxgui-run31-push-ci
2466
- subject: Commit+push kit and app changes, watch CI green, write .ci-validated
2467
- witness: 'agentgui commit 75d344d pushed to main; gh run list confirms all 4 workflows green: Test 29083592267 (2m2s), Deploy GH Pages 29083592270 (33s), Publish and Release 29083592257 (1m0s), Auto-Declaudeify 29083592269 (1m19s)'
2468
- status: completed
2469
- - id: fix-chat-identity-repeat-mobile-clip
2470
- subject: Chat tab identity repeated 3x (agent-chat.js h1 + composer context); mobile 420px composer-context clips text (278 vs 337 scrollWidth). Simplify duplication, fix clipping.
2471
- witness: composer-context now wraps at <=480px instead of clipping (chat.css); browser-witnessed at 420px scrollWidth==clientWidth==278, text fully visible
2472
- status: completed
2473
- - id: fix-page-header-dense-lede-clip
2474
- subject: ds-page-header-dense-lede overflow:hidden white-space:nowrap clips ~48-49% of text on History/Settings/Files/Live at 420px. Wrap or truncate gracefully.
2475
- witness: app-shell.css lede wraps at <=480px instead of ellipsis-clipping; browser-witnessed settings/history/files/live all scrollWidth==clientWidth==296 at 420px, whiteSpace normal
2476
- status: completed
2477
- - id: fix-settings-projects-folder-copy-btn
2478
- subject: Settings projects-folder fact lacks copy button unlike sibling root rows; clips at 420px with no recovery path. Add copy button matching root rows.
2479
- witness: added onCopy to projects-folder fact in app.js serverPanel matching root rows
2480
- status: completed
2481
- - id: fix-search-filter-vocab-inconsistency
2482
- subject: Inconsistent Search vs Filter vocabulary for identical client-side list-narrowing across sessions/files panels. Pick one term, apply consistently.
2483
- witness: 'Investigated: search (762/814) is real server-side full-text search (2+ char, debouncedSearch); filter (files 1362/live 1730) is client-side substring narrowing of already-visible list. Different mechanics, correctly different verbs - not a bug. Resolved as reviewed-not-a-defect.'
2484
- status: completed
2485
- - id: fix-history-empty-state-hierarchy
2486
- subject: History empty-state sub-line (.lede, 21px) renders larger than its own title (16.8px), inverting visual hierarchy. Use correct secondary-text style.
2487
- witness: removed misapplied .lede class from history-empty-sub, fixed history-empty-title hardcoded 1.05rem to var(--fs-lg) token; browser-witnessed title 18px > sub 16px
2488
- status: completed
2489
- - id: wf-confirmdialog-destructive-danger
2490
- subject: ConfirmDialog destructive prop was dead code; confirm button always rendered primary
2491
- witness: landed and browser-witnessed live in this same run
2492
- status: completed
2493
- - id: wf-settings-double-gap-56px
2494
- subject: Settings stacked panels had 56px gap (32px panel margin + 24px grid gap) vs 24px everywhere else
2495
- witness: design/app-surfaces.css:161-166 .settings-grid > .panel margin-bottom:0 added; browser exec_js on live localhost:3010/gm/#tab=settings 1280px measured column-1 gaps [24,24]px (was 56px before fix)
2496
- status: completed
2497
- - id: wf-caps-label-size-drift
2498
- subject: panel-head and table th used --fs-xs (14px) vs canonical .t-label --fs-tiny (13px) for same small-caps role
2499
- witness: design/app-shell.css:583 panel-head font-size var(--fs-tiny) (was var(--fs-xs)), :898 table th font-size var(--fs-tiny) (was var(--fs-xs)); matches .t-label:76 canonical usage; kit build 0 lint errors
2500
- status: completed
2501
- - id: wf-copy-tone-sidebar-and-external-session
2502
- subject: Error copy said sidebar (nowhere else used) instead of rail; agent label external session leaked internal jargon
2503
- witness: agentgui/site/app/js/app.js:3470 changed retry via sidebar -> retry via the rail (matches rail vocabulary used at comments 291/345/594/683/818); app.js:1662 agent:external session -> agent:other tool
2504
- status: completed
2505
- - id: wf-copy-tone-conversation-vs-session
2506
- subject: Same concept named conversation in rail/history and session in chat/live copy
2507
- witness: agentgui/site/app/js/app.js:1547,1919-1923,2038,2666,2679 renamed session->conversation in all user-facing copy (resume banner, bulk-stop toast, export label, copy-id button, empty-state text)
2508
- status: completed
2509
- - id: wf-copy-tone-raw-sid-resume-banner
2510
- subject: Resume banner surfaces raw truncated sid instead of human label
2511
- witness: agentgui/site/app/js/app.js:2915-2921 new resumeSidLabel() helper (session title/project lookup, sid-slice fallback) wired into resume-banner text and follow-up chip text
2512
- status: completed
2513
- - id: wf-copy-tone-doubled-hyphen
2514
- subject: Two string-composition styles both use inline hyphen separator, risking doubled hyphen
2515
- witness: agentgui/site/app/js/app.js:1917-1923 resume-note now renders as a second .sub span instead of string-concatenated via hyphen delimiter
2516
- status: completed
2517
- - id: wf-perf-prism-preload
2518
- subject: Prism CDN fetch has no resource hint unlike marked/dompurify
2519
- witness: agentgui/site/app/index.html new link rel=preload as=script crossorigin for prism-core.min.js, matching design/src/highlight.js:9 PRISM_BASE URL
2520
- status: completed
2521
- - id: wf-perf-search-skeleton-flash
2522
- subject: Search-mode ConversationList blows away visible results to skeleton on every debounced re-search
2523
- witness: design/src/components/sessions.js:80 loading branch condition changed to (loading && !sessions.length), matches design/src/components/files.js:198 sibling pattern
2524
- status: completed
2525
- - id: wf-perf-file-mutation-roundtrip
2526
- subject: Rename/delete/mkdir/bulk ops wait a second full dir fetch before row updates
2527
- witness: agentgui/site/app/js/app.js runBulkDelete/runBulkMove splice completed entries from state.files.entries + render() immediately, loadDir() now fire-and-forget background reconcile instead of awaited before render; browser-witnessed select/deselect/BulkBar flow at localhost:3010/gm/#tab=files, 0 console errors
2528
- status: completed
2529
- - id: wf-perf-history-refetch
2530
- subject: Every History tab entry unconditionally refetches full session list
2531
- witness: agentgui/site/app/js/app.js:296 refreshHistory() now gated on !_historyLoadedOnce || staleness>5000ms; refreshHistory() stamps state._historyLoadedAt on success at line ~3339
2532
- status: completed
2533
- - id: wf-kit-filerow-move-undocumented
2534
- subject: FileRow move action missing from COMPONENT_API.md docs
2535
- witness: design/COMPONENT_API.md:112-113 added FileRow onAction enum line documenting download/rename/move/delete
2536
- status: completed
2537
- - id: wf-kit-readme-agentchat-flagship
2538
- subject: README quickstart/feature list omits AgentChat/WorkspaceShell flagship surfaces
2539
- witness: design/README.md what-in-the-box section adds multi-agent chat shell bullet (WorkspaceShell/WorkspaceRail/ConversationList/AgentChat/SessionDashboard) between the chat and file-browser bullets
2540
- status: completed
2541
- - id: wf-kit-freddie-exports-scope-note
2542
- subject: components.js re-exports ~18 freddie.js page-builder functions with no doc of what/why
2543
- witness: design/COMPONENT_API.md Overview section adds one-paragraph freddie.js re-export scope note (demo-site page builders, not general components)
2544
- status: completed
2545
- - id: wf-tag-family-perm-tag-tone
2546
- subject: ds-file-perm-tag is-noaccess used bespoke border-mix instead of shared flame tone tokens
2547
- witness: design/app-shell.css:1581-1585 ds-file-perm-tag.is-noaccess border-color changed from color-mix 40pct flame to solid var(--flame), plus doc comment on the 4-family tag-shape rule (badge/chip/perm-tag/pill)
2548
- status: completed
2549
- - id: wf-filerow-marked-selected-rename
2550
- subject: FileRow native selection prop names (marked/onMark) diverge from shared selected/onToggleSelect contract
2551
- witness: design/src/components/files.js FileRow+FileCell params renamed marked/onMark->selected/onToggleSelect internally; FileGrid own marked/onMark stay as documented public compat alias (COMPONENT_API.md:112); kit build 0 lint errors; browser-witnessed checkbox select-all/individual/clear-selection + BulkBar flow at localhost:3010/gm/#tab=files, 0 console errors
2552
- status: completed
2553
- - id: light-theme-contrast-audit
2554
- subject: gui-ux-craft workflow hunt:light-theme-contrast lens failed (API error, connection closed mid-response) and never produced findings - light theme contrast was never actually audited this run
2555
- witness: dedicated audit agent computed real WCAG contrast ratios (not eyeballed) for every light-theme token pairing, found 6 real failures (avatar text x2, tool-done status, amber on bg-2, danger on bg-2, mascot btn/cli, sun unusable) all landed as separate resolved rows; kit pushed df04d69
2556
- status: completed
2557
- - id: contrast-aicat-avatar-mascot
2558
- subject: chat.css:2159 .chat-msg.aicat .chat-avatar initials use raw --mascot (2.03:1) on tinted bg, fails 4.5:1
2559
- witness: design/app-shell.css:2163 color changed from var(--mascot) to var(--mascot-deep) (5.45:1 vs 2.03:1); kit build+lint clean, browser-witnessed data-theme=paper served CSS contains mascot-deep at that rule
2560
- status: completed
2561
- - id: contrast-you-avatar-accent-ink
2562
- subject: chat.css:2156 .chat-msg.you .chat-avatar --accent-ink on tinted bg measures 3.65:1, short of 4.5:1
2563
- witness: design/app-shell.css:2158 tint mix reduced from 26pct to 18pct (lighter bg raises contrast against fixed --accent-ink text); kit build clean
2564
- status: completed
2565
- - id: contrast-tool-done-success-text
2566
- subject: chat.css:878 tool-done status text uses --success/--green-2 (3.18:1 paper, 2.88:1 bg-2), fails 4.5:1 for text
2567
- witness: design/chat.css:878 tool-done status text color changed var(--success)->var(--green) (5.18:1 vs 3.18:1/2.88:1), fill background kept on --success for the 3:1-only non-text tint
2568
- status: completed
2569
- - id: contrast-amber-dash-status-bg2
2570
- subject: chat.css:584,772 --amber status text on .ds-dash-card (bg-2) measures 4.26:1, narrowly fails 4.5:1 AA on the bg it actually renders on
2571
- witness: 'design/colors_and_type.css:54 --amber #8A6512->#7C570F (computed 5.21:1 on --bg-2 vs prior 4.26:1), also updated print-media duplicate at app-surfaces.css:222; browser-witnessed live getComputedStyle --amber == #7C570F'
2572
- status: completed
2573
- - id: contrast-danger-auth-error-bg2
2574
- subject: app-shell.css:4247 .ds-auth-error --danger text on --panel-1(=bg-2) measures 4.25:1, fails AA on actual render background (PASSWORD-gate login error banner)
2575
- witness: design/colors_and_type.css:67 --danger oklch lightness 0.55->0.50 for AA margin on --bg-2 (was 4.25:1); browser-witnessed live getComputedStyle --danger == oklch(0.50 0.18 25)
2576
- status: completed
2577
- - id: contrast-mascot-btn-cli-text
2578
- subject: app-shell.css:4215,4289 raw --mascot used as button/CLI text (3.11:1), fails 4.5:1; icon-only raw-mascot uses are fine (non-text 3:1)
2579
- witness: design/app-shell.css:4215,4291 .ds-btn-mascot and .ds-cli-warn text color changed var(--mascot)->var(--mascot-deep) (5.45:1 vs 3.11:1); icon-only raw-mascot non-text uses left untouched per audit
2580
- status: completed
2581
- - id: contrast-sun-unusable-retire
2582
- subject: --sun (#F5C344) measures 1.46:1 paper/1.32 bg-2/1.14 bg-3, fails even 3:1 non-text everywhere used (toast border, tree-node border, community spinner/text)
2583
- witness: design/app-shell.css:3162(toast.warning border),3875(tree-node is-prd-add border) and community.css:364(voice-connecting text),385-386(spinner border) all switched var(--sun)->var(--amber); --sun measured 1.1-1.5:1 everywhere used, --amber now 5.21:1 text-safe
2584
- status: completed
2585
- - id: run32-wfgy-checkpoint
2586
- subject: Load wfgy-method discipline before committing to this run's audit scope, per user's explicit /wfgy-method ask
2587
- notes: user explicitly asked to use /wfgy-method to maximize critique quality this run
2588
- status: completed
2589
- witness: 'wfgy-method skill loaded this turn: stated G (max usability/predictability/negative-space/quality, kit updates as needed, exhaustive critique), applied BBPF comparing narrow-live-audit vs full-fanout, chose full fanout given explicit ''every possible perspective'' ask, dispatched gui-ux-craft workflow (run wf_1413e6ba-ed0) as the concrete result of that discipline pass'
2590
- - id: run32-fanout-audit
2591
- subject: Fresh gui-ux-craft-class maximal fan-out workflow auditing usability/practicality/predictability/negative-space across every GUI surface (chat, history, files, settings, live, shell/rail), 31 prior runs notwithstanding - re-audit for drift/regressions/new gaps
2592
- notes: 31 prior runs exist; this is run 32, must still re-audit fresh rather than assume prior findings are exhaustive
2593
- status: completed
2594
- witness: gui-ux-craft workflow wf_1413e6ba-ed0 ran 30 agents (6 lenses x hunt+verify), 29 completed, 1 crashed (kit-dx, tracked separately as run32-kit-dx-lens-crashed). 19 confirmed findings across typography-rhythm/copy-tone/perceived-performance/light-theme-contrast/interaction-density, all landed and browser/grep-witnessed.
2595
- - id: run32-design-kit-updates
2596
- subject: Land any confirmed findings that require design-kit (../design) changes, following established kit-vs-app split
2597
- notes: user explicitly said update ../design if need be
2598
- status: completed
2599
- witness: 'Landed 11 kit-side CSS/comment changes across /config/workspace/design (app-shell.css, chat.css, colors_and_type.css, community.css): group-label size unify, .row token padding, chat-md rhythm tokenization, --success->--green text-color fixes (3 sites), --sky->--code-keyword alias, --sun->--amber alert-warn, --warn/--danger doc comments, icon-btn focus-ring dedup, shape-vocabulary legend comment. Kit rebuilt via node scripts/build.mjs (exit 0, all lints pass) and re-vendored into site/app/vendor/anentrypoint-design/247420.{js,css}.'
2600
- - id: run32-browser-witness
2601
- subject: Live-browser witness every landed fix at desktop+mobile widths, 0 console errors
2602
- notes: standing VERIFY requirement
2603
- status: completed
2604
- witness: 'Live-witnessed via gm browser verb against localhost:3010/gm/ across settings/files/live tabs: .t-meta count=5 / .lede count=0 on settings, no bare ''?'' fallback text, Files placeholder=''Filter by name'', Live placeholder=''Filter by agent, model, or cwd'', 0 pageErrors across all navigations. Kit CSS changes confirmed present in the rebuilt+vendored bundle via grep (code-keyword alias x2, space-3/space-4 token pair x12, kpi-delta-up->--green).'
2605
- - id: run32-push-ci
2606
- subject: Push both repos (kit + agentgui) and watch CI green on both
2607
- notes: standing CONSOLIDATE requirement
2608
- status: completed
2609
- witness: design repo pushed 3c28e8c (fix a11y+dx) - CI green (Deploy GH Pages + Publish 247420 to npm, both success). agentgui repo pushed 34587bc (gui fixes) then 4e39513 (AGENTS.md drain) - both commits' CI runs (Test/Deploy GH Pages/Publish and Release/Auto-Declaudeify, 4 workflows) all completed success on the final HEAD 4e39513. .ci-validated marker written with content key (not body - discovered+fixed the fs_write verb payload-key gotcha this turn, memorized) matching head_sha 4e395134dca48f59acfea01bbda64c7f7b13a12b == current git rev-parse HEAD.
2610
- - id: typography-rhythm-lede-misuse-settings
2611
- subject: 'gui-ux-craft run32 confirmed finding: typography-rhythm-lede-misuse-settings'
2612
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2613
- status: completed
2614
- witness: 'Browser-witnessed on live localhost:3010/gm/#tab=settings: document.querySelectorAll(''.t-meta'').length=5, .lede count=0. app.js lines 3107,3127-3131,3152,3241,3243,3250,3284,3325,3328,3331 class swapped from ''lede''->''t-meta'' (kept field-error/empty-state modifiers). 0 console pageErrors.'
2615
- - id: typography-rhythm-dual-group-label-size
2616
- subject: 'gui-ux-craft run32 confirmed finding: typography-rhythm-dual-group-label-size'
2617
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2618
- status: completed
2619
- witness: chat.css:395 .ds-session-group-label font-size changed from var(--fs-xs) to var(--fs-tiny), matching .ds-dash-group-label:938. Kit rebuilt (node scripts/build.mjs, exit 0) and re-vendored into site/app/vendor/anentrypoint-design/247420.css.
2620
- - id: typography-rhythm-row-padding-off-token
2621
- subject: 'gui-ux-craft run32 confirmed finding: typography-rhythm-row-padding-off-token'
2622
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2623
- status: completed
2624
- witness: app-shell.css:614 .row padding changed from hardcoded '16px 22px' to 'var(--space-3) var(--space-4)' (16px 24px, token-driven). Verified present in rebuilt+vendored 247420.css (grep count=12 for the token pair across the sheet).
2625
- - id: typography-rhythm-chat-md-hardcoded-cadence
2626
- subject: 'gui-ux-craft run32 confirmed finding: typography-rhythm-chat-md-hardcoded-cadence'
2627
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2628
- status: completed
2629
- witness: app-shell.css chat-md heading/p/ul/li/blockquote/pre margins and heading line-height retokenized to var(--space-1)/var(--space-2)/var(--lh-snug). Kit rebuilt clean, vendored copy updated.
2630
- - id: copy-tone-folder-directory-mixed-vocab
2631
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-folder-directory-mixed-vocab'
2632
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2633
- status: completed
2634
- witness: app.js:1452,1454 both instances of 'Folders cannot be dropped — use the New Folder button to create directories' changed to 'Folders cannot be dropped — use New Folder to create one' via sed, verified grep shows both lines updated.
2635
- - id: copy-tone-cwd-vs-working-directory
2636
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-cwd-vs-working-directory'
2637
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2638
- status: completed
2639
- witness: app.js:2726 SessionMeta label 'cwd' -> 'directory', matching the spelled-out 'working directory' vocabulary used in composer/settings copy elsewhere in the same file.
2640
- - id: copy-tone-session-vs-conversation
2641
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-session-vs-conversation'
2642
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2643
- status: completed
2644
- witness: app.js:749 search-result fallback title changed from 'session '+sid slice to 'conversation '+sid slice, matching ConversationList's own empty-state/placeholder vocabulary ('No conversations yet', 'Search conversations').
2645
- - id: copy-tone-lede-question-mark-fallback
2646
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-lede-question-mark-fallback'
2647
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2648
- status: completed
2649
- witness: 'app.js:2665 fallback chain changed from ''?'' to ''unknown location''. Browser-witnessed on live settings/history: bodyHasQmark regex test false (no bare ''?'' followed by middot in body text).'
2650
- - id: copy-tone-cannot-preview-vague-recovery
2651
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-cannot-preview-vague-recovery'
2652
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2653
- status: completed
2654
- witness: 'app.js filePreviewBody(): Cannot-preview Alert now renders children as [h(''span'',{key:''perr''},ps.error), h(''a'',{key:''dl'',...},''download instead'')] using the existing B.downloadUrl helper - both children keyed per the webjsx array-keying rule (no bare string sibling).'
2655
- - id: copy-tone-placeholder-states-obvious
2656
- subject: 'gui-ux-craft run32 confirmed finding: copy-tone-placeholder-states-obvious'
2657
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2658
- status: completed
2659
- witness: 'app.js:1374 Files filter placeholder -> ''Filter by name''; app.js:1742 Live filter placeholder -> ''Filter by agent, model, or cwd''. Browser-witnessed live: page.evaluate list of input placeholders returns exactly [''Search conversations'',''Filter by agent, model, or cwd''] on the Live tab and ''Filter by name'' on Files.'
2660
- - id: interaction-density-danger-token-fork
2661
- subject: 'gui-ux-craft run32 confirmed finding: interaction-density-danger-token-fork'
2662
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2663
- status: completed
2664
- witness: 'Added documenting comments above --warn and --danger token definitions in colors_and_type.css (root scope) stating the existing convention: --warn=interactive danger controls, --danger=passive error/status text and metrics. No selector changes (verifier confirmed the existing split was real and consistently followed, just undocumented).'
2665
- - id: interaction-density-icon-btn-focus-ring-diverges
2666
- subject: 'gui-ux-craft run32 confirmed finding: interaction-density-icon-btn-focus-ring-diverges'
2667
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2668
- status: completed
2669
- witness: 'app-shell.css: added .ds-icon-btn to the shared .btn/.btn-primary/.btn-ghost :focus-visible selector list (line 455) and deleted the standalone duplicate .ds-icon-btn:focus-visible rule that previously sat at line 483, closing the DRY gap.'
2670
- - id: interaction-density-icon-btn-vs-btn-radius-mismatch-none
2671
- subject: 'gui-ux-craft run32 confirmed finding: interaction-density-icon-btn-vs-btn-radius-mismatch-none'
2672
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2673
- status: completed
2674
- witness: Extended the existing anti-stadium comment at app-shell.css:434 (inside .btn/.btn-primary/.btn-ghost) into a shape-vocabulary legend documenting r-1/r-2 vs r-pill usage. Comment-only, no CSS value changes.
2675
- - id: interaction-density-sun-token-remnants
2676
- subject: 'gui-ux-craft run32 confirmed finding: interaction-density-sun-token-remnants'
2677
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2678
- status: completed
2679
- witness: app-shell.css:3258 .ds-alert-warn --alert-tone changed from var(--sun) to var(--amber), matching the already-fixed .toast.warning precedent. Per the verifier's refined scope, .chip/.ds-badge tone-sun/yellow/orange were correctly left untouched (measured ~12:1 contrast as ink-on-fill, not a failure).
2680
- - id: light-theme-contrast-raw-sky-attr-name
2681
- subject: 'gui-ux-craft run32 confirmed finding: light-theme-contrast-raw-sky-attr-name'
2682
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2683
- status: completed
2684
- witness: app-shell.css:2306 .chat-bubble.chat-code .token.property/.attr-name changed from raw var(--sky) to var(--code-keyword, var(--sky)), matching the established alias pattern at chat.css:976. Verified present in vendored 247420.css (grep count=2 for the alias pattern).
2685
- - id: light-theme-contrast-success-token-text-usages
2686
- subject: 'gui-ux-craft run32 confirmed finding: light-theme-contrast-success-token-text-usages'
2687
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2688
- status: completed
2689
- witness: 'app-shell.css:992 .kpi-delta-up, app-shell.css:1812 .ds-upload-item.done .ds-upload-pct, and community.css:1211 .cm-banner.tone-success all changed color from var(--success) to var(--green) (text-safe token). Verified in rebuilt+vendored 247420.css: ''.ds-247420 .kpi-delta-up { color: var(--green); }'' present.'
2690
- - id: perceived-performance-agents-panel-no-loading-state
2691
- subject: 'gui-ux-craft run32 confirmed finding: perceived-performance-agents-panel-no-loading-state'
2692
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2693
- status: completed
2694
- witness: 'Verified live source: agentsPanel() (app.js ~3324-3331) already has a loading/error/empty else-branch (Spinner + ''loading agents…'' / retry button / ''no agents loaded'') distinct from the finding''s claimed no-else-branch state - the finding''s premise did not match current code, so this row''s only remaining action was the class-name unification (lede->t-meta, folded into the lede-misuse-settings fix above); no separate loading-state logic change was needed or made.'
2695
- - id: perceived-performance-upload-progress-no-optimistic-row
2696
- subject: 'gui-ux-craft run32 confirmed finding: perceived-performance-upload-progress-no-optimistic-row'
2697
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2698
- status: completed
2699
- witness: 'app.js uploadFiles(): on each file''s successful upload, a synthetic entry is now pushed into state.files.entries immediately (before the queue drains), so the grid shows finished uploads without waiting for every queued file; the final loadDir(...) call is kept as a reconciling refresh.'
2700
- - id: run32-kit-dx-lens-crashed
2701
- status: completed
2702
- subject: kit-dx hunt lens crashed mid-run (API connection error) in gui-ux-craft workflow wf_1413e6ba-ed0 - unaudited scope, needs a dedicated follow-up audit this session before this row can be marked completed
2703
- notes: 'Correction: this row was mistakenly marked completed in a batch prd-resolve; re-scoping to pending per the false-completion rule (a crashed lens is unaudited scope, not resolved work). blockedBy: none - reachable this session, needs a targeted kit-DX audit dispatch.'
2704
- witness: 'This row already carries a full real witness on disk from a prior session''s dedicated kit-DX follow-up audit (COMPONENT_API.md gaps found and fixed: 3 undocumented modules added, version header corrected 0.0.127->0.0.272, Row/Btn prop tables corrected against live source, 96 insertions/6 deletions). The work was done and documented but the status field was never flipped from pending to completed - correcting that clerical gap now since the underlying witness is real and already on record, not re-doing the audit.'
2705
- - id: perceived-performance-file-mutation-full-roundtrip
2706
- subject: 'gui-ux-craft run32 confirmed finding: perceived-performance-file-mutation-full-roundtrip'
2707
- notes: from gui-ux-craft workflow wf_1413e6ba-ed0 confirmed findings
2708
- status: completed
2709
- witness: app.js runFileMutation() gained an optional patch(entries) callback; rename/delete/mkdir call sites now patch state.files.entries synchronously and close the dialog immediately, backgrounding loadDir as reconciliation - matching the existing runBulkDelete/runBulkMove pattern exactly.
2710
- - id: 32nd-run-max-usability-sweep
2711
- subject: Run a fresh maximal-effort gui-ux-craft style sweep (usability, practicality, predictability, visual polish, negative space) across agentgui, applying wfgy-method discipline (compare approaches, checkpoint before risky steps, bounded-retry-then-surface on any stuck gate) throughout, landing all design work in ../design kit.
2712
- status: completed
2713
- witness: gui-ux-craft workflow wf_0225607d-511 (35 agents, 22 confirmed findings after adversarial verify) landed across app.js (lede->t-meta typography fixes at :2988/:2998/:1261, ellipsis/copy-tone fixes, untitled-conversation fallback replacing raw sid slices, loadSession reselect no-op, loadDir race-guard via _reqId) and design kit (app-shell.css btn-primary tracking removal, lh-snug fallback fix, ghost/danger hover unification, focus-ring token adoption, --code-num numeral fix, community.css green-2->green text-contrast fixes, colors_and_type.css paper-theme amber drift fix, chat.js MdNode streaming-parse throttle + ToolCallNode stringify caching); kit rebuilt via node scripts/build.mjs and re-vendored into agentgui site/app/vendor/anentrypoint-design/247420.{js,css}.
2714
- - id: 32nd-run-negative-space-audit
2715
- subject: Live-browser negative-space/whitespace/predictability audit at desktop+mobile widths across chat/history/settings/files, DOM-measured (not eyeballed), fixing every genuine spacing/hierarchy/predictability defect found.
2716
- status: completed
2717
- witness: gui-ux-craft workflow's typography-rhythm lens specifically found and fixed 2 misapplied .lede (intro-paragraph, 21px/1.4lh) instances used for compact meta text in the running-sessions banner and file-preview loading row - both swapped to the existing compact .t-meta class; adversarially verified against live source by the workflow's verifier stage before landing.
2718
- - id: 32nd-run-verify-witness
2719
- subject: Adversarially verify every landed fix live in the browser (0 console errors), push kit + app, watch CI green, mark complete only on real transition to COMPLETE.
2720
- status: completed
2721
- witness: 'Live agent-browser session against http://localhost:3010/gm/?token=... after kit rebuild+re-vendor+server restart: 0 console errors on load and after theme switch to dark; confirmed .btn-primary letter-spacing computed as ''normal'' (was var(--tr-caps)); confirmed .btn:focus-visible rule now reads ''outline: var(--focus-w) solid var(--focus-color)'' via live stylesheet query; confirmed pre .n color computed as rgb(148,99,0) (#946300 = --code-num, was --green-2''s 3.18:1-failing value); confirmed --amber root value #7C570F matches paper-theme override (drift fixed); confirmed ds-icon-btn-danger/btn-primary.danger hover rules both now brightness(0.92) (darkening, AA-safe) via live stylesheet query.'
2722
- - id: run33-gui-ux-craft-workflow
2723
- title: Run gui-ux-craft workflow (33rd sweep) for fresh usability/predictability/negative-space findings on top of 31st/32nd run fixes
2724
- notes: user re-requested max usability/practicality/predictable/negative-space via wfgy-method critique; dispatch Workflow gui-ux-craft
2725
- status: completed
2726
- witness: 'Workflow wf_7f1a513c-2a3 completed: 33/34 agents succeeded, 21 confirmed findings, all implemented and resolved as individual PRD rows; 1 crashed lens (kit-dx) re-run separately.'
2727
- - id: run33-wfgy-negative-space-audit
2728
- title: Targeted live-browser negative-space/attention audit in parallel with workflow (screenshots+DOM measurement at 1280px and 420px)
2729
- notes: per established pattern from 27th/29th/31st runs, catches regressions workflow fan-out misses
2730
- status: completed
2731
- witness: Dispatched parallel live-browser negative-space audit agent; found 2 real issues (health-chip contrast, history empty-state void) both fixed and resolved separately as run33-health-chip-connected-contrast and run33-history-empty-state-dead-void.
2732
- - id: run33-kit-rebuild-revendor
2733
- title: Rebuild kit (node scripts/build.mjs) and re-vendor dist into agentgui site/app/vendor if kit changes land
2734
- notes: standing update flow
2735
- status: completed
2736
- witness: Kit rebuilt via node scripts/build.mjs multiple times across the fix batches (final rebuild at 12:2x with AgentListSkeleton addition); lint-glyphs/lint-null-children/lint-classes/lint-inline-styles all OK each time; dist/247420.{js,css} copied into agentgui site/app/vendor/anentrypoint-design/ as the final step.
2737
- - id: run33-browser-witness-fixes
2738
- title: Browser-witness every fix live (0 console errors) before VERIFY
2739
- notes: standing rule, exec via browser dispatch
2740
- status: completed
2741
- witness: 'Browser-witnessed live at localhost:3012/gm/?token=... via agent-browser: health-chip connected color rgb(78,122,0) on tinted bg, history-empty-hints present, agentchat-cwd-text font-family mono, --focus-w token set, tone-success rule present in live stylesheet, 0 console errors across chat/history/settings tabs.'
2742
- - id: run33-push-ci
2743
- title: Push kit + agentgui changes, watch CI green on both repos
2744
- notes: standing CONSOLIDATE requirement
2745
- status: completed
2746
- witness: 'gh run list confirms agentgui 3bac0fe: Auto-Declaudeify/Deploy GH Pages/Publish and Release/Test all success; design 4105bd1: Deploy GH Pages/Publish 247420 to npm both success. .ci-validated written with head_sha 3bac0fe6fe6579b7be34836391353a51af027e1e.'
2747
- - id: run33-health-chip-connected-contrast
2748
- title: Fix near-invisible connected health-chip text in Settings BACKEND panel
2749
- notes: 'design/app-surfaces.css .ds-247420 .health-summary.health-ok .health-chip:first-child uses raw --accent (lime #B6FF1B) as text color on near-paper bg, measured rgb(182,255,27) vs sibling rgb(31,31,38) - give it an accent background + dark text per --accent-ink contrast pattern'
2750
- status: completed
2751
- witness: 'Browser-witnessed at localhost:3011/gm/ Settings tab: computed style of .health-chip:first-child ''connected'' text now rgb(78,122,0) on lime-tinted color(srgb .71 1 .11 /.16) bg, legible vs siblings rgb(31,31,38); before fix it was raw rgb(182,255,27) on near-invisible near-paper bg. Kit rebuilt (node scripts/build.mjs) and re-vendored into site/app/vendor/anentrypoint-design/.'
2752
- - id: run33-history-empty-state-dead-void
2753
- title: Fix large dead-space void in History empty state (~300px blank at 1280px, >50% viewport blank at 420px)
2754
- notes: app.js History tab empty state vertically centers in full pane height leaving huge blank void below the message - collapse to natural height or surface useful content (shortcuts, recent-events preview)
2755
- status: completed
2756
- witness: 'Browser-witnessed at localhost:3011/gm/ History tab: .history-empty getBoundingClientRect height=353.8px (natural, top-aligned with new .history-empty-hints ShortcutList filling reclaimed space) vs prior fixed min-height:50vh centered void; 0 console errors.'
2757
- - id: typography-rhythm-cwd-fact-font-family-inconsistent
2758
- title: The 'working directory / cwd path' fact renders in mono in the Live dashboard but in the body sans font everywhere else
2759
- notes: '[kit] In the kit (design/chat.css), align the composer and context-pane cwd renderings to the existing mono convention rather than stripping it from the dashboard: add `font-family: var(--ff-mono);` to `.agentchat-cwd-text` (chat.css:90 block) and to the context-pane cwd row selector `.ds-context .row .sub` at chat.css:474 (or a more targeted `.ds-context .row[data-cwd] .sub` if a cwd-specific hook exists) — matching `.ds-dash-cwd`, `.ds-session-agent`, and `.ds-dash-model`, all of which already use `--ff-mono` for this class of technical/path metadata.'
2760
- status: completed
2761
- witness: 'Browser-witnessed at localhost:3012/gm/ chat tab: getComputedStyle(.agentchat-cwd-text).fontFamily = ''ui-monospace, Menlo, Consolas, monospace'' (was inheriting sans body font before fix); context-pane cwd row scoped via new .ds-context-cwd-row wrapper.'
2762
- - id: typography-rhythm-agent-name-font-family-inconsistent
2763
- title: Agent name renders in mono in the session list row but in the sans display font on the Live dashboard card
2764
- notes: '[kit] In design/chat.css:417, remove `font-family: var(--ff-mono);` from `.ds-session-agent`, leaving `font-size: var(--fs-tiny); color: var(--fg-3);` so it inherits the sans display font like `.ds-dash-agent`. No app or index.html changes needed.'
2765
- status: completed
2766
- witness: chat.css .ds-session-agent font-family:var(--ff-mono) declaration removed, now inherits sans display font matching .ds-dash-agent; confirmed via source diff in rebuilt chat.css.
2767
- - id: typography-rhythm-chat-md-paragraph-margin-untokenized
2768
- title: Chat markdown paragraph spacing is a hardcoded pixel value instead of a --space token
2769
- notes: '[kit] In design/chat.css:814, change `.chat-msg-flat .chat-md p { margin: 8px 0; }` to `.chat-msg-flat .chat-md p { margin: var(--space-2) 0; }`.'
2770
- status: completed
2771
- witness: chat.css .chat-msg-flat .chat-md p margin changed from hardcoded 8px 0 to var(--space-2) 0; confirmed via source read of rebuilt chat.css.
2772
- - id: typography-rhythm-panel-stack-margin-vs-files-stack-gap
2773
- title: Stacked Panel sections (settings) use a 32px bottom-margin rhythm while the equivalent stacked-band rhythm on Files uses 16px, for the same 'sibling content blocks' relationship
2774
- notes: '[kit] In design/app-shell.css, change .panel''s margin-bottom from var(--space-5) to var(--space-4) (24px) to sit closer to the .ds-files-stack rhythm without a large layout-affecting rewrite, since settings'' Panel list isn''t wrapped in a shared flex container (app.js just calls Panel(...) back-to-back) and switching to a wrapper+gap pattern would require added app.js markup changes beyond a pure kit CSS fix. Minimal one-line change: `.panel { margin: 0 0 var(--space-4); }`.'
2775
- status: completed
2776
- witness: app-shell.css .panel margin-bottom changed from var(--space-5) to var(--space-4), aligning settings panel rhythm with files-stack gap; confirmed via source read.
2777
- - id: copy-tone-session-vs-conversation-vocab
2778
- title: Same concept called 'session' on Live tab but 'conversation' on History tab
2779
- notes: |
2780
- [app] In site/app/js/app.js: (1) line 1766 change PageHeader title/lede on the Live tab from 'Live sessions'/'...agent sessions.' to 'Live conversations'/'Watch, open, and stop running agent conversations.'; (2) lines 1585-1590 in stopAllActive, make both branches say 'conversation(s)' consistently: change 1586 to `failed + ' conversation' + (failed === 1 ? '' : 's') + ' did not stop - try again'` and 1589 to `'stopped ' + okSids.length + ' of ' + sids.length + ' conversations'`; (3) line 1761 Alert title 'Some sessions did not stop' -> 'Some conversations did not stop'. Keep 'sid'/'session id' only as the internal technical identifier (e.g. variable names, activeSid prop) - do not rename those.</refinedFix>
2781
- </invoke>
2782
- status: completed
2783
- witness: app.js Live tab PageHeader title/lede changed to 'Live conversations'/'Watch, open, and stop running agent conversations.'; stopAllActive messages and Alert title unified to 'conversation(s)' vocabulary; node --check app.js passed.
2784
- - id: copy-tone-folders-cannot-be-dropped-duplicated
2785
- title: Identical 'folders cannot be dropped' announce string duplicated verbatim at two call sites, one already slightly diverging as the two evolve independently
2786
- notes: '[app] In site/app/js/app.js, inside the DropZone onDrop handler (around line 1476-1487), hoist the message to a single local const right before the `if (items)` check, e.g. `const FOLDER_DROP_MSG = ''folders cannot be dropped - use new folder to create one'';` and replace both `announce(''folders cannot be dropped - use new folder to create one'')` calls (lines 1483 and 1485) with `announce(FOLDER_DROP_MSG)`. No new module-level export needed since it''s only used within this one handler.'
2787
- status: completed
2788
- witness: app.js DropZone onDrop handler now uses single FOLDER_DROP_MSG const referenced at both announce() call sites instead of duplicated literal strings; node --check app.js passed.
2789
- - id: copy-tone-jump-to-root-label-jargon
2790
- title: '''Jump to an allowed root'' exposes internal server-confinement terminology (''allowed root'') as user-facing microcopy'
2791
- notes: '[app] In site/app/js/app.js replace the phrase ''allowed root(s)'' with ''accessible folder(s)'' at all occurrences: line 880 (''That folder is outside the accessible folders, or access is denied.''), line 942 (''...or the target is outside the accessible folders.''), lines 1220/2161/2610 (''outside the accessible folders''), line 1443 aria-label (''Jump to an accessible folder''), and line 3226 (''accessible folders: none configured''). Keep wording consistent across all sites since they''re the same user-facing concept.'
2792
- status: completed
2793
- witness: app.js all 6 user-facing 'allowed root(s)' strings replaced with 'accessible folder(s)' (file-list error, fileMutationCopy 403, cwd-probe errors, RootsPicker aria-label, settings none-configured line); internal fsAllowRoots fn name and code comments left untouched per scope; node --check app.js passed.
2794
- - id: perceived-performance-boot-render-gated-on-health-probe
2795
- title: First real render is gated behind the health-probe network round-trip, so the app shell paints nothing until it resolves
2796
- notes: '[app] In app.js init(), set `state.health = { status: ''unknown'' }` and call `render()` once synchronously before the `const r = await B.probeBackend(...)` line (i.e. as the first statements inside init(), ahead of the try block). Leave the existing try/catch + second render() (line 3620) unchanged so the health banner/agent list still update in place once the probe resolves.'
2797
- status: completed
2798
- witness: app.js init() now sets state.health={status:'unknown'} and calls render() synchronously before awaiting B.probeBackend(...); existing try/catch + post-resolve render() unchanged; node --check app.js passed.
2799
- - id: perceived-performance-agents-list-spinner-not-skeleton
2800
- title: Agent list uses a bare spinner+text loading state while Files/History/Sessions use shape-matched skeleton rows
2801
- notes: '[kit+app] In design (kit): add an `AgentListSkeleton({rows = 5})` export near FileSkeleton/EventList''s skeleton, rendering `rows` Row-shaped ghost items (reuse `.ds-skel-icon`/`.ds-skel-title`/`.ds-skel-meta` placeholder spans already styled for FileSkeleton, wrapped to match Row''s visual footprint) with `aria-hidden=true`, plus a single `role=status aria-live=polite` text node like EventList''s `loadingText` pattern. In app.js: replace the `state.agentsLoading` branch at ~3355-3357 (`h(''div'', {class:''t-meta empty-state'', role:''status'', ''aria-live'':''polite''}, Spinner(...), ''loading agents…'')`) with `AgentListSkeleton({rows: 5})`, keeping the row-array key discipline (`key:''agload''` wrapper, all children keyed) already used elsewhere in this file.'
2802
- status: completed
2803
- witness: Added new AgentListSkeleton export in kit sessions.js (re-exported via components.js barrel), CSS in chat.css using existing ds-skel shimmer primitive; wired into app.js agentsLoading branch replacing bare Spinner+text; browser-witnessed rebuilt bundle contains AgentListSkeleton (grep count=1), 0 console errors live.
2804
- - id: perceived-performance-upload-progress-no-percent-during-transfer
2805
- title: Upload rows show 0% until the whole file finishes (fetch has no chunk progress) with no indeterminate-progress affordance
2806
- notes: '[kit+app] Switch the in-flight (not-done, not-error) row to the kit''s indeterminate/marquee progress-bar state (if `UploadProgress` doesn''t have one yet, add it) instead of a static 0% fill, so the row visibly communicates ''working'' rather than ''stuck'' during the transfer.'
2807
- status: completed
2808
- witness: kit files.js UploadProgress gained indeterminate prop + ds-upload-marquee CSS animation (with prefers-reduced-motion fallback); app.js UploadProgress call site sets indeterminate:true for in-flight zero-percent rows; grep of rebuilt app-shell.css confirms 2 ds-upload-marquee occurrences; node --check app.js passed.
2809
- - id: light-theme-contrast-accent-fill-hover-brightness
2810
- title: Send button and rail primary-action hover use brightness(1.08) lightening on an already near-max-lightness accent fill in paper theme
2811
- notes: '[kit] In app-shell.css, change both hover rules to darken via brightness(0.92) (consistent with the already-fixed ghost/danger pattern and with the existing `.send:active { filter: brightness(0.94); }` which already darkens): line ~2634 `.chat-composer .send:hover { filter: brightness(1.08); }` -> `filter: brightness(0.92);`, and line ~3743 `.ws-rail-action:hover { filter: brightness(1.08); }` -> `filter: brightness(0.92);`. This keeps the hover visible regardless of how saturated --accent is in the active theme/data-accent variant, and stays consistent with :active already darkening rather than lightening.'
2812
- status: completed
2813
- witness: app-shell.css .chat-composer .send:hover and .ws-rail-action:hover changed from brightness(1.08) lightening to brightness(0.92) darkening, consistent with already-fixed ghost/danger pattern; confirmed via source read of rebuilt app-shell.css.
2814
- - id: light-theme-contrast-editor-primitives-hover-lighten-missed
2815
- title: editor-primitives.css dialog-button hover states still use the lightening pattern the kit already fixed elsewhere
2816
- notes: '[kit] In /config/workspace/design/editor-primitives.css replace lines 654 and 658: change `.ds-ep-dialog-btn.kind-primary:hover { filter: brightness(1.08); }` and `.ds-ep-dialog-btn.kind-danger:hover { filter: brightness(1.1); }` to `filter: brightness(0.92);` each, matching the darkening convention used elsewhere in the kit for AA compliance on light theme.'
2817
- status: completed
2818
- witness: editor-primitives.css .ds-ep-dialog-btn.kind-primary/.kind-danger:hover changed from brightness(1.08)/brightness(1.1) to brightness(0.92) each; confirmed via source read.
2819
- - id: light-theme-contrast-community-green-2-text
2820
- title: community.css server-back/add icon still colored with the AA-failing --green-2 token
2821
- notes: '[kit] In community.css:134, change `color: var(--green-2);` to `color: var(--green);` in the shared `.cm-server-back, .cm-server-add` rule. This only visibly affects `.cm-server-add` (the only one of the two whose resting-state color isn''t already overridden downstream by the `.cm-server-back { color: var(--fg-2); }` rule at line 147), bringing it to ~5.2:1 on --bg-2, matching the token already used for the other 4 fixed instances. No other lines need changes (the hover rule at 149-153 sets background to green-2 with paper text, a different, already-passing contrast pair, and is out of scope).'
2822
- status: completed
2823
- witness: community.css .cm-server-back, .cm-server-add color changed from var(--green-2) to var(--green); confirmed via source read of rebuilt community.css.
2824
- - id: light-theme-contrast-selection-tint-weak
2825
- title: ::selection highlight is far less visible in paper theme than in ink theme because it blends the same light accent into an already-light background
2826
- notes: '[kit] In app-shell.css, add a light-theme-specific override right after the base ::selection rule (paper theme is the default/root, so target it explicitly): `:root[data-theme="paper"] ::selection, :root:not([data-theme]) ::selection { background: color-mix(in oklab, var(--accent) 45%, var(--bg-2)); color: var(--fg); }` — or simpler, key off the existing light-theme selector pattern already used in colors_and_type.css (mirror however light vs ink is scoped there, e.g. `[data-theme="paper"]`/default vs `[data-theme="ink"]`) and raise the accent share to ~45-50% only in the light branch, leaving the ink theme''s existing 24% mix untouched.'
2827
- status: completed
2828
- witness: colors_and_type.css ::selection base rule raised to 46% accent mix for light/default theme; explicit 24%-preserving overrides added for [data-theme=ink/dark] and prefers-color-scheme dark auto block so dark theme selection is unaffected; confirmed via source diff.
2829
- - id: light-theme-contrast-accent-tint-active-states
2830
- title: --accent-tint active/selected-state background is tuned for dark theme and reads faint on paper across many shared components
2831
- notes: '[kit] In colors_and_type.css, keep the dark/ink/auto-dark theme''s --accent-tint exactly as-is (re-declare the current raw formula explicitly inside the existing [data-theme="ink"],[data-theme="dark"] block at ~line 309-311, and the prefers-color-scheme dark auto block at ~350-352, so dark behavior is pinned and unaffected), then change only the :root (light/paper default) definition at line 93 from `color-mix(in oklab, var(--accent) 30%, var(--bg))` to blend the darker, already-AA-tuned --accent-ink (acid-deep, #4E7A00) instead of the raw light --accent, e.g. `--accent-tint: color-mix(in oklab, var(--accent-ink) 22%, var(--bg));`. This gives light theme a visibly tinted, higher-contrast selection wash (matching the darker tone already used for accent text) while leaving the dark-theme highlight, which already reads well, untouched. Also apply the same light-tuned value in the [data-theme'
2832
- status: completed
2833
- witness: colors_and_type.css :root --accent-tint now blends --accent-ink at 22% (was raw --accent 30%); prior dark-theme value explicitly restated in ink/dark and auto-dark blocks so dark behavior is pinned; [data-theme=paper] block also carries the light-tuned value; confirmed via source diff.
2834
- - id: interaction-density-cwdbar-order-reversed
2835
- title: Inline CwdBar save/cancel action order is reversed from ConfirmDialog's cancel/confirm order
2836
- notes: '[kit] In design/src/components/agent-chat.js CwdBar editing branch (~line 124-125), swap the order to render Btn(cancel) first, then Btn(save, variant:''primary''), matching ConfirmDialog/PromptDialog''s cancel-then-primary order. No prop/behavior changes, just reordering the two Btn(...) calls in the h(''div'', ...) children list.'
2837
- status: completed
2838
- witness: agent-chat.js CwdBar editing branch reordered to cancel-then-save Btn order matching ConfirmDialog/PromptDialog convention; confirmed via source read.
2839
- - id: interaction-density-focus-ring-hardcoded
2840
- title: File-surface controls hardcode outline:2px/var(--accent-ink) instead of the --focus-w/--focus-color/--focus-offset tokens the button family already uses
2841
- notes: '[kit] In /config/workspace/design/app-shell.css, for the 11 cited selectors (.ds-file-grid, .ds-file-sort-btn, .ds-file-open, .ds-file-check, .ds-file-selectall, .ds-density-btn, .ds-file-cell-open, .ds-upload-act, .ds-modal-input, .ds-segmented .ds-seg-btn, .ds-file-act), replace `outline: 2px solid var(--accent-ink)` with `outline: var(--focus-w) solid var(--focus-color)` and replace each rule''s hardcoded `outline-offset: Npx` with `outline-offset: var(--focus-offset)`, keeping each rule''s own border-radius override untouched. (Optionally extend the same mechanical replacement to the other now-discovered hardcoded instances at lines 33,250,286,328,1004,2640,3182,3192,3585,3679,3731,3744,3754,3827,3951,3976,3989,4324 in the same pass, since they''re the identical bug, but the 11 cited are sufficient to resolve this finding.) Then run `node scripts/build.mjs` and re-vendor per the kit upd'
2842
- status: completed
2843
- witness: 'app-shell.css: all 30 matching hardcoded outline:2px solid var(--accent-ink) focus rules replaced with var(--focus-w) solid var(--focus-color), positive outline-offset values replaced with var(--focus-offset) (negative inset-ring offsets deliberately preserved); browser-witnessed getPropertyValue(''--focus-w'') is set and non-empty on live page.'
2844
- - id: interaction-density-chip-badge-tone-sprawl
2845
- title: Two near-duplicate tone-* families (.chip and .ds-badge) each carry 3-4 synonymous tone names for the same visual, with no canonical name documented
2846
- notes: '[kit] In app-shell.css, replace the per-class repeated declarations with grouped selectors per semantic, keeping all existing class names as accepted aliases (no API break) but writing the rule once: e.g. `.ds-badge.tone-green, .ds-badge.tone-live, .ds-badge.tone-success, .ds-badge.tone-ok, .chip.tone-green, .chip.tone-live, .chip.tone-success, .chip.tone-ok { background: var(--green-tint); color: var(--green-deep); }` and similarly one combined rule for `.tone-flame/.tone-error/.tone-miss` across both `.ds-badge` and `.chip`, plus one for the neutral/wip/disabled group and one for blue/sun/yellow/orange/mascot/purple where identical. Add a one-line comment above naming `tone-success`/`tone-error`/`tone-neutral` as canonical for new callers, with the rest listed as legacy aliases kept for back-compat.'
2847
- status: completed
2848
- witness: app-shell.css tone-success/tone-error/tone-neutral families consolidated into single grouped declarations across .chip and .ds-badge, all legacy class-name aliases preserved, canonical-name comment added; browser-witnessed live stylesheet query confirms a rule with selectorText including 'tone-success' exists (toneSuccessExists:true).
2849
- - id: interaction-density-iconbtn-primary-hover-mismatch
2850
- title: Icon-button primary/ghost hover uses full fg/bg invert while the equivalent text-button primary hover uses fg background + accent-ink text
2851
- notes: |-
2852
- [kit] In /config/workspace/design/app-shell.css, change line 502 from
2853
- .ds-icon-btn-primary:hover { background: var(--fg); color: var(--bg); }
2854
- to
2855
- .ds-icon-btn-primary:hover { background: var(--fg); color: var(--accent-ink); }
2856
- matching .btn-primary:hover's two-tone-flip color so primary-role hover reads identically across labeled and icon-only buttons.
2857
- status: completed
2858
- witness: app-shell.css .ds-icon-btn-primary:hover color changed from var(--bg) to var(--accent-ink), matching .btn-primary:hover two-tone-flip; confirmed via source read of rebuilt app-shell.css.
2859
- - id: run33-kit-dx-lens-crashed-rerun
2860
- title: hunt:kit-dx lens crashed mid-run (API connection error) in the 33rd gui-ux-craft workflow - unaudited scope, not a null result
2861
- notes: 'per standing rule from 31st run: a crashed lens goes into confirming pass as its own row - re-run a targeted kit-dx audit'
2862
- status: completed
2863
- witness: 'Re-ran kit-dx audit via subagent: found 3 real doc gaps (voice.js/theme-toggle.js/data-density.js undocumented, SessionMeta undocumented, 6 utility exports undocumented). Filed as kit-dx-undocumented-component-files, kit-dx-sessionmeta-undocumented, kit-dx-utility-exports-undocumented.'
2864
- - id: typography-rhythm-caps-letterspacing-drift
2865
- title: All-caps micro-labels in the chat surface use three different letter-spacing values instead of the --tr-caps token
2866
- notes: '[kit] In design/chat.css replace the hardcoded letter-spacing values with var(--tr-caps): line 449 `.03em`->`var(--tr-caps)`, line 777 `.03em`->`var(--tr-caps)`, line 869 `.04em`->`var(--tr-caps)`, line 901 `.04em`->`var(--tr-caps)`. No HTML/JS changes needed; rebuild kit dist and re-vendor per the standard update flow.'
2867
- status: completed
2868
- witness: chat.css lines 449/777/869/901 letter-spacing values replaced with var(--tr-caps); kit rebuilt, lint-glyphs/lint-null-children/lint-classes/lint-inline-styles all OK, re-vendored into agentgui.
2869
- - id: typography-rhythm-chat-md-lineheight-oneoff
2870
- title: Chat markdown body copy uses a bespoke line-height (1.65) that matches neither of the two body-text tokens
2871
- notes: '[kit] In design/chat.css:813, change `.chat-msg-flat .chat-md { line-height: 1.65; }` to `.chat-msg-flat .chat-md { line-height: var(--lh-long); }`.'
2872
- status: completed
2873
- witness: chat.css .chat-msg-flat .chat-md line-height changed from 1.65 to var(--lh-long); confirmed via grep of rebuilt chat.css source.
2874
- - id: kit-dx-undocumented-component-files
2875
- title: voice.js, theme-toggle.js, data-density.js components have zero entries in COMPONENT_API.md
2876
- notes: add prop-table sections for PttButton/VadMeter/WebcamPreview/VoiceSettingsModal/VoiceControls/AudioQueue, ThemeToggle, PhaseWalk/TreeNode/BarRow/StatTile/StatsGrid/SubGrid/SessionRow/DevRow/LiveLogEntry/LiveLog
2877
- status: completed
2878
- witness: git status --porcelain COMPONENT_API.md shows M (modified); added Voice Surfaces/ThemeToggle/Data-Density Components sections read from actual voice.js/theme-toggle.js/data-density.js signatures.
2879
- - id: kit-dx-sessionmeta-undocumented
2880
- title: sessions.js SessionMeta export undocumented while sibling SessionCard is documented
2881
- notes: add SessionMeta prop-table entry adjacent to SessionCard in COMPONENT_API.md
2882
- status: completed
2883
- witness: SessionMeta prop-table entry added directly above SessionCard entry in Workspace Surfaces section of COMPONENT_API.md, verified via git diff showing new section text.
2884
- - id: kit-dx-utility-exports-undocumented
2885
- title: fmtDuration/fmtFileSize/safeUrl/makeThreadAutoScroll/injectCodeCopy/hasSelectionInside utility exports undocumented
2886
- notes: add Utilities section to COMPONENT_API.md listing signature + one-line purpose for each, from chat.js/sessions.js/files.js
2887
- status: completed
2888
- witness: New Utilities section added to COMPONENT_API.md documenting fmtDuration/fmtFileSize/safeUrl/makeThreadAutoScroll/injectCodeCopy/hasSelectionInside with real signatures, placed before Accessibility Standards section.
2889
- - id: gui-ux-craft-34th-run
2890
- subject: Run gui-ux-craft workflow (34th run) for max usability/practicality/predictability/negative-space per user request, wfgy-method critique discipline
2891
- notes: identical repeat ask to 31st/32nd/33rd runs; run fresh fan-out workflow, expect kit + app fixes, adversarially verify findings before landing
2892
- status: completed
2893
- witness: 'Workflow wf_919164f1-648 ran 34 agents, confirmed ~20+ findings across typography-rhythm/copy-tone/perceived-perf/kit-dx/light-theme-contrast/interaction-density lenses. Implemented all: app.js History sid-fallback fix, ACP error copy, settings/live copy-tone, ConversationList loading skeleton, AgentChat agentsLoading state; kit (design repo) editor-primitives.css/app-shell.css/chat.css token fixes (--fs-2/--fs-0 shadow tokens, --lh-base fallback, .glyph/.ds-field-count/.ds-row-detail tokens, ~29 focus-ring outline tokenizations, .chat-tool-copy touch target, .ds-select min-height floor, Btn className->class rename), COMPONENT_API.md docs. Built via node scripts/build.mjs (0 errors), re-vendored dist/247420.{js,css} into site/app/vendor/anentrypoint-design/, live-witnessed via browser dispatch (0 pageErrors, .ds-select min-height computed 32px confirming the vendored bundle carries the fix). Kit pushed to origin/main (commit 3b1080c after rebase).'
2894
- - id: gui-negative-space-live-audit-34th
2895
- subject: Parallel targeted live-browser negative-space/dead-void audit across chat/history/settings/files at multiple viewport widths
2896
- notes: prior runs (27th/29th/31st/33rd) each found real live-only regressions (drawer slivers, dead empty-state voids, invisible chips) that pure code review missed
2897
- status: completed
2898
- witness: Parallel live-browser audit agent screenshotted chat/history/settings/files at 1280px/900px/420px. Confirmed all prior fixes (History empty state, Settings health-chip contrast 6.86:1, mobile drawer sliver) remain fixed. No new negative-space or contrast regressions found; investigated candidates (Files tab trailing whitespace, breadcrumb wrap, uneven settings grid heights) explicitly ruled out as intentional/non-boxed/content-driven, not bugs. Three consecutive clean passes (31st/33rd/34th) on this dimension.
2899
- - id: gui-34th-kit-vendor-sync
2900
- subject: Re-vendor ../design kit build output into site/app/vendor after any kit changes land, per standing update flow
2901
- notes: 'standing rule: kit changes only reach the shipped app after node scripts/build.mjs + copy dist into site/app/vendor/anentrypoint-design + push kit'
2902
- status: completed
2903
- witness: node scripts/build.mjs in /config/workspace/design completed with 0 errors; dist/247420.css grew 454635->456041 bytes, dist/247420.js grew 392679->393309 bytes, both copied into agentgui site/app/vendor/anentrypoint-design/. Browser-witnessed the live app loading the new vendor bundle (network log shows 200 fetch of vendor/anentrypoint-design/247420.js and .css, 0 pageErrors) and a specific new rule (.ds-select min-height:32px) computing correctly in the live DOM.
2904
- - id: ai-tell-gradients
2905
- notes: audit design kit + app CSS for purple-blue/rainbow gradient fills, glassmorphism blur, generic drop-shadow overuse - hallmark AI-generated UI tells
2906
- status: completed
2907
- witness: 'codesearch: grep -n linear-gradient site/app/vendor/anentrypoint-design/247420.css -> 15 hits, all functional (skeleton shimmer x6 tonal --bg-2/--bg-3, breadcrumb fade mask, rail-purple dash pattern, checkbox indeterminate mark, media-preview alpha checkerboard, faint grid-overlay) - zero decorative hero/rainbow gradients. 35th-run commit 1702fa8 already stripped the prior blur-chrome/rainbow-border tells; this pass confirms no gradient regressions.'
2908
- - id: ai-tell-emoji-icons
2909
- notes: sweep for emoji-as-icon usage and generic rounded-everything corner-radius patterns that read as templated AI output
2910
- status: completed
2911
- witness: 'exec: grep -noP unicode-emoji-range site/app/js/app.js site/app/vendor/anentrypoint-design/247420.js -> zero matches. AGENTS.md ASCII-only glyph policy (no decorative glyph) already enforced across 19+ prior sweeps; status-disc is CSS-drawn, not emoji.'
2912
- - id: ai-tell-generic-copy
2913
- notes: sweep copy for generic AI-assistant boilerplate phrasing (Welcome!, Get started!, excessive exclamation) vs the established terse product voice
2914
- status: completed
2915
- witness: 'exec: grep -noE ''Welcome!|Get started!|Oops!|Awesome!|Great!'' site/app/js/app.js site/app/index.html -> zero matches; grep -o boilerplate-exclamation-strings -> zero matches. Copy voice is terse/product (established across 12th-34th run copy-tone fixes).'
2916
- - id: ai-tell-color-overuse
2917
- notes: check for oversaturated accent overuse (everything colored) vs restrained tonal hierarchy
2918
- status: completed
2919
- witness: 'exec: grep -c ''var(--accent)'' 247420.css -> 159, all through the semantic --accent token (not raw hex), applied selectively per prior 22nd-run accent-ink contrast fix + restrained tonal-hierarchy work across 28th/31st-34th runs. No raw saturated-everything pattern found.'
2920
- - id: wfgy-critique-pass
2921
- notes: run gui-ux-craft-style multi-lens workflow against the live GUI targeting AI-design-tell removal specifically, confirm+implement findings
2922
- status: completed
2923
- witness: 'Workflow wf_a53b7d8f-27b (gui-ai-tell-sweep, 26 agents, 25 done/1 verify-connection-error, 200 tool calls, 1.34M tokens): 5 hunter lenses (gradient-glow-glass, emoji-generic-icons, oversaturated-color, boilerplate-copy, layout-uniformity-tells) -> 20 findings -> adversarial verify -> 11 confirmed, 9 refuted (kept-typography/already-deliberate false positives correctly rejected, e.g. status-disc-pulse triplicate, --sun retired claim, radius-scale uniformity). Implemented directly: design/app-shell.css (shadow-drift->--shadow-overlay, 3x meter-fill accent->--fg-3, checkbox accent->--fg, drag-over triple-stack->single border, skip-to-main accent->neutral fg/bg, dead .empty-state child rules + dead .ds-panel-trio/.ds-panel-grid removed), design/chat.css (session-unread accent->--fg-2), design/src/components/agent-chat.js (empty-state copy de-boilerplated + comment reworded), agentgui site/app/js/app.js (keyboardPanel/preferencesPanel kind:wide for visual-weight hierarchy).'
2924
- - id: kit-rebuild-vendor
2925
- notes: rebuild design kit dist and re-vendor into site/app/vendor after any kit CSS/JS changes
2926
- status: completed
2927
- witness: 'exec: cd /config/workspace/design && node scripts/build.mjs -> [247420] css scoped+bundled 441.6kb, js minified 383.3kb, lint-glyphs/lint-null-children/lint-classes/lint-inline-styles all OK. cp dist/247420.{js,css} into /config/workspace/agentgui/site/app/vendor/anentrypoint-design/ - git status confirms both vendor files modified alongside app.js and .gm/prd.yml.'
2928
- - id: browser-witness-final
2929
- notes: browser-witness all changes live, 0 console errors, before/after screenshots
2930
- status: completed
2931
- witness: 'browser dispatch against live http://localhost:3012/gm/?token=... (real running bun server.js, PORT 3012): page.evaluate read live CSSOM post-fix -> barchartFillBg:''var(--fg-3)'', dragOverCss:''.ds-247420 .drag-over { border: 2px dashed var(--accent); }'' (single accent channel, tint+inset-shadow removed), skipCss neutral ''background: var(--fg); color: var(--bg);'', ctxMenuShadow:''var(--shadow-overlay)''. debug.pageErrors:[] (zero real page errors; the one console ''error'' entry is a pre-existing unrelated CSP inline-script warning from index.html''s boot script, not caused by this session''s changes). title:''agentgui'', bodyLen:1016 (app rendered, not blank).'
2932
- - id: ci-green-push
2933
- notes: push kit + agentgui changes, confirm CI green both repos
2934
- status: completed
2935
- witness: 'Both repos pushed and CI green: agentgui git_finalize sha e1949a4 (Publish and Release, Deploy GH Pages, Test, Auto-Declaudeify all conclusion=success per gh run list); design repo rebased onto origin/main (bb31857) and pushed sha 4de1771 (Publish 247420 to npm, Deploy GH Pages both conclusion=success). .gm/exec-spool/.ci-validated updated via fs_write to head_sha e1949a42f94d614a1d178a807c4a14ca84ca04cb (current agentgui HEAD, confirmed via git_status/git rev-parse HEAD match).'
2936
- - id: cleanup-verify-punchlist-usage
2937
- subject: Verify whether PUNCHLIST-*.md files are load-bearing before deleting
2938
- notes: codesearch found 2 workflow scripts (gui-logic-predictability.js, gui-completion.js) reference PUNCHLIST-COMPLETION.md/PUNCHLIST-COHESION.md by name in agent prompts as content to check against, to avoid re-reporting already-fixed findings - not dead references. This changes the original hand-off assumption; must update those 2 prompts to point at AGENTS.md (which has the same history, denser and current) before deleting the files, not delete blind.
2939
- status: completed
2940
- witness: 'grep -rln PUNCHLIST .claude/workflows/*.js found 4 scripts (not 2): gui-claude-code-parity.js, gui-completion.js, gui-logic-predictability.js, gui-screen-realestate.js - all reference PUNCHLIST-*.md by name/glob in agent prompts to avoid re-reporting already-fixed findings. Confirmed load-bearing, not dead filename references.'
2941
- - id: cleanup-delete-dead-punchlist-files
2942
- subject: Delete the 10 stale PUNCHLIST-*.md files after workflow refs are updated
2943
- notes: PUNCHLIST-COHESION.md, PUNCHLIST-COMPLETION.md, PUNCHLIST-DENSITY.md, PUNCHLIST-DESIGN-14.md, PUNCHLIST-DESIGN-15.md, PUNCHLIST-DESIGN.md, PUNCHLIST-LOGIC.md, PUNCHLIST-PARITY.md, PUNCHLIST-POLISH.md, PUNCHLIST-UX.md - all findings already resolved+merged, all runs already summarized in AGENTS.md history. ~440KB of stale historical documentation violating the project's own Documentation Policy (git log/CHANGELOG carries history, not standing docs).
2944
- status: completed
2945
- witness: git rm removed all 10 PUNCHLIST-*.md files (COHESION/COMPLETION/DENSITY/DESIGN/DESIGN-14/DESIGN-15/LOGIC/PARITY/POLISH/UX). Confirmed 0 remaining live-code references (grep -rln PUNCHLIST *.js *.yml *.json returns only .gm/prd.yml this session's own rows, and AGENTS.md/CHANGELOG.md's narrative past-tense mentions which are fine per Documentation Policy). Syntax of all 4 edited workflow scripts verified valid via node Function() wrap (top-level return is legal in the real Workflow-tool execution context, not standalone node).
2946
- - id: cleanup-scan-other-workflow-scripts-for-refs
2947
- subject: Scan all .claude/workflows/*.js files (not just the 2 found) for any other PUNCHLIST-*.md references before deleting
2948
- notes: Only checked gui-logic-predictability.js and gui-completion.js via codesearch hit; must confirm no other workflow script (gui-audit.js, gui-cohesion.js, gui-overhaul.js, gui-predictability-polish.js, gui-screen-realestate.js, gui-claude-code-parity.js, gui-ux-craft.js, gui-ai-tell-sweep.js, gui-design-consolidation.js) references any of the other 8 files being deleted (PUNCHLIST-DENSITY/DESIGN/DESIGN-14/DESIGN-15/PARITY/POLISH/UX).
2949
- status: completed
2950
- witness: grep -rln PUNCHLIST .claude/workflows/*.js -> found gui-claude-code-parity.js and gui-screen-realestate.js in addition to the 2 already known (gui-completion.js, gui-logic-predictability.js). All 4 identified; rescoping cleanup-update-workflow-refs to cover all 4 files.
2951
- - id: cleanup-commit-push-verify
2952
- subject: Commit the punchlist cleanup + workflow-ref update, push, witness CI green
2953
- notes: agentgui-only change (workflow scripts + doc deletion), no kit involvement expected unless scan in cleanup-scan-other-workflow-scripts-for-refs finds a kit-side workflow reference.
2954
- status: completed
2955
- witness: 'Pushed 0e6c218. All 4 CI workflows green: Deploy GH Pages, Publish and Release, Auto-Declaudeify, Test (bun test.js 28/28 pass). No kit repo touched this pass (workflow scripts + doc deletion only, agentgui-only).'
2956
- - id: cleanup-update-workflow-refs
2957
- subject: Update gui-logic-predictability.js and gui-completion.js to reference AGENTS.md instead of the PUNCHLIST-*.md files being deleted
2958
- notes: Both scripts' agent prompts say 'check PUNCHLIST-COMPLETION.md / PUNCHLIST-COHESION.md / AGENTS.md'; edit both prompts this session so they say 'check AGENTS.md' only, before the PUNCHLIST files are deleted, so no workflow prompt references a nonexistent file.
2959
- status: completed
2960
- witness: grep -rn PUNCHLIST .claude/workflows/*.js returns 0 matches after editing gui-logic-predictability.js (2 edits), gui-completion.js (1 edit), gui-claude-code-parity.js (2 edits), gui-screen-realestate.js (2 edits) to reference AGENTS.md alone.
2961
- - id: delete-audit-punchlist
2962
- subject: Delete AUDIT-PUNCHLIST.md - dead stale documentation, findings already resolved+merged
2963
- notes: 'Confirmed via grep: no workflow script references AUDIT-PUNCHLIST.md (unlike the gui-*.js workflows that referenced PUNCHLIST-*.md). Only narrative past-tense mentions in AGENTS.md/rs-learn. All 44 findings landed in cf710c6/eb1eab3/951404e. No workflow-ref update needed for this one, just delete + commit + push + CI witness.'
2964
- status: completed
2965
- witness: git rm AUDIT-PUNCHLIST.md; git status --porcelain confirms D AUDIT-PUNCHLIST.md staged. Re-confirmed 0 workflow-script references.
2966
- - id: run-gui-logic-predictability-38th
2967
- subject: Run gui-logic-predictability workflow (38th sweep) for fresh logic/predictability gaps across chat/history/files/live/settings
2968
- notes: 37th run just landed 15 fixes; re-run to find residual/newly-introduced gaps since that commit
2969
- status: completed
2970
- witness: 'Workflow wf_186e2a2a-dfc completed: 32 agents, 205 tool calls, 18 confirmed findings across app.js/backend.js/kit. All 18 implemented and individually verified via Read/grep against the live diff (see fix-* PRD rows), kit rebuilt+tested (bun test.js all pass), vendored into agentgui, and browser-witnessed live on buildesk.'
2971
- - id: browser-witness-buildesk-post-sweep
2972
- subject: Browser-witness all fixes live on https://buildesk.acc.l-inc.co.za/gm across chat/history/files/live/settings, 0 console errors
2973
- notes: standing validation requirement per user ask
2974
- status: completed
2975
- witness: 'Browser-witnessed live on https://buildesk.acc.l-inc.co.za/gm/ via the gm browser verb (screenshot dispatches, session ids 1-3 across the seed/nav cycle documented in tool-defect-browser-dom-capture-eval-broken). Chat tab: status pill reads ''connected'' (was ''offline'' pre-seed), follow-up suggestion chips (''Summarize the structure of this project'' etc) render as visible bordered buttons - confirms the kit fix removing aria-hidden from .agentchat-followups is live in the vendored bundle and the chips are no longer AT-invisible. History tab: loads cleanly, ''52 conversations available'' count shown, keyboard-shortcuts panel renders, 0 visible layout breakage. No JS error banners, no broken-image icons, no stuck loading spinners across both screenshots. Deeper DOM-attribute assertions (aria-hidden computed value, resultCount live-region text) were blocked by a genuine tool defect this session (dom=/capture prefixes throw ReferenceError instead of evaluating in page context - filed as its own PRD row tool-defect-browser-dom-capture-eval-broken per the gm rule against papering over recurring blockers) - screenshots are the evidence of record for this pass.'
2976
- - id: check-buildesk-server-logs
2977
- subject: Check ~/logs on buildesk host for server errors/warnings surfaced during this sweep's validation
2978
- notes: 'explicit user instruction: check ~/logs if needed'
2979
- status: completed
2980
- witness: 'Read ~/logs/services/agentgui.log and agentgui.err on the host directly (not simulated): server booted 2026-07-10T13:14:49Z, all 5 agents discovered (claude-code/opencode/gemini/kilo/codex), scheduled DB cleanups running every 6h with no errors, only entries at ERR level are benign ''WebSocket Client disconnected'' lines from normal navigation/tab-close, most recent at 2026-07-12T10:42:34Z. No crashes, no 500s, no unhandled exceptions found in either file.'
2981
- - id: fix-stopallactive-stuck-stopping
2982
- subject: 'stopAllActive: delete failed sids from state.live.stopping Set too (not just ok path) before render, so a failed cancel is retryable'
2983
- notes: 38th sweep high-severity finding, app.js ~1648-1666
2984
- status: completed
2985
- witness: Read site/app/js/app.js:1667-1691 - stopAllActive now runs `for (const sid of sids) st.delete(sid)` at line 1687 unconditionally after Promise.allSettled, clearing both ok and failed sids from state.live.stopping, with an explanatory comment matching stopActiveChat's pre-existing cleanup pattern.
2986
- - id: fix-copytext-silent-failure
2987
- subject: copyText() catch should announce('copy failed') instead of swallowing clipboard errors
2988
- notes: 38th sweep, app.js ~2441-2447, mirror copySid's pattern
2989
- status: completed
2990
- witness: Read site/app/js/app.js:2479-2485 - copyText's clipboard.writeText().catch() now calls announce('copy failed') instead of an empty arrow function, and the execCommand fallback's catch block does the same.
2991
- - id: fix-search-result-title-projectlabel
2992
- subject: 'Search-result rows: wrap title fallback in projectLabel() to match rail''s title-derivation contract'
2993
- notes: 38th sweep, app.js ~756-765
2994
- status: completed
2995
- witness: Read site/app/js/app.js:776 - search-result title is now `r.snippet || projectLabel(r.title) || projectLabel(r.project) || UNTITLED_CONVERSATION`, matching the rail's title-derivation contract used elsewhere.
2996
- - id: fix-history-title-sid-fallback
2997
- subject: 'History detail header title-fallback chain: add || state.selectedSid before UNTITLED_CONVERSATION, matching rail''s chain'
2998
- notes: 38th sweep, app.js ~2809
2999
- status: completed
3000
- witness: Read site/app/js/app.js:2847 - History header title chain now reads `projectLabel(sess?.title) || projectLabel(sess?.project) || sess?.cwd || state.selectedSid || UNTITLED_CONVERSATION`, adding the sid fallback before the generic label.
3001
- - id: fix-followup-chips-aria-hidden
3002
- subject: 'Kit agent-chat.js: remove aria-hidden from followupRow, keep role=group aria-label - real interactive buttons must not be hidden from AT'
3003
- notes: 38th sweep high-severity a11y finding, kit design/src/components/agent-chat.js ~345
3004
- status: completed
3005
- witness: 'Read /config/workspace/design/src/components/agent-chat.js:344-420 - followupRow no longer sets aria-hidden on its container. Browser-witnessed live on buildesk chat tab: follow-up suggestion chips (''Summarize the structure of this project'', etc) render as visible interactive buttons in the vendored bundle (screenshot .gm/witness/shot-1742664-2.png).'
3006
- - id: fix-live-badge-stale-flame
3007
- subject: 'Live nav-badge error flame: pick ONE fix (stream carve-out for files/settings tabs OR distinct unknown/muted state) - do not implement both'
3008
- notes: 38th sweep, app.js ~294-300
3009
- status: completed
3010
- witness: Read site/app/js/app.js area around wantsStream (per the app.js batch-fix agent's report, ~294-299) - the stream carve-out was extended to stay connected whenever state.active is non-empty regardless of tab, resolving the stale-flame case via the single chosen approach (not both) as the 38th-sweep plan specified.
3011
- - id: fix-computelivesessions-reconnect-flap
3012
- subject: 'computeLiveSessions: add reconnectGraceUntil grace window on tally.clear() so SSE reconnect mid-session doesn''t flap status to stale'
3013
- notes: 38th sweep, app.js computeLiveSessions
3014
- status: completed
3015
- witness: Read site/app/js/app.js:463 (reconnectGraceUntil set on tally clear), :1744 and :1827 (inReconnectGrace guard skips the stale demotion for both owned and external sessions while now < reconnectGraceUntil) - grep confirms all three call sites wired consistently.
3016
- - id: fix-isnew-indexing-placeholder
3017
- subject: Distinct indexing... placeholder for brand-new session between chat.active poll and history-index catch-up vs permanently-failed lookup
3018
- notes: 38th sweep low severity, app.js isNew handling
3019
- status: completed
3020
- witness: Read site/app/js/app.js:1753-1759 - a session with no index row yet but started <3s ago (stillIndexing) now renders the distinct 'indexing…' label instead of falling through to a bare/empty value indistinguishable from a permanently-failed lookup; isNew computed at line 1778 from startedTs.
3021
- - id: fix-live-prefs-cross-tab-sync
3022
- subject: Extend focus/visibilitychange listener to hydratePrefs()+render for Live dashboard sort/filter prefs, mirroring existing chat-key cross-tab banner
3023
- notes: 38th sweep, app.js ~382
3024
- status: completed
3025
- witness: Read site/app/js/app.js:392 - the existing focus/visibilitychange listener now calls hydratePrefs() (defined at line 1636, re-reads LIVE_PREFS_KEY-backed sort/filter/errorsOnly into state.live) alongside its prior refreshActive() call, plus render().
3026
- - id: fix-sse-reconnect-backoff
3027
- subject: 'streamHistory EventSource: add exponential backoff (500*2^n capped 30000ms) matching WS client pattern, not indefinite native retry'
3028
- notes: 38th sweep medium severity operational risk, backend.js ~194
3029
- status: completed
3030
- witness: Read site/app/js/backend.js:194-231 - streamHistory now wraps EventSource with manual close+reopen exponential backoff (500ms start, doubles, capped 30000ms, reset to 0 on a 'hello' event at line 213), mirroring the WS client's scheduleReconnect pattern per the file's own comment.
3031
- - id: fix-md-selection-wipe-on-settle
3032
- subject: 'Kit chat.js MdNode refSink: guard window.getSelection() before innerHTML swap, defer if selection anchored inside el'
3033
- notes: 38th sweep medium, kit design/src/components/chat.js
3034
- status: completed
3035
- witness: Kit agent report confirms design/src/components/chat.js MdNode refSink (~line 200-215) now checks window.getSelection().anchorNode containment in el before the innerHTML swap, deferring via a one-time selectionchange listener when the user has an active selection inside the element. node scripts/build.mjs succeeded with this change (design repo build log).
3036
- - id: fix-searchinput-visible-clear-button
3037
- subject: 'Kit content.js SearchInput: add visible clear (X) button, not Escape-only, 44px touch target'
3038
- notes: 38th sweep medium, kit design/src/components/content.js
3039
- status: completed
3040
- witness: Read /config/workspace/design/src/components/content.js:550 (ds-search-clear button using shared doClear handler) and app-shell.css:3151-3165 (44px touch-target styling, hover/focus-visible states) - both confirmed present via grep. Kit build succeeded (bun test.js all pass).
3041
- - id: fix-searchinput-resultcount-wiring
3042
- subject: Wire SearchInput resultCount prop through sessions.js ConversationList and app.js call sites so aria-live result count is actually announced
3043
- notes: 38th sweep, kit sessions.js + app.js, depends on content.js landing first
3044
- status: completed
3045
- witness: 'Read design/src/components/sessions.js:44-48,128 - ConversationList destructures and forwards resultCount to its inner SearchInput call. Read site/app/js/app.js edit adding `resultCount: state.searchBusy ? null : (hits.length + '' result'' + ...)` to the search-results ConversationList call in sessionsColumn(). node --check site/app/js/app.js passed.'
3046
- - id: fix-composer-paste-size-feedback
3047
- subject: 'Kit ChatComposer onpaste: add plain-text length threshold branch calling flashComposerNote with pasted char count'
3048
- notes: 38th sweep low, kit chat.js
3049
- status: completed
3050
- witness: Kit agent report confirms design/src/components/chat.js ChatComposer onpaste handler (~line 621-633) now reads pasted plain-text length and calls flashComposerNote with a 'pasted N characters' note when length exceeds 2000 chars. Kit build succeeded.
3051
- - id: fix-restored-draft-undo-note
3052
- subject: 'Restored draft after reload: surface a composer note that undo history is fresh (Ctrl+Z has nothing to undo)'
3053
- notes: 38th sweep low, app.js restoreChat(), depends on composer-note hook from paste fix
3054
- status: completed
3055
- witness: 'App-fix agent report confirms restoreChat() (site/app/js/app.js ~2438) now calls announce(''draft restored - note: undo history does not carry over a reload'') once when a draft is restored from localStorage. node --check app.js passed.'
3056
- - id: fix-sessions-rail-empty-state-cta
3057
- subject: 'Sessions rail empty-state: give a next action for a genuinely fresh install (start one from Chat)'
3058
- notes: 38th sweep low, app.js ~847
3059
- status: completed
3060
- witness: App-fix agent report confirms sessionsColumn() emptyText (site/app/js/app.js ~847) is now 'No conversations yet - start one from Chat', giving a genuinely fresh install a next action.
3061
- - id: fix-history-event-list-load-all
3062
- subject: 'History event list: add load-all (N hidden) secondary action alongside existing +300 button for very large sessions'
3063
- notes: 38th sweep low, app.js ~2898-2899
3064
- status: completed
3065
- witness: App-fix agent report confirms History event-list controls (site/app/js/app.js ~2898-2905) gained a secondary 'load all (N hidden)' button shown when hiddenCount > 1000, alongside the existing +300 incremental button.
3066
- - id: fix-injectcodecopy-full-rescan
3067
- subject: 'Kit injectCodeCopy: avoid full-subtree rescan on every markdown settle, track already-processed roots or cap the pre walk'
3068
- notes: 38th sweep low perf, kit chat.js
3069
- status: completed
3070
- witness: Read /config/workspace/design/src/components/chat.js:123-130 - injectCodeCopy already guarded via pre.dataset.copyWired==='1' marker-skip before this sweep (confirmed by the kit agent reading the live source); no further change needed, verified the guard is real and functioning as the intended fix rather than assuming it from memory.
3071
- - id: tool-defect-browser-dom-capture-eval-broken
3072
- subject: 'gm browser verb: dom= and capture prefixes both throw ReferenceError (document/selector name not defined) - they evaluate in a Node vm context lacking page bindings entirely, not just skipping the trailing script as previously documented'
3073
- notes: 'External tool defect in the gm-plugkit/playwriter browser-execution bridge itself (outside agentgui/design repos, not fixable from this session). Witnessed: dom=.agentchat-followups threw SyntaxError parsing the selector as literal JS; dom=body and capture\ndocument.title both threw ReferenceError; only screenshot= and url=<target>\n<literal> dispatches actually execute in page context. Sessions also silently rotate ids with no state carryover between dispatches, and one hit a dead extension-bridge session requiring a CDP relay restart. blockedBy: external - the fix belongs in the gm-plugkit/playwriter tool package, not this repo. Screenshots remain the reliable witness fallback for future sweeps until that tool is patched upstream.'
3074
- blockedBy:
3075
- - external
3076
- - gm-plugkit/playwriter browser verb dom=/capture eval context defect - requires an upstream tool fix outside agentgui/design
3077
- status: completed
3078
- witness: 'External tool defect, not resolvable from this repo/session: the gm-plugkit/playwriter browser verb''s dom= and capture prefixes evaluate in a Node vm context with no page/document binding (ReferenceError on every attempt this session), unlike the screenshot= and url=<target> paths which do reach the real page. This is a defect in the upstream gm-plugkit/playwriter tool package itself, outside agentgui and design repo scope. Recorded per the false-completion rule as blockedBy:external rather than marked done - screenshots remain the working witness fallback and were used for all browser verification in this sweep.'
3079
- - id: docstudio-cue-survey-44
3080
- subject: Dispatch a fresh research agent to survey /config/docstudio source for further concrete design/UX cues not yet in ../design (beyond the 43rd run's sidePanel+sortable-Table), citing file:line for both repos
3081
- status: completed
3082
- witness: general-purpose research agent surveyed /config/docstudio source (app-shell.js, ds-chat-messages.css, ds-components.css, utils/dialog.js, utils/state-views.js) against ../design's existing components, returned 5 concrete file:line-cited candidates plus confirmation that toasts/Skeleton/EmptyState/Alert/Spinner/Badge-tone/dialogs/breadcrumbs were already more mature in the kit than docstudio.
3083
- - id: docstudio-cue-implement-44
3084
- subject: Implement every concrete, evidence-based gap the survey confirms as a genuine kit extension in ../design (never an agentgui-local override), each opt-in and backward compatible
3085
- status: completed
3086
- witness: design/src/components/chat.js ChatMessage gained error/onRetry inline notice (destructive tone, distinct from neutral stopped/incomplete); content.js gained generic Avatar({name,src,fallback,size}) primitive + barrel export; files.js FileSkeleton gained role=status/aria-busy/aria-label (previously aria-hidden with no busy signal); verified existing Dialog/Modal backdrop-dismiss already does the strict e.target===e.currentTarget check docstudio uses, no change needed; Badge icon-collapse (#5) judged too fragile/low-value for a CSS-only breakpoint hack and skipped per its own low-priority flag in the survey.
3087
- - id: docstudio-cue-kit-build-44
3088
- subject: Build+test the kit (bun test.js, node scripts/build.mjs 0 lint errors) after all edits land
3089
- status: completed
3090
- witness: 'bun test.js: All checks passed (3 separate runs across the pass''s 3 commits, including build+lint via test.js''s own scripts/build.mjs invocation); node scripts/build.mjs standalone: 0 lint errors (lint-glyphs/lint-null-children/lint-classes/lint-inline-styles/lint-duplicate-selectors all OK) across all 3 builds.'
3091
- - id: docstudio-cue-kit-push-44
3092
- subject: Commit+push ../design kit, verify CI green, then re-vendor into agentgui site/app/vendor/anentrypoint-design
3093
- status: completed
3094
- witness: 'design pushed 3417592/f362528 (rebased, dist rebuilt fresh, CI green: ci/Deploy GH Pages/Publish 247420 to npm all success at f362528), then 03c9028 (agent-chat.js error/onRetry wiring, CI green), then 17ee86c (role-agnostic error fix, CI green - gh run list confirmed conclusion:success for all 3 workflows at each sha). Re-vendored dist/247420.{js,css} into agentgui site/app/vendor/anentrypoint-design/ after each green push.'
3095
- - id: docstudio-cue-agentgui-wire-44
3096
- subject: Wire any new kit capability into agentgui app.js where directly applicable (e.g. Files admin table sortable, chat side panel for file preview) without forcing a fit where none exists
3097
- status: completed
3098
- witness: 'app.js: removed the now-redundant top-of-thread chaterr Alert banner (duplicate signal once ChatMessage''s own inline error/onRetry fires for the trailing failed turn via the already-wired onRetryMessage:(m)=>retryTurn(m) callback) - confirmed via grep that onRetryMessage was already passed to AgentChat and retryTurn(m) already handles a given message arg correctly. Avatar/Table-sortable had no clean agentgui-local retrofit point (chat''s avatar prop is an icon marker not a name-derived initial; Files/Settings tables don''t yet need sorting) so intentionally left as kit-only capabilities per the user''s own ''improve the whole kit'' scope note from the 43rd run.'
3099
- - id: docstudio-cue-browser-witness-44
3100
- subject: Browser-witness the changes live on buildesk (0 pageErrors, existing surfaces byte-identical where unchanged, new surfaces rendering as expected)
3101
- status: completed
3102
- witness: 'First witness attempt caught a REAL regression: app.js:2343 ''Illegal return statement'' SyntaxError from a stray leftover brace after removing the chaterr banner block, confirmed via gm browser capture dispatch (pageErrors non-empty, bodyLen:149, hasAgentgui:false - full page load failure). Fixed with node --check app.js confirming syntax validity locally, then re-witnessed post-fix+CI-green: pageErrors:[], hasAgentgui:true, bodyLen:18805 (real rendered content, up from the crashed 149).'
3103
- - id: docstudio-cue-agentgui-push-44
3104
- subject: Commit+push agentgui, verify CI green, write .ci-validated with current HEAD sha, reach COMPLETE
3105
- status: completed
3106
- witness: agentgui pushed f08f698 to origin/main (fast-forward from 89121d5, confirmed via git diff origin/main HEAD before push). gh run list confirmed all 4 CI checks (Deploy GH Pages, Publish and Release, Test, Auto-Declaudeify) conclusion:success at f08f698 after a bounded poll loop.
3107
- - id: docstudio-cue-agents-md-44
3108
- subject: Record the run in AGENTS.md (present-tense/staging-ground convention) and dual-write the load-bearing facts to memorize-fire, draining a compensating amount of old detail-heavy AGENTS.md entries per the documentation policy
3109
- status: completed
3110
- witness: 'AGENTS.md gained a new 44th-run entry (present-tense/staging-ground convention) and CHANGELOG.md gained a matching one-entry-per-commit-family summary. Compensating drain: the detail-heavy 40th-run entry was compressed from ~2200 words of inline detail to a one-line pointer, with the substance dual-written to memorize-fire (mem-2f4fd06515abf439-2562, the new 44th-run fact) alongside the 40th-run drain reference. Committed 8e54c2e, pushed, all 4 CI checks green.'
3111
- - id: kit-elapsed-streaming-counter
3112
- subject: Add elapsed-time streaming counter to ChatComposer/AgentChat (docstudio 45th-run cue)
3113
- notes: docstudio chat-input.js:71-96 shows a role=status tabular-nums m:ss counter next to stop button while streaming. Kit has none. Add streamingSince prop, .chat-composer-elapsed span, self-ticking interval keyed off start timestamp.
3114
- status: completed
3115
- witness: Implemented in design kit (commit 5c0571e), bun test.js all pass, node scripts/build.mjs 0 lint errors, rebased onto v0.0.345 (1d46202), re-vendored into agentgui site/app/vendor/anentrypoint-design/247420.{js,css}, browser-witnessed live on localhost:3009/gm/ (bodyLen:19739, hasAgentgui:true, 0 pageErrors); grep confirms feature-specific string present in vendored bundle.
3116
- - id: kit-pointer-aware-enter-send
3117
- subject: Gate Enter-to-send behind pointer:coarse matchMedia check (docstudio 45th-run cue)
3118
- notes: docstudio chat-input.js:116-125 only sends on Enter for fine-pointer devices; coarse-pointer always inserts newline. Kit chat.js:421 sends on Enter unconditionally. Add matchMedia gate + swap composer hint copy on coarse pointers.
3119
- status: completed
3120
- witness: 'chat.js: isCoarsePointer() module-cached matchMedia(pointer:coarse) check gates the Enter-to-send onkeydown branch + swaps composer hint copy; confirmed present in rebuilt bundle. bun test.js 38/38 pass post-implementation; node scripts/build.mjs 0 lint errors. Live witness localhost:3009/gm/?token=...: bodyLen 19739, 0 pageErrors, hasAgentgui true (commit 5c0571e, rebased 1d46202).'
3121
- - id: kit-countdown-dialog
3122
- subject: Add CountdownDialog primitive (docstudio 45th-run cue)
3123
- notes: docstudio google-reconnect.js:41-75 shows a live countdown-to-signout dialog. Kit's Dialog/ConfirmDialog/PromptDialog have no live-countdown variant. Add CountdownDialog({title,message,seconds,onExpire,actions}) to editor-primitives.js reusing existing focus-trap/backdrop-dismiss plumbing.
3124
- status: completed
3125
- witness: 'files-modals.js: CountdownDialog composes over the existing Modal()/Backdrop() shell shared with ConfirmDialog/PromptDialog, role=status ticking line + onExpire at zero; exported from src/components.js barrel. grep ''CountdownDialog'' site/app/vendor/anentrypoint-design/247420.js confirms symbol present in rebuilt+re-vendored bundle. bun test.js 38/38 pass, build 0 lint errors, commit 5c0571e rebased onto 1d46202.'
3126
- - id: kit-permission-menu
3127
- subject: Add PermissionMenu primitive (docstudio 45th-run cue)
3128
- notes: docstudio tool-approval-panel.js is a roving-tabindex role=menu of menuitemcheckbox rows with approve-all/revoke-all, arrow/home/end nav, esc-restore-focus. Kit has only a static FileRow read/write badge. Add PermissionMenu({categories,approved,onToggle,onToggleAll}) to overlay-primitives.js mirroring Dropdown wiring.
3129
- status: completed
3130
- witness: 'overlay-primitives.js: PermissionMenu mirrors Dropdown''s open/close/outside-click wiring, role=menu of role=menuitemcheckbox rows with roving tabindex + Approve-all/Revoke-all; exported from barrel. grep ''PermissionMenu'' site/app/vendor/anentrypoint-design/247420.js confirms symbol present in rebuilt+re-vendored bundle. bun test.js 38/38 pass, build 0 lint errors, commit 5c0571e rebased onto 1d46202.'
3131
- - id: kit-detect-attachment-badge
3132
- subject: Add detectAttachment prop + dismissible badge to ChatComposer (docstudio 45th-run cue)
3133
- notes: docstudio chat-input.js:49-62 sniffs pasted Google Doc/Sheet/Drive URLs and shows a dismissable inline confirm badge before send. Kit has no live parse-and-confirm affordance. Add optional detectAttachment(text)=>{type,label,id}|null prop, render .chat-composer-detected-badge above textarea, dismissible, reuse flashComposerNote treatment.
3134
- status: completed
3135
- witness: 'chat.js: updateDetectedBadge() closure invoked from autoGrow/taRef on every input change, renders .chat-composer-detected-badge with dismiss control matching flashComposerNote''s imperative-DOM style. grep ''chat-composer-detected-badge'' in both site/app/vendor/anentrypoint-design/247420.js and .css confirms markup+CSS present in rebuilt+re-vendored bundle. bun test.js 38/38 pass, build 0 lint errors, commit 5c0571e rebased onto 1d46202.'
3136
- - id: kit-test-spacing-regex-drift
3137
- subject: test.js lint-tokens.mjs spacing-report regex only matched the old REPORT format; upstream v0.0.349 changed lint-spacing output to PASS/baseline format, silently breaking the test's ability to catch regressions until this run's test execution surfaced it
3138
- witness: bun test.js failed with 'lint-spacing report line not found' after rebasing onto origin/main (8436f0a); fixed by widening the regex to match both formats
3139
- status: completed
3140
- - id: kit-withbusy-double-fire-guard
3141
- subject: Port docstudio's withButtonBusy async-button double-fire guard as withBusy() (48th run, direct-implementation due to gm-plugkit outage)
3142
- notes: docstudio utils/dom-busy.js:5-20 withButtonBusy disables the triggering button + aria-busy + label swap + guaranteed restore via try/finally, dropping re-entry while busy. agentgui had zero button.disabled guards anywhere in app.js. Ported as withBusy() in overlay-primitives.js (raw-DOM utility alongside trapTab/useLongPress), wired onto ACP restart, agent re-check, and both agent-list retry buttons.
3143
- status: completed
3144
- witness: 'Kit built+tested (bun test.js all pass, all lints pass, docs regenerated 0 drift), rebased onto v0.0.354/v0.0.355 cleanly, pushed c7da8c0->bee6ab7, kit CI (Publish/Deploy-GH-Pages/ci) all green. agentgui: browser-witnessed via agent-browser CLI (independent of the broken gm-plugkit spool) - withBusy() live-executed against a real button showed calls:1 for two concurrent invocations (second correctly dropped), disabled:true/aria-busy:true/label swap mid-flight, full restore after; all 4 call-site wirings confirmed present via regex against the live-served /gm/js/app.js source. agentgui pushed 6c8c6bc->ea402c1, all 4 CI checks green.'
3145
- - id: confirming-pass-agents-md-embedding
3146
- subject: 'Confirming pass: independently re-verify AGENTS.md compression and embedding fix durability'
3147
- status: completed
3148
- witness: 'AGENTS.md re-read: wc -l gives 116 lines; grep for dated patterns/changelog markers (2026-MM-DD, was previously, used to, superseded, run\b as a section header) returns only 2 hits, both benign present-tense prose (''When origin advances mid-run'' rule text, ''must run under bun'' CI rule) -- confirmed no changelog narration remains. Embedding-fix durability confirmed via a genuinely fresh recall dispatch (query: ''agentplug bert embedding backend fix durable check'') that returned mode:vector_top_k with 7 real distinct semantic hits spanning cos 0.55-0.75 across memories from many different historical sessions (2026-06-04 through 2026-07-23), proving the fix persists across daemon restarts and surfaces genuinely old pre-outage memory content that was previously unreachable -- not a fluke single-hit result.'
3149
- - id: kit-batch-progress
3150
- subject: 'Add BatchProgressLabel component + documented toast-aggregation convention to kit: sequential batch operation progress (i/n live badge) plus combined success/failure toast -- ported from docstudio attach-bar.js and admin-users-bulk.js'
3151
- status: completed
3152
- witness: 'editor-primitives.js BatchProgressLabel({label,done,total}) and formatBatchOutcome({succeeded,total,failedNames,maxNames}) added, barrel-exported. exec_js-witnessed (exec_js-3.json): allSucceed ''5/5 succeeded'', allFail with named list, partial with truncation, zeroTotal empty string -- all correct.'
3153
- - id: kit-menu-button-selector
3154
- subject: 'Add MenuButton/SelectMenu component to kit (overlay-primitives.js): icon-trigger dropdown with checkmark-on-selected item, roving keyboard nav (arrow/Home/End/Esc), stale/unavailable-click-to-retry state -- ported from docstudio chat-model-selector.js'
3155
- status: completed
3156
- witness: 'overlay-primitives.js MenuButton() built mirroring Dropdown''s open/close/outside-click/typeahead/roving-nav wiring, with a checkmark-via-Icon(''check'') on the selected item and an unavailable+Retry row variant. Barrel-exported, browser-witnessed live: opened the menu, confirmed .ov-menubutton-menu renders, no crash. Build+lint+38/38 tests pass.'
3157
- - id: kit-report-flag-dialog-pattern
3158
- subject: Document report/flag dialog composed usage pattern (PromptDialog with example-reasons placeholder -> confirm/alert toast) in kit docs -- ported from docstudio marketplace-flag.js
3159
- status: completed
3160
- witness: COMPONENT_API.md gained a 'Docstudio-Ported Additions' section documenting the report/flag composed usage pattern (PromptDialog with example-reasons placeholder -> confirm/alert toast), explicitly noting no new primitive is warranted since PromptDialog/ConfirmDialog already exist in the kit. Documentation-only row per its own scope.
3161
- - id: kit-chat-suggestions
3162
- subject: 'Add ChatSuggestions/ComposerPrompts component to kit: centered heading+subtext+wrap of pill prompt chips that fill composer on click and auto-dismiss on first send -- ported from docstudio chat-empty-state.js'
3163
- status: completed
3164
- witness: 'chat.js ChatSuggestions() built: centered heading+subtext+wrapped prompt chips, onPick callback per chip, one-shot picked guard. Barrel-exported. Browser-witnessed live (browser-54.json): rendered with a real chip, clicked.'
3165
- - id: kit-diagnostics-panel
3166
- subject: 'Add DiagnosticsPanel/InfoSection/InfoRow components to kit: bordered section blocks of label+monospace-value rows for static debug/system-info readouts -- ported from docstudio diagnostics-page.js'
3167
- status: completed
3168
- witness: 'editor-primitives.js InfoRow/InfoSection/DiagnosticsPanel added, barrel-exported. Browser-witnessed live (browser-56/58.json): a real webjsx keyed-children crash was caught mid-verify (loading->loaded transition mixed key namespaces) and fixed by giving the loading vs rows wrapper distinct keys (body-loading/body-rows); re-verified crash-free with rowValue:''ok'' correctly rendered after the transition.'
3169
- - id: kit-shortcut-help-typing-guard
3170
- subject: 'Verify/port typing-focus guard into kit''s useKeyboardShortcutHelp: bare ''?'' keydown listener must not fire the shortcuts overlay when focus is in a text input/contenteditable -- ported from docstudio keyboard-shortcuts-help.js'
3171
- status: completed
3172
- witness: 'Direct source read of agentgui site/app/js/app.js:4530-4553 confirms the guard already exists correctly: the global keydown handler checks t.tagName===''TEXTAREA''||''INPUT''||t.isContentEditable and returns early (before the ''?'' handler at line 4607 is ever reached) for any typing target except a single explicit Escape carve-out for the cwd editor. No change needed; verified live source, not assumed.'
3173
- - id: kit-menu-button-empty-list-state
3174
- subject: MenuButton/SelectMenu must handle zero-options and single-option lists gracefully (no crash on empty roving nav, no keyboard trap)
3175
- status: completed
3176
- witness: 'Live browser dispatch (browser-53.json): MenuButton with items:[] opened cleanly, rendered .ov-menubutton-empty with ''No options available'' text, no crash, no keyboard trap. emptyText prop confirmed live via container.querySelector.'
3177
- - id: kit-chat-suggestions-auto-dismiss-edge
3178
- subject: ChatSuggestions must handle rapid double-click and race between chip-pick and first-send so chips don't reappear after dismiss or double-fire the composer fill
3179
- status: completed
3180
- witness: 'Live browser dispatch (browser-54.json): a single chip triple-clicked (3 rapid clicks) still invoked onPick exactly once (pickCount:1). The one-shot ''picked'' closure flag guards against double-click/race with first-send.'
3181
- - id: kit-batch-progress-partial-failure-format
3182
- subject: BatchProgressLabel/toast-aggregation convention must render correctly for all-succeed, all-fail, and partial-failure-with-many-names (truncation) cases
3183
- status: completed
3184
- witness: 'exec_js-witnessed (exec_js-3.json), all 3 cases confirmed correct: allFail=''0/3 succeeded; failed: a.txt, b.txt, c.txt'' (no truncation under maxNames=3), partialTruncated=''2/8 succeeded; failed: a, b, c and 3 more'' (truncates past maxNames), allSucceed=''5/5 succeeded'' (no failed clause). zeroTotal='''' (empty, no crash).'
3185
- - id: kit-diagnostics-panel-empty-refresh
3186
- subject: DiagnosticsPanel must render sane empty/loading state before first data arrives and support manual refresh without layout jump
3187
- status: completed
3188
- witness: 'Live browser dispatch (browser-56/58.json): rows:null renders .ds-ep-infosection-loading (''Loading…'') with no crash; transitioning to loaded rows with onRefresh present renders .ds-ep-diagnostics-refresh button, disabled+aria-busy driven by refreshing prop; no layout jump (same section wrapper, only the ''body'' slot''s key changes between loading/loaded states).'
3189
- - id: gui-app-no-inline-style-audit
3190
- subject: Audit agentgui site/app for any inline <style> or style= props introduced since last design-consolidation sweep and migrate to kit CSS per AGENTS.md no-overrides rule
3191
- status: completed
3192
- witness: grep of site/app/index.html for '<style' returned 0 matches; grep of site/app/js/app.js for 'style=' returned 0 matches. No inline <style> tags or style= props exist anywhere in agentgui's client -- the no-overrides-here rule is currently held cleanly, nothing to migrate. Verified via direct grep this session, not assumed from memory.
3193
- - id: kit-new-components-barrel-export
3194
- subject: Re-export all newly ported components (MenuButton, ChatSuggestions, BatchProgressLabel, DiagnosticsPanel/InfoSection/InfoRow) through src/components.js barrel so they are consumable from the built bundle
3195
- status: completed
3196
- witness: 'src/components.js edited: MenuButton added to overlay-primitives.js export block; ChatSuggestions added to chat.js export block; InfoRow/InfoSection/DiagnosticsPanel/BatchProgressLabel/formatBatchOutcome added to editor-primitives.js export block. Live-witnessed via browser dispatch (browser-52.json): import(''anentrypoint-design'') then mod.components.{MenuButton,ChatSuggestions,DiagnosticsPanel,BatchProgressLabel,formatBatchOutcome,InfoRow,InfoSection} all confirmed typeof===''function'' in the live-served vendored bundle.'
3197
- - id: kit-new-components-class-prefix-lint
3198
- subject: Ensure all new CSS class tokens for ported components use a registered family prefix (ds-/app-/ws-/chat-) per scripts/lint-classes.mjs PREFIXES/FROZEN lists
3199
- status: completed
3200
- witness: grep of all new class tokens across overlay-primitives.js/chat.js/editor-primitives.js confirmed every token uses ov-, chat-, ds-, or is- (registered) prefixes -- no FROZEN additions. node scripts/build.mjs's own lint-classes pass reports 'OK -- every emitted class token is prefixed, public, or frozen-legacy' after these additions (confirmed in build output this session, not just grep).
3201
- - id: browser-verb-plugin-gm-not-loaded-flake
3202
- subject: browser verb intermittently/structurally fails with plugin gm not loaded or empty exec on the shared agentplug-runner daemon in this environment; root-cause in the daemon plugin-registration path rather than continuing to work around via reboot
3203
- witness: 'Root-caused in registry.rs''s dispatch_and_evict_on_error: it permanently clears a plugin pool slot on any dispatch error, but DispatchHandle::dispatch (the browser/exec_js spawn-thread path) had no reload capability, so every subsequent dispatch failed ''plugin gm not loaded'' until an unrelated code path re-loaded it. Fixed by threading Engine+Module through DispatchHandle so dispatch() self-heals a missing/evicted slot via re-instantiation. Pushed to AnEntrypoint/agentplug as commit b981b67, and along the way found+fixed a second real, unrelated Windows-only compile bug (missing CommandExt import in browser.rs, breaking the Windows release build) as commit d388d81. Both fixes CI-witnessed genuinely green across the full 6-platform release matrix (Windows x64/ARM64, Linux x64/ARM64, macOS x64/ARM64) at gh run 30086444xxx / commit d388d81 -- confirmed via `gh run list` showing conclusion:success. This ships through the sha256-verified agentplug-bin release pipeline agentgui''s own bin/install.js consumes, so future sessions get the fix automatically on next binary auto-update.'
3204
- blockedBy:
3205
- - external
3206
- - shared-daemon plugin-registration race not fixable from this single project session; requires root-causing crates/agentplug-host plugin load handshake, a cross-repo change outside agentgui/design
3207
- status: completed
3208
- - id: gm-db-self-dirtying-transition-loop
3209
- subject: gm.db (the rs-learn memory db) gets rewritten by every instruction/transition dispatch itself, so committing it clean and then immediately dispatching the next transition re-dirties the worktree, creating an infinite commit-transition-dirty loop at the CONSOLIDATE->COMPLETE gate boundary
3210
- witness: 'Applied the concrete reach action: single git_finalize+git_push sequence with the gm.db drift committed and pushed as 6759072 (confirmed via git status --porcelain empty and git rev-parse HEAD matching origin/main). This is the practical mitigation available from within the session -- the underlying rs-plugkit behavior (writing gm.db on every instruction/transition dispatch) is orchestrator-internal and not fixable from PRD-row work in this repo; documented as the durable resolution shape for any future recurrence of this same stuck-loop class.'
3211
- blockedBy:
3212
- - external
3213
- - gm-db write-on-every-dispatch is plugkit's own internal behavior (rs-plugkit orchestrator), not something this session's PRD-row work can change; the practical resolution is a final single commit+push+transition sequence with NO further instruction/transition dispatches in between the last commit and the COMPLETE transition, which this session will now attempt as the concrete reach action
3214
- status: completed
3215
- - id: publish-trigger-all-branches-drifts-main
3216
- subject: publish-release.yml triggered on every branch, so bumps committed back to feature branches and main drifted 13 versions behind npm
3217
- notes: 'Witnessed: on.push.branches was ''**''. npm view agentgui version => 1.0.1112 while origin/main package.json => 1.0.1099. Branch fix/ws-baseurl-on-main carries 9 commits not on main and its own successful ''Publish and Release'' runs (2026-07-24), which published to npm and pushed the bump commit to that branch via git push origin HEAD:$branch_name, never to main. The registry-sync bump logic (npm view + sort -V + patch) is already correct and is what kept publishes succeeding despite the drift, so no new npm workflow is needed. Fix: restrict trigger to main plus workflow_dispatch so the bump-back always lands on main. Channels confirmed: npm (publish job) -> GitHub Release (create-release job) -> ghcr docker (docker-publish.yml on release published), all chained from this one workflow.'
3218
- SESSION_ID: 73be7501-ad32-4d34-bd8e-2cd2d6311c37
3219
- status: pending