8000 test(clicks): journeys for regenerating, copying, exporting and choosing tools in a chat by adeelahmad · Pull Request #541 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

test(clicks): journeys for regenerating, copying, exporting and choosing tools in a chat - #541

Merged
adeelahmad merged 7 commits into
mainfrom
claude/project-thread-r960xc-c9-journeys
Oct 18, 2026
Merged

adeelahmad merged 7 commits into
mainfrom
claude/project-thread-r960xc-c9-journeys

Conversation

@adeelahmad
@adeelahmad adeelahmad commented Oct 18, 2026 •
Copy link
Copy Markdown
Owner

Description

The clicks survey (ci/clicks) now measures the chat features that have merged, on a computer and on a phone. Each
count is from full runs of ci/clicks/run.sh on this branch with main (6eefdff) merged in, and the Clicks workflow
runs them again on CI:

Journey What a person does Computer (clicks) Phone (taps, swipes)
chat-regenerate From Home: Chat, the conversation chat-ask started, Regenerate, then ‹ back to the first version 4 5, 0 (the menu button first)
chat-copy Continues: Copy on the answer (it's in the clipboard as Markdown; the journey reads it back) 1 1, 0
chat-export-pdf Continues: the header's download icon, then PDF 2 2, 0
chat-tools Continues: the Tools chip, switch off The server, Limit tool calls per answer (starts at 10), Done 4 4, 0

No keys or passkey touches in any of them. baseline.json and baseline-phone.json are regenerated from those runs,
so CI holds every journey to its count. They now also carry entity-merge and graph-merge: both were in
journeys.mjs but not in the baselines, so CI wasn't holding them to a number yet. Every journey that was already in
the baselines kept its count on both devices, and no page has a control under the Ask button.

Two web app fixes the journeys turned up, each small and in the chat components:

  1. Copying an answer took two clicks. The Copy button opened a menu, and picking the format was a second click.
    C3's goal is "Get anything out of a conversation in one click". A click on Copy now copies the answer as
    Markdown (citations as footnotes, as before). The arrow beside it, the same split button Regenerate has, holds
    Copy as Markdown, Copy text and Export as Markdown, PDF or JSON. docs/assistant.md says so.
  2. A quick second change in the Tools chip undid the first. In a conversation, each change was saved and then
    the conversation was read back, and the next change was built on what the page still held. So switching a group
    off and then turning the limit on before the first save came back sent the old tools (Auto) with the limit, and
    the group came back on. The first full survey run caught it: the chip ended at "Tools: Auto · 10 calls". The new
    useSaveTools hook (tools-picker.tsx) shows each change at once, saves the changes in the order they were made,
    and reads the conversation back after the last one. A new jest test holds the first save back, makes the second
    change, and checks that it keeps the first (it fails against the old code).

Other changes:

  • fake-model.mjs: the stand-in model answers the same question again in the same conversation (a regenerated
    answer) with "…answering, version 2.", so the journey can tell the versions apart. It keys on the question and
    the conversation before it, not the excerpts, which are marked afresh on each call. Every other call gets the same
    reply as before, and the other journeys' stand-in model answering match still holds.
  • fake-model.mjs also titles conversations. Since feat(chat): title conversations after their first answer #531 Lens asks the model for a title after a conversation's first
    answer, and the stand-in's one reply became every conversation's title in the list beside Chat. That made the first
    CI run here fail all four journeys: chat-ask waits for the reply's words, found them at once in that list (the
    conversation the welcome tour started), and ended before its own answer was saved, so the journeys after it found
    a conversation with a question and no answer. The stand-in now answers the title prompt with the first question's
    words, as a model would, and first-question and chat-ask wait for the reply inside the newest answer
    (answered() in journeys.mjs), not anywhere on the page.
  • The per-page survey counts a page's controls again for a few seconds when it finds none (counted() in
    survey.mjs): two full runs here recorded a settings page still loading as having no controls (Documents in one,
    Video in the other), which would have gone into the baseline as fact.
  • The new journeys come just before cloud-model, not after it. cloud-model has to stay last because it points
    Lens at a cloud model with a dummy key, and these need the stand-in model to answer. The baselines compare by id,
    so this order doesn't change any other journey.
  • chat-export-pdf follows whichever path the server takes. Where the server can make the PDF (Chromium, anytopdf
    or LibreOffice), the browser saves the download. Where it can't (409), the web app opens the print dialog, which
    is counted as one click on (outside the browser), as report-pdf does. In both runs here the server fetched
    anytopdf and made the PDF (200), so the browser downloaded it. CI's ubuntu-latest runner has Chrome on the PATH,
    so it makes the PDF there too.
  • docs/requirements.md: the regenerate row also names chat-regenerate ≤ 4 clicks.

Motivation and Context

Chat-gaps plan, C9 item 1 (journeys). The deep research journey waits for its web app (C8), which hasn't merged.

Types of changes

  • Bug fix (non-breaking change which fixes an issue): copying took two clicks; a quick second tool change lost the first
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests.
  • My change requires documentation updates, and I have updated docs/ accordingly.
  • Users need more than the title to understand it, so I wrote it under ## Unreleased in CHANGELOG.md. (n/a: the title and the commits say it)

