Skip to content

rename tasks to chats and add an image viewer - #242

Open
ka-wah wants to merge 7 commits into
mainfrom
small-chats
Open

rename tasks to chats and add an image viewer#242
ka-wah wants to merge 7 commits into
mainfrom
small-chats

Conversation

@ka-wah

@ka-wah ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

The dock's "task" vocabulary was the OS-level word leaking into chat UI. Rename every user-visible mention to "chat" — dock header, popovers, agent panel, transcript, console runtime pages, and the gateway's chat-title strings. Identifiers, routes, and proc delegate's separate "delegated task" concept keep the old name.

Chat surfaces:

  • Meta-row buttons open the chat list and start a new chat. Both boxes are odd-sized: a 1px glyph stroke only lands on whole pixels when the box centring it is odd, so the even box snapped them off-centre.
  • TaskListGlyph's bullets were zero-length round-cap strokes, which drop out under shape-rendering: crispEdges — they are rects now, so the glyph reads as a list instead of a right-shifted hamburger.
  • The chats popover puts its count beside the title and a + in the corner (new PopoverMenu header action), leaving one VIEW ALL row at the bottom.
  • Hovering a message timestamp shows the full date and time, via a new opt-in single-line Hint.

Image viewer (ImageLightbox): click a chat image to open it full-screen — click to zoom at that point and again to fit, wheel and pinch zoom anchored at the pointer, drag to pan, download, Escape or backdrop to close. The toolbar carries the filename and, quieter beside it, when the image was sent. Zoom and pan maths lives in imageLightboxGeometry with tests.

Also: the MCP add-server form placeholders Linear rather than GitHub.

The dock's "task" vocabulary was the OS-level word leaking into chat UI.
Rename every user-visible mention to "chat" — dock header, popovers, agent
panel, transcript, console runtime pages, and the gateway's chat-title
strings. Identifiers, routes, and `proc delegate`'s separate "delegated
task" concept keep the old name.

Chat surfaces:
- Meta-row buttons open the chat list and start a new chat. Both boxes are
  odd-sized: a 1px glyph stroke only lands on whole pixels when the box
  centring it is odd, so the even box snapped them off-centre.
- TaskListGlyph's bullets were zero-length round-cap strokes, which drop out
  under shape-rendering: crispEdges — they are rects now, so the glyph reads
  as a list instead of a right-shifted hamburger.
- The chats popover puts its count beside the title and a + in the corner
  (new PopoverMenu header action), leaving one VIEW ALL row at the bottom.
- Hovering a message timestamp shows the full date and time, via a new
  opt-in single-line Hint.

Image viewer (ImageLightbox): click a chat image to open it full-screen —
click to zoom at that point and again to fit, wheel and pinch zoom anchored
at the pointer, drag to pan, download, Escape or backdrop to close. The
toolbar carries the filename and, quieter beside it, when the image was
sent. Zoom and pan maths lives in imageLightboxGeometry with tests.

