Reference in New Issue
Block a user
Delete Branch "batch/issues-2026-06-25"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Батч из заявленных issue, каждая — отдельным коммитом.
#151(реалтайм-счётчик токенов) уже был в develop (коммит0ebb1adc), поэтому здесь его нет.Closes #181. Closes #180. Closes #173. Closes #163. Closes #164. Closes #168.
Partially addresses #159 (5 из 10 находок; разбивка ниже).
Что сделано (по коммитам)
liveTurnTokensпокомпонентныйmax(authoritative, estimate)).collapseBlankLinesсхлопывает\n\n(сохраняя fenced-код), убранwhite-space: pre-wrapс markdown-<div>. Loose-списки → tight. 9 тестов.replaceImageбольше не дёргает курсор:mutateLiveContentUnlockedпереведён наapplyDocToFragment(structural diff #152). +2 регресс-теста (top-level + image в callout).model_config(роли) →::text::jsonb+ self-heal на чтении; вынесен общийjsonbBind(); интеграционные round-trip тесты (jsonb_typeof+ heal); fail-openwarnна битый allowlist; обновлён устаревший комментарий типа; упрощёнparseToolAllowlist.↩ a b c …, каждая скроллит к своей occurrence.computeFootnoteRefCounts+getFootnoteRefCount(кэш в numbering-плагине),scrollToReference(id, index?). Тесты на data-слой + структуру вью. (Вёрстку строки бэклинков стоит глянуть в браузере — jsdom не покрывает визуал.)instructions text), репо/DTO(@MaxLength(4000))/сервис/вью, проброс через тулсет (McpServerInstruction, только для подключённых серверов с ≥1 тулом и непустым текстом), блок<mcp_tooling>внутри safety-сэндвича, реордерtoolsFor→buildSystemPrompt, клиентская форма + i18n. Тесты по всем слоям (unit + integration). Делегировано + отревьюено (APPROVE).#159 (red-team) — 5 из 10 находок
Сделано (с тестами) — 8 из 10:
patch_node/delete_nodeотказываются работать при дублирующихсяattrs.id(абортят + ошибка модели).*.int-spec) теперь гоняется в CI (services: postgres(pgvector)+redis+ шагtest:int).openPageвалидируется на сервере (resolveOpenPageContext), title из БД, не из клиента (+7 тестов).resolveReadableSharePage(restricted-ancestor gate) +isSharingAllowed(+4 теста).insertByPositionбольше не материализует частичный список[node]из незагруженного (children===undefined) родителя — оставляет ветку незагруженной и лениво подтягивает ПОЛНЫЙ набор на разворот (+тесты на модель и редьюсер).mergeRootTreesтеперь реконсайлит к авторитетному входящему набору корней (дропает отсутствующие), сохраняя загруженные поддеревья (+4 теста).treeModel.reconcileChildren+ рефреш открытых загруженных веток на сокет-connectсfetchAllAncestorChildren({fresh:true})(+тесты на reconcile и выбор веток). Живой реконнект-раунд-трип не автоматизирован в браузере (симулировать разрыв непрактично) — рендер дерева + разворот прогнаны смоук-тестом без регрессий.Осталось 2 из 10 (низкий приоритет по модели угроз, с обоснованием):
FOR UPDATEчерезgetPageBreadCrumbs+updatePage(риск регрессии всего перемещения) ради крайне маловероятной гонки (двое одновременно тянут X→под-Y и Y→под-X). Скажи — сделаю отдельно.Admins can now give each EXTERNAL MCP server a free-text instruction ("how/ when to use this server's tools") that the agent receives in its SYSTEM PROMPT next to the tool descriptions — porting the built-in SERVER_INSTRUCTIONS idea to admin-configured servers. Trusted, admin-authored text (like a system prompt); NON-secret, so unlike headersEnc it IS returned in views/forms. - Migration: nullable `instructions text` on ai_mcp_servers (old rows = null = no guidance). Table type + repo insert/update (blank/whitespace -> null via blankToNull). DTO `@MaxLength(4000)`. Service threads it through McpServerView/toView. - mcp-clients: `McpServerInstruction { serverName, toolPrefix, instructions }` threaded through the toolset/cache/lease. Guidance is built ONLY for a server that actually connected AND contributed >=1 callable tool (the allowlist may filter all of them out) AND has non-blank text — so a guide never appears for tools the agent cannot call. Cached with the toolset, so an edit is picked up next turn via the existing CRUD cache invalidation. - System prompt: `buildMcpToolingBlock` renders an <mcp_tooling> block INSIDE the safety sandwich (after context, before the trailing SAFETY_FRAMEWORK) so it informs tool choice but cannot override the rules; each section is headed by the server's `prefix_*` namespace. Empty/blank -> block omitted. The caller (ai-chat.service) now builds the external toolset BEFORE the prompt and passes external.instructions; client-handle lifecycle (close-once) unchanged. - Client: instructions field in types + a Textarea (autosize, maxLength 4000) in the MCP-server form with a namespace-prefix hint; i18n (en/ru). Tests across every layer (prompt block placement + both SAFETY copies; view blank->null; buildEntry includes guidance only for connected+>=1-tool+non-blank; DTO MaxLength; repo + integration round-trip; service wiring). Delegated impl reviewed (APPROVE); applied the import-type follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>The client sends the "current page" as { id, title } in the request body and the server echoed BOTH verbatim into the system prompt context and the getCurrentPage tool. id and title are independently attacker/desync-controllable (two tabs, stale navigation), so openPage.id could point at page B while openPage.title said "Page A" — the model then reported "updated Page A" while it actually edited page B (CASL still allowed it; the user has access). Red-team finding #4. Resolve the open page ONCE against the DB via a new `resolveOpenPageContext`: workspace-scoped lookup + access check, returning the AUTHORITATIVE { id, title } (title from the DB row, never the client) or null (fail-closed) for a missing / foreign / inaccessible page. That validated value now feeds the system prompt, the getCurrentPage tool, AND the new-chat history origin (which previously did this validation inline, for the id only — now shared, and the title is fixed too). Tests: resolveOpenPageContext covers no-id, not-found, foreign-workspace, Forbidden, non-Forbidden-fault (fail-closed), the DB-title-wins-over-client case, and null-title coercion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>a670de7638todd64c2ea05Батч: ai-chat/footnotes/mcp/db + red-team (#163 #181 #164 #173 #168 #180 + #159 частично)to Батч: ai-chat/footnotes/mcp/db/tree + red-team (#163 #181 #164 #173 #168 #180 + #159 8/10)24264efa25tof80276d41a