From 8d750139a19a504481b5b68c77ac248cd4e9c0ec Mon Sep 17 00:00:00 2001 From: Croissant Le Doux Date: Fri, 10 Jul 2026 16:24:20 -0400 Subject: [PATCH 1/2] Make Reginald posh + remove em-dashes from user-facing copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Voice: rewrote REGINALD_SYSTEM and CAPTURE_SYSTEM (core) to an elevated, dry butler register, and re-voiced his visible lines — chat greetings, the approve/dismiss/error replies, the standup closer ('The kettle is on. Yours, Reginald.'), the onboarding welcome, and the capture prose. Both system prompts now also instruct him never to use an em dash. Em-dashes: swept every user-facing string in the renderer free of em-dashes (punctuation only, comments left untouched) via a per-file pass, plus the core tool descriptions and the memory focus-slot placeholder ('· ' not '— '). Bare '—' value placeholders became middots ('·'). No em-dash now renders anywhere in the app or in Reginald's own output. core 169 tests green (updated the memory placeholder assertion) · core + desktop tsc clean · verified visually (posh greeting + standup closer render). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../components/screens/calibration-screen.tsx | 4 ++-- .../src/components/screens/capture-screen.tsx | 20 ++++++++--------- .../src/components/screens/connect-screen.tsx | 10 ++++----- .../components/screens/directives-screen.tsx | 4 ++-- .../src/components/screens/focus-screen.tsx | 4 ++-- .../src/components/screens/issue-screen.tsx | 6 ++--- .../components/screens/milestone-screen.tsx | 2 +- .../components/screens/onboarding-screen.tsx | 14 ++++++------ .../components/screens/settings-screen.tsx | 10 ++++----- .../src/components/screens/standup-screen.tsx | 4 ++-- .../src/components/shell/app-shell.tsx | 2 +- apps/desktop/src/renderer/src/lib/backlog.ts | 4 ++-- apps/desktop/src/renderer/src/lib/use-chat.ts | 17 ++++++++------ .../src/renderer/src/lib/views/deps-graph.ts | 4 ++-- .../src/renderer/src/lib/views/inbox-view.ts | 4 ++-- .../renderer/src/lib/views/issue-detail.ts | 2 +- packages/core/src/agent/agent-tools.ts | 22 +++++++++---------- packages/core/src/agent/capture-work.ts | 9 ++++---- packages/core/src/agent/memory-v0.test.ts | 2 +- packages/core/src/agent/memory-v0.ts | 2 +- 20 files changed, 75 insertions(+), 71 deletions(-) diff --git a/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx b/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx index 1d06861..0e1639a 100644 --- a/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx @@ -189,9 +189,9 @@ export function CalibrationScreen({ onBack, data }: { onBack: () => void; data?:

{c.active ? 'You are not bad at estimating; you are optimistic in a very stable way. Stable, I can work with.' - : 'Not enough closed history yet — I’m forecasting from cold-start priors and widening the cone to stay honest. The curve takes over at 20.'} + : 'Not enough closed history yet: I’m forecasting from cold-start priors and widening the cone to stay honest. The curve takes over at 20.'} {!c.active && c.excludedSameDay > 0 - ? ` And ${c.excludedSameDay} closed ${c.excludedSameDay === 1 ? 'issue' : 'issues'} closed the same day they were started — 0 working days can’t calibrate, so they don’t count toward the 20.` + ? ` And ${c.excludedSameDay} closed ${c.excludedSameDay === 1 ? 'issue' : 'issues'} closed the same day they were started. 0 working days can’t calibrate, so they don’t count toward the 20.` : ''}