Also: the MCP add-server form placeholders Linear rather than GitHub.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review pls

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 181d3c46fe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +139 to +142
useEffect(() => {
const previous = document.activeElement as HTMLElement | null;
closeRef.current?.focus();
return () => previous?.focus?.();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Trap keyboard focus inside the image viewer

When a keyboard user tabs forward from the Close button—or backward from the first enabled toolbar control—focus wraps into the chat behind this aria-modal dialog because this effect only sets the initial focus. Those hidden controls can then be activated while the viewer remains open; contain Tab navigation within the lightbox as the existing Dialog and ConfirmModal components do.

Useful? React with 👍 / 👎.

Comment on lines +148 to +150
.gsv-lightbox-caption {
flex: none;
margin: 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound long captions so the image remains visible

When a model-provided image description is tall enough to exceed the viewport, this non-shrinking caption consumes its full intrinsic height in the fixed full-screen flex column, reducing the image stage to zero height and overflowing content that cannot be reached because body scrolling is disabled. Give the caption a bounded, scrollable height or otherwise allow it to shrink.

Useful? React with 👍 / 👎.

Trap Tab inside the lightbox. It is aria-modal, but only the initial focus was
set, so tabbing off the close button walked into the transcript behind it,
where a control is invisible and still activatable. Same trap Dialog and
ConfirmModal use, disabled-filter included: zoom out is disabled at fit, so
wrapping onto it would drop focus out of the viewer.

Bound the caption. A long image description took its full intrinsic height in
the fixed flex column, squeezing the stage to nothing and overflowing off a
page that cannot scroll. It now shrinks, caps at a third of the screen, and
scrolls its own overflow.

Give the delivery-notice tombstone test a real timeout. It walks 257 notices,
each awaiting a proc.changed signal, which lands near the 5s default locally
and over it on a loaded CI runner.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review pls

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf2f0e60de

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread gateway/src/process/do.ts Outdated
const TASK_TITLE_GENERATION_TIMEOUT_MS = 20_000;
const TASK_TITLE_SYSTEM_PROMPT = [
"Write a concise task title in the same language as the message.",
"Write a concise chat title in the same language as the message.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move the title prompt under prompt ownership

This introduces production system-prompt text directly in the process runtime, even though the repository contract centralizes production prompts in gateway/src/prompts/**. Keeping the title-generation prompt here splits prompt ownership and bypasses the repository's protected prompt review boundary; move the prompt to the owning prompts module and import it here.

AGENTS.md reference: AGENTS.md:L108-L110

Useful? React with 👍 / 👎.

Comment on lines +328 to +331
<a
class="gsv-lightbox-btn"
href={src}
download={filename || alt || "image"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent remote downloads from replacing the app

When an image media record supplies a cross-origin HTTP(S) URL—which chatMediaSource explicitly accepts—the browser ignores the download attribute. Because this anchor neither converts the response to a blob nor opens a separate target, clicking Download navigates the current GSV tab to the image and tears down the active chat UI instead of downloading the file.

Useful? React with 👍 / 👎.

Move the chat-title system prompt into gateway/src/prompts/, which AGENTS.md
makes the owner of production prompt text. It sat in process/do.ts, next to
the runtime knobs that drive it; the compaction prompt already shows the shape.
Text unchanged.

Fetch a cross-origin image into a blob before downloading it. chatMediaSource
accepts remote http(s) URLs, and there the browser ignores the anchor's
download attribute and navigates instead — in a single-page app that replaces
the running chat with the image. Same-origin and blob: sources still download
straight from the anchor; a host that refuses the fetch falls back to opening
the image in its own tab, which at least leaves the chat standing.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review svp

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0375d3b3c1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +298 to +300
void downloadViaBlob(src, downloadName).then((downloaded) => {
if (!downloaded) {
window.open(src, "_blank", "noopener,noreferrer");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Open the download fallback during user activation

When a cross-origin image host does not provide CORS headers—which is valid for an image displayed via <img>downloadViaBlob resolves false and this new fallback invokes window.open asynchronously after the fetch. For a slow request, the click's transient user activation has expired by then, so popup blocking leaves the Download action producing neither a file nor a fallback tab; reserve the tab synchronously in the click handler or expose a user-activated fallback link.

Useful? React with 👍 / 👎.

A host may serve an image to <img> and still refuse a cors fetch of it. The
fetch has to fail before we know that, and by then the click's transient user
activation is spent, so the window.open fallback was liable to be swallowed by
the popup blocker — leaving Download with nothing to show for it.

Show a notice with a plain link instead. The reader's click on it carries its
own activation, so the tab always opens, and the failure is now visible rather
than silent.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review aub

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a8f8bba18b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +51 to +52
[`${statusForProcess(process).toLowerCase()} chat`, owner, process.profile, process.cwd],
"Process-backed chat with durable history and runtime controls.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve process labels for non-chat runtimes

When proc.list includes a scheduled process.spawn or another interactive: false process, RuntimePage passes it here without filtering, so this function now describes that background process as a chat and the detail page offers labels such as “RESET CHAT” and “OPEN CHAT.” iconForProcess already distinguishes these noninteractive entries; keep generic process/runtime wording for them or apply chat terminology only when process.interactive is true.

AGENTS.md reference: AGENTS.md:L36-L38

Useful? React with 👍 / 👎.

proc.list carries every process, so the runtime pages also list scheduled
spawns and other interactive: false entries. The rename described those as
chats too, and offered them RESET CHAT and OPEN CHAT — for something nobody
ever chatted with. A new processNoun() picks the word from process.interactive,
and the detail page's labels, confirmations and blurb follow it.

Collection labels (the CHATS list, its NEW CHAT and the breadcrumb back to it)
stay as they are: they name the surface, not a single row.

Also bottom-align the dock's context reading with the model row and drop the
box around it, and take the header's action buttons down to 27px. Mobile keeps
its boxed 44px context cell.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c853a51694

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}
if (running) {
const openLabel = openCount === 1 ? "1 open task" : `${openCount} open tasks`;
const openLabel = openCount === 1 ? "1 open chat" : `${openCount} open chats`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude background processes from open-chat counts

When an account owns a running scheduled or otherwise interactive: false process, ownedProcesses and openCount still include it, so the crew card can report “1 open chat” even when the only activity is a background process. The current revision’s fresh evidence is that processNoun now explicitly recognizes this distinction, but this overview count remains unfiltered; count only interactive processes here or describe the value as process activity.

AGENTS.md reference: AGENTS.md:L36-L38

Useful? React with 👍 / 👎.

ka-wah added 2 commits August 21, 2026 15:40
A stroke is centred on its path, so the 1px bars of a 24-unit plus always
landed half on one pixel and half on the next: the renderer either blurred them
or snapped one a whole pixel sideways, leaving the crossing off centre. Round
caps on all four arms did the rest, and it read as a cross.

It is two filled rects on whole coordinates now. The box and the bar are both
odd, so the arms are equal by construction at any size, and they inset two
pixels so the glyph matches the weight of the list icon it sits beside.
MinusGlyph shares the geometry — the two are a pair in the image viewer.
The crew card counted every process an account owns, so a running scheduled
spawn reported "1 open chat" for a conversation nobody ever had. Count the
interactive ones for that label, and when an account is running only background
work, say that instead of claiming a chat.

The other readings on this card — queued, needs review — are process-level
facts and stay as they are.
@ka-wah

ka-wah commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 0bc16bf505

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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.

1 participant