test(ai-chat): current-page coverage + getCurrentPage helper (verified live) #112
Closed
Ghost
wants to merge 0 commits from
feat/ai-chat-current-page-robustness into develop
pull from: feat/ai-chat-current-page-robustness
merge into: vvzvlad:develop
vvzvlad:main
vvzvlad:test/244-part-b
vvzvlad:fix/255-ws-redis-adapter-leak
vvzvlad:feat/251-intentional-clear
vvzvlad:fix/252-e2e-open-handles
vvzvlad:feat/184-autonomous-agent-runs
vvzvlad:feat/221-image-captions
vvzvlad:feat/git-sync
vvzvlad:refactor/193-tool-spec-registry
vvzvlad:fix/244-dataloss-bugs
vvzvlad:fix/embeddings-reindex-progress
vvzvlad:develop
vvzvlad:feature/offline-sync
vvzvlad:feat/229-catalog-yaml
vvzvlad:feat/243-blob-sandbox
vvzvlad:feat/228-inline-footnotes
vvzvlad:fix/qa-ui-bugs-216-218
vvzvlad:feature/agent-roles-catalog
vvzvlad:fix/share-alias-rename
vvzvlad:fix/ai-chat-empty-render
vvzvlad:feat/191-chat-doc-binding
vvzvlad:feat/201-temporary-notes
vvzvlad:feat/198-interrupt-agent
vvzvlad:feat/ai-chat-full-history
vvzvlad:feat/199-ai-generate-title
vvzvlad:feat/205-share-aliases
vvzvlad:batch/issues-189-187-170
vvzvlad:feat/170-mcp-test-button
vvzvlad:feat/189-context-badge
vvzvlad:feat/198-interrupt-agent-send-now
vvzvlad:fix/issues-190-159
vvzvlad:fix/ai-chat-new-chat-during-stream
vvzvlad:fix/ai-chat-stream-perf
vvzvlad:batch/issues-2026-06-25
vvzvlad:feat/ai-chat-persistent-history
vvzvlad:fix/ai-chat-copy-chat-wysiwyg
vvzvlad:fix/ai-stream-reset-resilience
vvzvlad:fix/ai-stream-undici-timeout
vvzvlad:fix/footnote-review-1227-followup
vvzvlad:fix/ai-chat-token-counter-realtime
vvzvlad:docs/manual-qa-test-plan
No Reviewers
Labels
Clear labels
bug
documentation
duplicate
enhancement
epic
feature
good first issue
help wanted
idea
invalid
needs-human
question
refactor
review/approved
review/changes-requested
review/needs
security
status/blocked
status/done
status/in-progress
status/ready
test
wontfix
Something isn't working
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Large multi-phase effort spanning many changes
New functionality request
Good for newcomers
Extra attention is needed
Idea / proposal for discussion
This doesn't seem right
эскалация: нужно решение человека
Further information is requested
Code cleanup / refactoring
в последнем ревью нет открытых blocking-находок
последнее ревью оставило открытые blocking-находки
head не ревьюился (head != reviewed_head)
Security / hardening issue
ждёт зависимость blocked_by
закрыто и проверено
в активной работе (мягкая заявка)
специфицировано, не заблокировано, ждёт исполнителя
Test coverage / test infrastructure
This will not be worked on
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: vvzvlad/gitmost#112
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/ai-chat-current-page-robustness"
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?
Фича: надёжная передача «текущей страницы» в AI-агента
Отчёт по скиллу архитектора.
1. Задача
Из
docs/backlog/ai-chat-current-page-fragile.md: агент не понимал «эта/текущая страница». Две независимые причины хрупкости: (№1) клиент по исходнику отдавалopenPage = nullиз-заuseParams()в pathless layout-роуте; (№2) контекст жил только в system-промпте и мог теряться на прокси-пути (CLIProxyAPI).2. Результат анализа (verify-before-build)
Обе механики уже реализованы и смержены в develop:
ada1dce7—AiChatWindowперешёл сuseParams()наuseMatch("/s/:spaceSlug/p/:pageSlug")(ai-chat-window.tsx:159-166), теперьopenPage{id,title}резолвится корректно независимо от позиции в дереве роутов.getCurrentPage(ai-chat-tools.service.ts:218-233), читающий открытую страницу из серверного контекста запроса — идентичность страницы больше не зависит от сохранности system-промпта прокси. Плюс контекст по-прежнему инжектится в system-промпт (ai-chat.prompt.ts:112-118).Не покрыто было только тестами — это и есть содержание PR.
3. Решение
resolveCurrentPageResult(openedPage)в новыйcurrent-page.util.ts(побайтно повторяет прежний inline-код инструментаgetCurrentPage), чтобы его можно было юнит-тестировать без динамически-импортируемого ESM Docmost-клиента; инструмент теперь делегирует ему.current-page.util.spec.ts— 7 кейсов (null/undefined/нет id/пустой id/полный/без title/пустой title).ai-chat.prompt.spec.ts— +8 кейсов на context-строкуopenedPage(title+pageId присутствуют; fallback «Untitled» для пустого/whitespace title; строки нет при отсутствии/пустом id; порядок — внутри safety-сэндвича, перед закрывающей копией SAFETY_FRAMEWORK).4. Найденные баги
Ревью-субагент: дрейфа поведения у извлечённого хелпера нет (символ-в-символ), тесты содержательны — APPROVE. Найдено одно постороннее: в рабочем дереве «протёк» несвязанный build-артефакт
packages/mcp/build/lib/docmost-schema.js(нода htmlEmbed) — исключён из коммита (git restore), в PR не вошёл.5. Тестирование — статистика
Юнит-тесты: 2 сьюта / 20 тестов зелёные (
jest current-page.util.spec.ts ai-chat.prompt.spec.ts);tsc --noEmitexit 0.Циклы ревью: 1 (APPROVE с первого прохода; 1 посторонний артефакт убран — не дефект кода).
Живая браузерная проверка: 1 цикл, автономный субагент, headless Chromium, реальный стенд + реальный провайдер (OpenRouter claude-sonnet-latest). Багов: 0.
/api/ai-chat/streamсодержитopenPage:{id:"019ee2dc-…", title:"Quarterly Report Template"}; на не-страничном роуте (/home) →openPage = null. ✓ Доказывает фикс хрупкости №1 вживую.Скрины:
/tmp/f2-page-open.png,f2-chat-sent.png,f2-offpage-sent.png,f2-agent-reply.png.🤖 Generated with Claude Code
The 'current page' feature (client useMatch openPage + server getCurrentPage tool + system-prompt injection) was already implemented & merged; this backfills its missing test coverage and removes the completed backlog doc. - extract pure resolveCurrentPageResult(openedPage) into current-page.util.ts (byte-identical to the prior inline getCurrentPage tool body) so it is unit-testable without the dynamically-imported ESM Docmost client; the tool now delegates to it. - current-page.util.spec.ts: 7 cases (null/undefined/no-id/empty-id/full/no-title). - ai-chat.prompt.spec.ts: +8 cases for the openedPage context line (title+pageId present, Untitled fallback for blank/whitespace title, no line when absent/blank id, and sandwich ordering before the trailing safety block). Verified live in-browser: client sends openPage{id,title} on a page and null off-page; the agent invokes getCurrentPage and answers with the real title+id. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Pull request closed