diff --git a/apps/desktop/src/renderer/src/components/screens/capture-screen.tsx b/apps/desktop/src/renderer/src/components/screens/capture-screen.tsx index d80eecb..92abe3e 100644 --- a/apps/desktop/src/renderer/src/components/screens/capture-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/capture-screen.tsx @@ -70,10 +70,10 @@ export function CaptureScreen({ onDone }: { onDone: () => void }) { setLiveTickets(res.issues) setStage('review') } else { - setError(res.ok ? 'I could not find concrete work in that — try a bit more detail.' : `Capture failed: ${res.reason === 'error' ? res.message : 'no model'}`) + setError(res.ok ? 'I could not find concrete work in that; try a bit more detail.' : `Capture failed: ${res.reason === 'error' ? res.message : 'no model'}`) } }) - .catch(() => { setBrewing(false); setError('I could not reach the model.') }) + .catch(() => { setBrewing(false); setError('I was unable to reach the model, regrettably.') }) } const fileLive = () => { @@ -84,7 +84,7 @@ export function CaptureScreen({ onDone }: { onDone: () => void }) { .then((res) => { setBrewing(false) if (res.ok) { setFiledCount(res.created.length); setStage('filed') } - else setError('Filing failed — gitea is not configured.') + else setError('Filing failed; gitea is not configured.') }) .catch(() => { setBrewing(false); setError('Filing failed.') }) } @@ -99,12 +99,12 @@ export function CaptureScreen({ onDone }: { onDone: () => void }) { const QUESTIONS: Question[] = [ { - q: 'The auth work — one ticket, or shall I split token refresh from session storage? They fail differently.', + q: 'The auth work: one ticket, or shall I split token refresh from session storage? They fail differently.', chips: ['One ticket', 'Split them'], set: (a) => setSplit(a === 'Split them'), }, { - q: 'The webhook double-fire — how long? I should mention your "quick" has averaged two days.', + q: 'The webhook double-fire, how long? I should mention your "quick" has averaged two days.', chips: ['est/1d', 'est/2d', 'est/3d'], set: (a) => setWebEst(a), }, @@ -205,7 +205,7 @@ export function CaptureScreen({ onDone }: { onDone: () => void }) { {stage === 'dump' ? ( - +

- Sentences, fragments, grievances — all welcome. I'll sort it into tickets and only ask what I can't infer. + Sentences, fragments, grievances; all are welcome. I shall sort them into tickets and enquire only where I cannot infer.

diff --git a/apps/desktop/src/renderer/src/components/screens/connect-screen.tsx b/apps/desktop/src/renderer/src/components/screens/connect-screen.tsx index c329326..32d0a10 100644 --- a/apps/desktop/src/renderer/src/components/screens/connect-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/connect-screen.tsx @@ -28,9 +28,9 @@ export function ConnectScreen({ onConnected, existing }: { onConnected: () => vo const mapError = (e?: string) => e === '401' || e === '403' - ? 'The token was rejected — check it has repo + issue scopes.' + ? 'The token was rejected, check it has repo + issue scopes.' : e === '404' - ? "Couldn't reach that Gitea — check the URL." + ? "Couldn't reach that Gitea, check the URL." : `Discovery failed${e ? ` (${e})` : ''}.` // Discover the owners + repos this token can see. Triggered when the token @@ -114,7 +114,7 @@ export function ConnectScreen({ onConnected, existing }: { onConnected: () => vo label="Access token" type="password" value={token} - placeholder={existing?.hasToken ? '•••••••• (saved — enter a new one to change repos)' : 'gitea PAT · scopes: repo + issue'} + placeholder={existing?.hasToken ? '•••••••• (saved, enter a new one to change repos)' : 'gitea PAT · scopes: repo + issue'} hint={ discovery === 'discovering' ? 'Discovering your repositories…' @@ -157,7 +157,7 @@ export function ConnectScreen({ onConnected, existing }: { onConnected: () => vo value={repo} disabled={!pickerReady || repoOptions.length === 0} options={ - repoOptions.length ? repoOptions.map((r) => ({ value: r, label: r })) : placeholder('—') + repoOptions.length ? repoOptions.map((r) => ({ value: r, label: r })) : placeholder('·') } onChange={(e) => setRepo(e.target.value)} /> @@ -167,7 +167,7 @@ export function ConnectScreen({ onConnected, existing }: { onConnected: () => vo label="Model URL" value={modelUrl} placeholder="http://localhost:1234/v1" - hint="Optional — an OpenAI-compatible endpoint for Reginald. Leave blank to keep chat off." + hint="Optional: an OpenAI-compatible endpoint for Reginald. Leave blank to keep chat off." onChange={(e) => setModelUrl(e.target.value)} /> diff --git a/apps/desktop/src/renderer/src/components/screens/directives-screen.tsx b/apps/desktop/src/renderer/src/components/screens/directives-screen.tsx index 304d62d..2a7c3c6 100644 --- a/apps/desktop/src/renderer/src/components/screens/directives-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/directives-screen.tsx @@ -80,7 +80,7 @@ export function DirectivesScreen() { ) : ( @@ -117,7 +117,7 @@ export function DirectivesScreen() { )}

- Entries are never edited. Corrections are new entries — the ledger remembers everything, politely. + Entries are never edited. Corrections are new entries; the ledger remembers everything, politely.

) diff --git a/apps/desktop/src/renderer/src/components/screens/focus-screen.tsx b/apps/desktop/src/renderer/src/components/screens/focus-screen.tsx index 0d35f05..124daa9 100644 --- a/apps/desktop/src/renderer/src/components/screens/focus-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/focus-screen.tsx @@ -74,7 +74,7 @@ export function FocusScreen({ ) } @@ -113,7 +113,7 @@ export function FocusScreen({

{forecast.coldStart - ? `${forecast.scope} open ${forecast.scope === 1 ? 'issue' : 'issues'} in scope. Cold-start priors — ${forecast.calibratedN}/20 estimated closes so far; the cone tightens as the team closes work.` + ? `${forecast.scope} open ${forecast.scope === 1 ? 'issue' : 'issues'} in scope. Cold-start priors: ${forecast.calibratedN}/20 estimated closes so far; the cone tightens as the team closes work.` : `${forecast.scope} open ${forecast.scope === 1 ? 'issue' : 'issues'} in scope, calibrated on ${forecast.calibratedN} closed ${forecast.calibratedN === 1 ? 'issue' : 'issues'} of your own.`}

diff --git a/apps/desktop/src/renderer/src/components/screens/issue-screen.tsx b/apps/desktop/src/renderer/src/components/screens/issue-screen.tsx index 92f7ec8..a850689 100644 --- a/apps/desktop/src/renderer/src/components/screens/issue-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/issue-screen.tsx @@ -13,7 +13,7 @@ import { import { type IssueDetail, type IssueRef } from '../../data/view-types.js' import { Badge, Button, Card, Dialog, Icon, Select, Tag } from '../ui/index.js' -const NONE = '—' +const NONE = '·' export function IssueScreen({ issue, @@ -214,7 +214,7 @@ export function IssueScreen({
{pendingChanges.length === 0 ? (

- No change yet — pick a different estimate, priority, assignee, or milestone. + No change yet, pick a different estimate, priority, assignee, or milestone.

) : ( <> @@ -265,7 +265,7 @@ export function IssueScreen({
))}
-