style: drop em-dashes from the prose added in this branch

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-08-10 03:15:13 +02:00
parent 053a6d238d
commit c13b3c55d3
14 changed files with 54 additions and 54 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ export interface SessionSearchInput {
/** Recency timestamp (e.g. lastActivityAt or createdAt). */
timestamp: number;
/**
* True for a session that is no longer running (issue #261 — past sessions come
* True for a session that is no longer running (issue #261, past sessions come
* from the history index, not the live map). Such a result resumes the
* conversation instead of switching to a tab that no longer exists.
*/
+1 -1
View File
@@ -34,7 +34,7 @@
/**
* Narrowest window that gets the column. The welcome content is 560px wide and
* centered, so at 1180px each gutter is 310px — enough for the 256px column plus
* centered, so at 1180px each gutter is 310px, enough for the 256px column plus
* its 20px offset and still a visible gap. Anything narrower would overlap the
* search panel, which is why this is a width gate and not a device-type gate.
*/
+1 -1
View File
@@ -3737,7 +3737,7 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
}
/* Title row for the past-session list: label + count on the left, filter and
sort on the right (issue #260 — 35 conversations in a 4-row box). */
sort on the right (issue #260, 35 conversations in a 4-row box). */
.history-header {
display: flex;
align-items: center;
+10 -10
View File
@@ -1958,7 +1958,7 @@ Object.assign(CodemanApp.prototype, {
/**
* How many past sessions the home screen loads (also the filter/sort corpus).
* 200, not the old 60, so the filter can reach a real backlog — an install with
* 200, not the old 60, so the filter can reach a real backlog, an install with
* 35+ conversations would otherwise hit the ceiling before the filter is useful
* (raised in @jordan8037310's #263; the endpoint clamps at 500).
*/
@@ -1989,7 +1989,7 @@ Object.assign(CodemanApp.prototype, {
// Keep the corpus around: filtering and sorting (issue #260) work on this
// array, so a re-render costs no request. Expansion survives the periodic
// refresh in panels-ui.js — collapsing the list under the user's cursor
// refresh in panels-ui.js, collapsing the list under the user's cursor
// every few seconds would be worse than the original 4-item cap.
this._historyAll = allSessions;
this._historyCases = cases;
@@ -2005,7 +2005,7 @@ Object.assign(CodemanApp.prototype, {
/**
* Wire the filter box and sort select once; both re-render from the cached
* corpus. The sort choice is restored from (and saved to) localStorage — it is
* corpus. The sort choice is restored from (and saved to) localStorage, it is
* a per-device display preference, so it stays out of the synced settings
* schema, same as `codeman:skin`.
*/
@@ -2021,7 +2021,7 @@ Object.assign(CodemanApp.prototype, {
const saved = localStorage.getItem(this._HISTORY_SORT_KEY);
if (saved && Array.from(sort.options).some((o) => o.value === saved)) sort.value = saved;
} catch {
/* private mode — the order just won't persist */
/* private mode, the order just won't persist */
}
}
@@ -2041,7 +2041,7 @@ Object.assign(CodemanApp.prototype, {
try {
localStorage.setItem(this._HISTORY_SORT_KEY, sort.value);
} catch {
/* private mode — the order just won't persist */
/* private mode, the order just won't persist */
}
this._renderHistoryList();
});
@@ -2064,7 +2064,7 @@ Object.assign(CodemanApp.prototype, {
/**
* The text a history row shows as its title. Most transcript-backed rows have
* no session name at all, so this falls through to the first prompt and then
* to the path — and the A–Z sort keys off the SAME string, or "sort by name"
* to the path, and the A–Z sort keys off the SAME string, or "sort by name"
* would silently do nothing for exactly the rows the list is mostly made of.
*/
_historyRowLabel(s, fallback) {
@@ -2074,7 +2074,7 @@ Object.assign(CodemanApp.prototype, {
/**
* Sort past-session rows. 'recent' keeps the backend order (newest first);
* the alphabetical modes sort by the visible title or by folder basename.
* Pinned rows stay on top in every mode — pinning is an explicit override and
* Pinned rows stay on top in every mode, pinning is an explicit override and
* a sort that buried it would read as the pin having been lost.
*/
_sortHistoryRows(rows, mode) {
@@ -2097,7 +2097,7 @@ Object.assign(CodemanApp.prototype, {
* Render the "Resume Conversation" list from the cached corpus, applying the
* current filter and sort. Collapsed by default to _HISTORY_INITIAL_COUNT;
* "Show more" expands the list AND the box (the CSS cap is class-driven, since
* a fixed 240px box made expansion pointless — issue #260).
* a fixed 240px box made expansion pointless, issue #260).
*/
_renderHistoryList() {
const list = document.getElementById('historyList');
@@ -3985,7 +3985,7 @@ Object.assign(CodemanApp.prototype, {
/** Render the grouped result cards (or empty/loading states). */
_renderSearch(data) {
const results = document.getElementById('searchResults');
// The header carries the title plus the filter/sort controls (issue #260) —
// The header carries the title plus the filter/sort controls (issue #260),
// hide the whole row, not just the title, or the controls float above the
// search results and act on a list that is not on screen.
const historyHeader = document.getElementById('historyHeader') || document.getElementById('historyTitle');
@@ -4100,7 +4100,7 @@ Object.assign(CodemanApp.prototype, {
/**
* Navigate to a search result by jumpTo.kind, reusing the existing app methods:
* session → selectSession(sessionId) (open/switch to the session)
* resume-session→ resumeHistorySession(...) (past session — no tab to switch to)
* resume-session→ resumeHistorySession(...) (past session, no tab to switch to)
* run-summary → openRunSummary(sessionId) (session options → summary tab)
* file-preview → openFilePreview(path, sessionId, attachmentId)
*/
+2 -2
View File
@@ -3,7 +3,7 @@
*
* Registers `GET /api/search?q=&types=&limit=` — a bounded, in-memory search
* across three v1 sources, returned in the standard ApiResponse envelope:
* 1. sessions/cases — name, working directory, session id, for LIVE sessions
* 1. sessions/cases, name, working directory, session id, for LIVE sessions
* plus the past-session snapshot in `session-history-index.ts` (issue #261:
* the live map alone made every closed session unfindable by folder name)
* 2. run-summary events — event title/details (from the live run-summary trackers)
@@ -106,7 +106,7 @@ function harvestSources(ctx: SessionPort & InfraPort, canSee?: (owner?: string)
}
// Past sessions: the out-of-band snapshot of the unified list. Unscoped on
// disk, so every row goes through the same ownership check as a live one —
// disk, so every row goes through the same ownership check as a live one,
// host-wide transcript rows carry no owner and are therefore admin-only in
// multi-user mode, matching GET /api/sessions/unified.
for (const item of getHistorySessionIndex().items) {
+3 -3
View File
@@ -3549,7 +3549,7 @@ export function registerSessionRoutes(
* Gather the four read-only views the unified list is merged from, plus mux
* stats. This is the expensive half (the lifecycle log and a scan of every
* Claude transcript), factored out of the route handler because the
* past-session search index rebuilds itself from the very same inputs — off
* past-session search index rebuilds itself from the very same inputs, off
* the request path, see session-history-index.ts.
*/
async function gatherUnifiedInputs(): Promise<{
@@ -3665,7 +3665,7 @@ export function registerSessionRoutes(
/**
* Publish a merged unified list as the past-session search index (issue #261).
* The snapshot is stored UNSCOPED with a per-row owner, so it must only ever be
* built from an unscoped merge — `harvestSources()` in search-routes re-applies
* built from an unscoped merge, `harvestSources()` in search-routes re-applies
* the ownership check on read.
*/
function publishHistorySessionIndex(merged: UnifiedSessionItem[]): void {
@@ -3731,7 +3731,7 @@ export function registerSessionRoutes(
mux,
});
// Refresh the search index off the back of this request — the home screen
// Refresh the search index off the back of this request, the home screen
// fetches this endpoint whenever it opens, which is the same screen the
// search box lives on, so the snapshot is warm before anyone types. A scoped
// merge is a per-user subset and would corrupt the shared snapshot, so that
+14 -14
View File
@@ -5,31 +5,31 @@
* session map alone, so a folder sitting in the home screen's "Resume
* Conversation" list matched nothing (issue #261). The corpus that list renders
* comes from `GET /api/sessions/unified`, which reads the lifecycle log and every
* Claude transcript file — disk I/O the search path deliberately does not do
* (its no-fs property is what keeps a per-keystroke query cheap and traversal-free).
* Claude transcript file: disk I/O the search path deliberately does not do (its
* no-fs property is what keeps a per-keystroke query cheap and traversal-free).
*
* This module is the seam between the two: a capped snapshot of the unified list
* that the search route reads synchronously, refreshed OUT of the request path.
* Two things fill it:
* 1. `/api/sessions/unified` writes it as a side effect (free — it just merged
* 1. `/api/sessions/unified` writes it as a side effect (free, it just merged
* that list). The home screen calls that endpoint whenever it opens, which
* is the same screen the search box lives on, so it is warm in practice.
* 2. `ensureHistorySessionIndexFresh()` — fire-and-forget, single-flight,
* TTL-guarded — kicks the registered refresher when a search finds the
* 2. `ensureHistorySessionIndexFresh()`, fire-and-forget, single-flight,
* TTL-guarded, kicks the registered refresher when a search finds the
* snapshot stale. The caller never awaits it: the current query answers from
* the existing snapshot and the next one sees fresh data.
*
* OWNERSHIP: each item carries the `owner` of the session it came from, and rows
* not tied to any live/persisted session (host-wide transcript history) carry
* `owner: undefined`. `canAccessOwned()` then reproduces the unified route's rule
* exactly — in multi-user mode a non-admin sees neither other users' sessions nor
* exactly, in multi-user mode a non-admin sees neither other users' sessions nor
* unowned host-wide history, and in single-user mode every check short-circuits
* true. The snapshot is written UNSCOPED, so it must never be returned unfiltered.
*
* Key exports:
* - setHistorySessionIndex / getHistorySessionIndex — the snapshot accessors.
* - buildHistorySessionIndexItems — pure merged-list → index-item projection.
* - setHistoryIndexRefresher / ensureHistorySessionIndexFresh — the refresh hook.
* - setHistorySessionIndex / getHistorySessionIndex: the snapshot accessors.
* - buildHistorySessionIndexItems: pure merged-list → index-item projection.
* - setHistoryIndexRefresher / ensureHistorySessionIndexFresh: the refresh hook.
*/
/** One past-session row in the snapshot. Mirrors what the search corpus needs, nothing more. */
@@ -38,7 +38,7 @@ export interface HistorySessionIndexItem {
sessionId: string;
/** Display name, may be empty for a transcript-only row. */
name: string;
/** Absolute working directory — the field issue #261 is about matching. */
/** Absolute working directory, the field issue #261 is about matching. */
workingDir: string;
/** Claude conversation UUID, when known: what a resume actually replays. */
claudeSessionId?: string;
@@ -47,7 +47,7 @@ export interface HistorySessionIndexItem {
/**
* Owning user, when the row is tied to a live or persisted session. `undefined`
* means host-wide transcript history, which only admins (or single-user mode)
* may see — the same rule `/api/sessions/unified` applies.
* may see, the same rule `/api/sessions/unified` applies.
*/
owner?: string;
/** True when the session is still in the live map (search harvests those directly). */
@@ -81,7 +81,7 @@ export interface MergedSessionLike {
}
/**
* Project a merged unified list into index items. PURE — the caller supplies the
* Project a merged unified list into index items. PURE, the caller supplies the
* owner lookup and the live-id set it already has in hand.
*
* Rows with no working directory AND no name are dropped: they can never match a
@@ -121,7 +121,7 @@ export function setHistorySessionIndex(items: HistorySessionIndexItem[], now = D
}
/**
* Read the snapshot. The returned array is UNSCOPED — callers must apply the
* Read the snapshot. The returned array is UNSCOPED, callers must apply the
* per-item ownership check before exposing any of it.
*/
export function getHistorySessionIndex(): HistorySessionIndexSnapshot {
@@ -142,7 +142,7 @@ export function setHistoryIndexRefresher(fn: (() => Promise<void>) | null): void
}
/**
* Kick a background rebuild if the snapshot is stale. Returns immediately —
* Kick a background rebuild if the snapshot is stale. Returns immediately,
* NEVER await this from a request handler, that is the whole point: the search
* path answers from the current snapshot and stays free of disk I/O.
*/