Evidence

  • ci/clicks/run.sh --compare ci/clicks/baseline.json and ci/clicks/run.sh --device phone --compare ci/clicks/baseline-phone.json, full runs with main (6eefdff) merged in, after the title fix: 37 of 37 journeys ok on each, every count the same as in the baselines before, which are regenerated from these runs (the per-page control counts move with main: /settings/ai has the auto title switch, /settings/sensors two more controls).
  • NODE_ENV=test npx jest on the chat suites (tools picker, copy and export, chat, versions, composer, details, web citations): 51 passed. ESLint, Prettier and tsc --noEmit are clean on the web app files changed here, again after merging main.
  • python3 ci/check_requirements.py and ci/test_check_requirements.py pass. mkdocs build --strict is clean.
  • ci/local-ci.sh on this branch at a5be9f2: every job green (FastAPI embedded 678s, FastAPI SurrealDB server 578s, Next.js 413s, pre-commit 134s, PR title), 2026-10-18 01:42 UTC.

Done questions (AGENTS.md)

  • Goal: delivers what the user wanted, merged on green CI. The four journeys (regenerate and switch, copy, export as PDF, tools and a limit) run on both devices and are in both baselines. Merging waits for green CI.
  • Agents: n/a for the journeys, which measure the web app. What they cover is already in the API (POST /chats/{cid}/messages with regenerate, PUT /chats/{cid}/head, GET /chats/{cid}/export.{md,pdf,json}, PATCH /chats/{cid} with tools and max_tool_calls) and MCP (read_chat, export_chat). Both fixes are web app only.
  • Zero setup: no new prerequisite. run.sh needs the same ports and rclone as before.
  • Fewest clicks and keystrokes: copying an answer went from 2 clicks to 1. Regenerate (1), switching versions (1), export (2: the icon, then the format) and tools (4: the chip, a group, the limit, Done) have no extra step.
  • Configurable: n/a, no new settings.
  • Light: n/a, nothing added to the install, only the survey.
  • Private and secure: n/a, no new surface. Copy still writes to the clipboard inside the click.
  • Cost: n/a, no model calls added. The survey's stand-in model answers.
  • User decides: no new actions and no defaults changed. Tool choices are still saved as they're made, as before.
  • Upgrades: n/a, no stored data changes.
  • Honest: the journeys measure only merged features. Deep research waits for its web app. The PDF journey says which path it took.
  • Tests, docs and generated files updated: jest for the copy split button and the tools save order; docs/assistant.md and docs/requirements.md; the baselines come from run.sh output, not hand edits.
  • Open standards; dependencies keep Lens MIT: no new dependencies.
  • Result reported with evidence; "refine later" items written down (below).
  • Reuse: the copy split button follows Regenerate's; the PDF journey reuses report-pdf's print stub; the save hook uses TanStack Query's own cancel and cache update.

Refine later

  • The deep research journey (C8: goal to note) once its web app merges.
  • README and docs labels (C9 item 4): README's In progress still lists "Chat: a conversation exported as Markdown, PDF or JSON (feat(chat): export a conversation as Markdown, PDF or JSON #474)", which has merged. Copy and export and the Tools chip have no line in the built list and no row in docs/requirements.md yet, so chat-copy, chat-export-pdf and chat-tools aren't named as checks there. Add them with their counts (1, 2 and 4 clicks) when the labels pass adds those rows.
  • chat-export-pdf depends on whether the survey's server can make a PDF. With network access it fetches anytopdf from GitHub on the first PDF (or uses Chromium if it's on the PATH, as on CI's runner). Offline it takes the print path, which counts one more step outside the browser. A run with no network would read one step worse than the baseline.
  • The limit in chat-tools is the default 10. Any other number needs a click into the field, Ctrl+A and the digits, or the − and + buttons one call at a time.
  • The four ci/clicks/*.mjs files fail prettier --check on main, and no Nx project lints them. A project.json with a lint or format target would bring them into make affected.
  • The other places that save a conversation setting and then read it back (scope, model) build each change on what the page holds, as the Tools chip did. They're single-step pickers, so a lost update is less likely, but useSaveTools's pattern would fit them too.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B

An answer's Copy button opened a menu, so copying took two clicks. A click on Copy now copies it as Markdown (its
citations as footnotes, as before); the arrow beside it, as Regenerate has, holds Copy as Markdown, Copy text and
Export as Markdown, PDF or JSON.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
…aved

In a conversation, the Tools chip saved each change and then read the conversation back, and the next change was
made from what the page still held. Switching a group off and then turning on the limit before the first save came
back sent the old tools (Auto) with the limit, and the group came back on. Now each change shows at once, the
changes are saved in the order they were made, and the conversation is read back after the last one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
…ing tools in a chat

chat-regenerate (from Home: the conversation, Regenerate, back to the first version), chat-copy, chat-export-pdf (the
server's PDF downloaded, or the browser's print dialog counted outside the browser) and chat-tools (a group off and a
limit), on a computer and a phone. They run before cloud-model, which stays last since it points Lens away from the
stand-in model; the stand-in model now answers a regenerated question with "..., version 2." so the versions differ.
Both baselines are from full runs, so they also carry entity-merge and graph-merge, which they lacked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
…and-in model titles conversations

Since #531 Lens asks the model for a conversation's title after its first
answer, and the stand-in model's one reply became every conversation's
title in the list beside Chat. chat-ask waits for the reply's words, found
them at once in that list, and ended before its own answer was saved, so
chat-regenerate and the journeys after it found a conversation with a
question and no answer.

The stand-in now answers the title prompt with the first question's words,
as a model would, and first-question and chat-ask wait for the reply inside
the newest answer, not anywhere on the page. The page survey counts a
page's controls again for a few seconds when it finds none, so a settings
page still loading isn't recorded with none.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Both devices, 37 of 37 journeys ok, every journey's count as before. The
per-page control counts move with main: Settings › AI assistant has the
auto title switch, Settings › Sensors two more controls.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
@adeelahmad
adeelahmad merged commit 557327a into main Oct 18, 2026
10 of 11 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-r960xc-c9-journeys branch October 18, 2026 03:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0