Restructure UI with app-level tabs and chat history drawer; add dataset curation, HF import, Modelfile/QLoRA hooks, and link approved samples to the agent immediately via heard vector memory without waiting for fine-tuning. Co-authored-by: Cursor <cursoragent@cursor.com>
10 KiB
Project Review — 2026-08-22 (1)
Scope: Swarm Assistent 0.11.8 (client Assets/assistent.js, C# pipeline, packs, HTML/CSS). Includes a verification of the 0.11.8 ship (a5e96f7).
Prior Reviews Summary
Based on the last 3 review files analysed in Phase 0.
Still Open (carried forward)
None.
Resolved Since Last Review
None. (no prior docs/reviews/ files)
0.11.8 verification
Checked against the ship notes: session_exact, slim /debug ask, generate-only-for-frames.
Correct
ListPacksskipshidden: true;LoadPackPromptstill loads enabled hidden packs (debug_explain.jsonhashidden: true,enabled: true).- Slim debug skips prefs, skills, identity, RAG retrieve, tool hops, and memory/pref/persona writes; Exact still loads when
includeBaseis false. - Client
fromDebugsends packdebug_explain,includeBase: false,skipAppendUser, empty skills; dump stays a system note. - Single
doParamsbody;shouldRememberSessionParamremembers when the user asked or the value differs from Exact. userImpliesGeneratehas no noun-only fallback;userIsChatNotFramestrips generate on thanks/trivia;willGenno longer ORs the auto-generate checkbox.- Auto-critique / auto-vision HTML defaults remain unchecked (0.11.4 opt-in).
- Negative pass-through and variant-interrupt epoch guard still in place.
Not fully correct (filed below)
- Nested Krea-prep / empty-patch retry
sendChatis a no-op whilestate.busyis true (vision/critique hops are exempt; these are not). fromDebugreturns afterrememberLastPatch/interrupt/maybeVisionHop.- Model
actions:["generate"]still runs Generate unlessuserIsChatNotFramematches. shouldHonorLookAtstill honors unsolicitedlook_aton non-generate turns.
Phase 1: Code Quality
SOLID
Assets/assistent.js is a single IIFE (~9600 lines) owning chat, board, patches, inventory, personas, cards, and settings. C# is split into partial files on SwarmAssistentExtension, which is appropriate for a SwarmUI extension. No extra SOLID tasks beyond the concrete bugs below.
Performance
- Every RAG retrieve loads the full
memoriestable plus embeddings, then filters in C# —AssistentMemory.csline 750.
Correctness & Bugs
- Nested
sendChatfromhandleReplySideEffects(Krea EN prep, empty-patch retry) hits thestate.busygate and returns without sending —Assets/assistent.jslines 8622–8624, 8104–8115, 8169–8181. /debugside effects run before the Q&A early return — lines 8120–8160.- C#
TryParsePatchreturns the first fence; JSextractPatchkeeps the last —AssistentPatch.csline 97 vsAssets/assistent.patch.jsline 88. ResolveEnabledSkillsignoresskills: [](Count > 0) so the user cannot disable all skills —AssistentConfig.csline 1474. Slim debug is unaffected because it skips the skills layer.doInterruptNowbumpschatEpochwithoutclearInFlightUi;finishOkthen bails and leavesstate.busytrue —Assets/assistent.jslines 4629–4635, 8867–8868.- Failed
RunToolHop(follow == null)breaks the hop loop, dropping sibling tools (e.g. emptymemory_getkillssearch_civitai) —AssistentChatPipeline.cslines 237–239. - Overlay JSON writes never take
AssistentConfig._lock(the field is unused) —AssistentConfig.csline 18. - Wanted YAML is load–mutate–
WriteAllTextwith no lock —AssistentWanted.cslines 46–77. - Patch key lists diverge: JS has
persona_clone/persona, neither list hasscheduler(butapplyPatchwrites scheduler) —AssistentPatch.cslines 12–25,Assets/assistent.patch.jslines 8–19,Assets/assistent.jsline 4327.
Code Quality
No extra tasks. Duplicated help strings (JS fallback vs ui.json) are filed under UX.
Phase 2: Logical Consistency
Domain & Application Layer
No layered DDD. Pack/core contracts vs client behavior are the real domain rules.
Data Flow
- Server hops parse the first JSON fence; the UI applies the last. Hops/
ApplyMemoryActionscan follow a weak fence while Generate uses a later one. includeBaseonly gatescore.md; Exact/live still flow on debug turns (intended).
State Management
fromDebugcan overwritestate.lastPatchand start a vision hop before the early return.skipAppendUserpersists an assistant explanation with no matching user turn instate.history— next chat turns see a dangling assistant message.
Consistency
write_prompt.mdalways demands a JSON patch withprompt+negative;core.mdoutput contract shows a generate example as mandatory, while later saying “Pure Q&A: omit the JSON patch”. Client auto-apply will still write Swarm fields if the model emits a prompt patch on chat.shouldHonorLookAtreturns true whenever there islook_atand no generate trigger — contradicts 0.11.4 / pack “look only if asked”.wantsGentrusts modelactions:["generate"]unlessuserIsChatNotFrame(narrow).synthesizePatchAfterEmptyFencecan inventactions:["generate"]when the reply has an empty### JSON Patchheading even if the user did not ask for a frame.
Phase 3: UI/UX
Usability
- Loading spinner, Stop, empty chat/board states exist.
- Chat clear confirms; Clear Init+Mask in the board ⋯ menu does not.
/debug askdump as a system note (no second user bubble) is correct.
Visual & Consistency
No token/theme issues filed. Status and health use text plus color.
Interaction & Feedback
- Interrupt from the Stop button clears UI; interrupt from a model patch does not (see busy-stuck bug).
- README slash table and
/packerror string lag behindConfig/_base/ui.json.
Accessibility
- Composer
#sa_inputhas only a placeholder (no accessible name). - Persona/pack/model
<select>s usetitleonly. - Main subtabs are a
tablistwithoutrole="tab"/aria-selected(setViewtoggles CSS class only). .sa-board/.sa-slotsetoutline: nonewith no:focus-visiblereplacement; board istabindex="0".#sa_statusis notaria-live.
Tasks
Only actionable issues are listed here. Carried-forward items from prior reviews come first (marked with source), followed by net-new findings.
- 1. [Bug] Exempt
fromPromptEnRetryandfromEmptyPatchRetryfrom thestate.busygate (same as vision/critique). Nested Krea-prep and empty-patch retry currently return immediately; the “Готовлю промпт…” note is shown and Generate is skipped. —Assets/assistent.jsline 8623 (already resolved viaisContinuationTurn) - 2. [Bug] Move the
fromDebugearly return to the top ofhandleReplySideEffects(after extract). Today debug canrememberLastPatch,doInterruptNow, andmaybeVisionHopbefore the Q&A return. —Assets/assistent.jsline 8151 (already resolved: return immediately afterextractPatch) - 3. [Bug] Align C#
TryParsePatchwith JSextractPatch: prefer the last terminal/strong fence, not the first match. Server hops otherwise act on a weak fence while the UI applies a later one. —AssistentPatch.csline 97 - 4. [Logic]
shouldHonorLookAtmust notreturn truefor unsolicitedlook_aton ordinary/write turns. Honor only user/look, vision packs, or auto-critique/hop. —Assets/assistent.jsline 1184 - 5. [Bug] Do not start Generate from a model
actions:["generate"]or fromsynthesizePatchAfterEmptyFenceunless the user turn is a frame (userImpliesGenerate/ explicit/gen). Empty### JSON Patchon chat currently synthesizes generate. —Assets/assistent.jslines 915 and 8164 - 6. [Bug]
doInterruptNow(patchinterruptaction) must callclearInFlightUilike the Stop button. Epoch bump insidefinishOkcurrently leavesstate.busystuck. —Assets/assistent.jsline 4629 - 7. [Bug] Honor
clientSkillseven when empty:if (clientSkills is not null)(null = defaults,[]= none). Unchecking every skill currently reloadsdefaultOn. —AssistentConfig.csline 1474 - 8. [Bug] On
RunToolHopreturning null, skip that tool and try the nextNextToolHopinstead ofbreak. Emptymemory_getcurrently abortssearch_civitai/ inventory on the same patch. —AssistentChatPipeline.csline 237 - 9. [Logic] Make
write_prompt.mdandcore.mdmatch ordinary: fenced JSON only on frame turns; Q&A is prose only. The “mandatory JSON patch with prompt+negative” line fights auto-apply on chat. —Config/_base/packs/write_prompt.mdline 8 - 10. [Bug] Sync patch key lists: add
schedulerto JSPATCH_KEYSand C#PatchKeys; addpersona_clone/personato C#. A scheduler-only (or clone-only) fence is dropped. —Assets/assistent.patch.jsline 8 - 11. [Performance] Filter RAG
SELECTby persona chain (and/or FTS id list) instead of scanning every memory row + embedding on each chat. —AssistentMemory.csline 750 - 12. [Bug] Use
AssistentConfig._lockaround overlay read-modify-write (SaveSettings, control shelves) or remove the unused lock. Concurrent API calls can tear JSON. —AssistentConfig.csline 18 - 13. [Bug] Lock Wanted YAML load/merge/save (or write atomically). Concurrent enqueues can drop entries. —
AssistentWanted.csline 46 - 14. [Logic] For
skipAppendUser, persist a short history marker (/debug ask) with the assistant reply, or omit both. Orphan assistant turns pollute the next LLM context. —Assets/assistent.jsline 8775 - 15. [Accessibility] Name the composer (
aria-labelon#sa_input) and header selects; give main subtabsrole="tab"+aria-selectedinsetView. —Tabs/Text2Image/Assistent.htmlline 93 - 16. [Accessibility] Restore a
:focus-visiblering on.sa-boardand.sa-slot(they setoutline: none; board is keyboard-focusable). —Assets/assistent.cssline 95 - 17. [UX] Mark
#sa_statusasrole="status"/aria-live="polite"so busy/error text is announced. —Tabs/Text2Image/Assistent.htmlline 108 - 18. [UX] Confirm before Clear Init+Mask (chat clear already confirms). —
Assets/assistent.jsline 9425 - 19. [UX] Sync README slash table and
/packerror status withConfig/_base/ui.json(/new,/history,/persona *,ordinary|card|persona). —README.mdline 115