# 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** - `ListPacks` skips `hidden: true`; `LoadPackPrompt` still loads enabled hidden packs (`debug_explain.json` has `hidden: true`, `enabled: true`). - Slim debug skips prefs, skills, identity, RAG retrieve, tool hops, and memory/pref/persona writes; Exact still loads when `includeBase` is false. - Client `fromDebug` sends pack `debug_explain`, `includeBase: false`, `skipAppendUser`, empty skills; dump stays a system note. - Single `doParams` body; `shouldRememberSessionParam` remembers when the user asked **or** the value differs from Exact. - `userImpliesGenerate` has no noun-only fallback; `userIsChatNotFrame` strips generate on thanks/trivia; `willGen` no 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 `sendChat` is a no-op while `state.busy` is true (vision/critique hops are exempt; these are not). - `fromDebug` returns after `rememberLastPatch` / `interrupt` / `maybeVisionHop`. - Model `actions:["generate"]` still runs Generate unless `userIsChatNotFrame` matches. - `shouldHonorLookAt` still honors unsolicited `look_at` on 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 `memories` table plus embeddings, then filters in C# — `AssistentMemory.cs` line 750. ### Correctness & Bugs - Nested `sendChat` from `handleReplySideEffects` (Krea EN prep, empty-patch retry) hits the `state.busy` gate and returns without sending — `Assets/assistent.js` lines 8622–8624, 8104–8115, 8169–8181. - `/debug` side effects run before the Q&A early return — lines 8120–8160. - C# `TryParsePatch` returns the **first** fence; JS `extractPatch` keeps the **last** — `AssistentPatch.cs` line 97 vs `Assets/assistent.patch.js` line 88. - `ResolveEnabledSkills` ignores `skills: []` (`Count > 0`) so the user cannot disable all skills — `AssistentConfig.cs` line 1474. Slim debug is unaffected because it skips the skills layer. - `doInterruptNow` bumps `chatEpoch` without `clearInFlightUi`; `finishOk` then bails and leaves `state.busy` true — `Assets/assistent.js` lines 4629–4635, 8867–8868. - Failed `RunToolHop` (`follow == null`) `break`s the hop loop, dropping sibling tools (e.g. empty `memory_get` kills `search_civitai`) — `AssistentChatPipeline.cs` lines 237–239. - Overlay JSON writes never take `AssistentConfig._lock` (the field is unused) — `AssistentConfig.cs` line 18. - Wanted YAML is load–mutate–`WriteAllText` with no lock — `AssistentWanted.cs` lines 46–77. - Patch key lists diverge: JS has `persona_clone` / `persona`, neither list has `scheduler` (but `applyPatch` writes scheduler) — `AssistentPatch.cs` lines 12–25, `Assets/assistent.patch.js` lines 8–19, `Assets/assistent.js` line 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/`ApplyMemoryActions` can follow a weak fence while Generate uses a later one. - `includeBase` only gates `core.md`; Exact/live still flow on debug turns (intended). ### State Management - `fromDebug` can overwrite `state.lastPatch` and start a vision hop before the early return. - `skipAppendUser` persists an assistant explanation with no matching user turn in `state.history` — next chat turns see a dangling assistant message. ### Consistency - `write_prompt.md` always demands a JSON patch with `prompt`+`negative`; `core.md` output 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. - `shouldHonorLookAt` returns true whenever there is `look_at` and no generate trigger — contradicts 0.11.4 / pack “look only if asked”. - `wantsGen` trusts model `actions:["generate"]` unless `userIsChatNotFrame` (narrow). `synthesizePatchAfterEmptyFence` can invent `actions:["generate"]` when the reply has an empty `### JSON Patch` heading 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 ask` dump 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 `/pack` error string lag behind `Config/_base/ui.json`. ### Accessibility - Composer `#sa_input` has only a placeholder (no accessible name). - Persona/pack/model `