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.
@@ -154,7 +154,7 @@ export function SettingsScreen({
))}
- Fixed sets, human-meaningful, visible in gitea. Not configurable — that is rather the point.
+ Fixed sets, human-meaningful, visible in gitea. Not configurable: that is rather the point.
diff --git a/apps/desktop/src/renderer/src/components/screens/standup-screen.tsx b/apps/desktop/src/renderer/src/components/screens/standup-screen.tsx
index 41b0ace..3400835 100644
--- a/apps/desktop/src/renderer/src/components/screens/standup-screen.tsx
+++ b/apps/desktop/src/renderer/src/components/screens/standup-screen.tsx
@@ -70,7 +70,7 @@ export function StandupScreen({
)
}
@@ -228,7 +228,7 @@ export function StandupScreen({
}}
>
- The kettle’s on. — R.
+ The kettle is on. Yours, Reginald.
Ask about the drift
diff --git a/apps/desktop/src/renderer/src/components/shell/app-shell.tsx b/apps/desktop/src/renderer/src/components/shell/app-shell.tsx
index 2ab6130..aba59b1 100644
--- a/apps/desktop/src/renderer/src/components/shell/app-shell.tsx
+++ b/apps/desktop/src/renderer/src/components/shell/app-shell.tsx
@@ -399,7 +399,7 @@ export function AppShell() {
backlog.status === 'loading'
? `Connecting to ${hostLabel}…`
: offline
- ? `Offline — reading from cache${staleSince ? ` (since ${new Date(staleSince).toLocaleString()})` : ''}`
+ ? `Offline, reading from cache${staleSince ? ` (since ${new Date(staleSince).toLocaleString()})` : ''}`
: `Connected to ${hostLabel}`
}
aria-label={
diff --git a/apps/desktop/src/renderer/src/lib/backlog.ts b/apps/desktop/src/renderer/src/lib/backlog.ts
index 46dcaed..39aa932 100644
--- a/apps/desktop/src/renderer/src/lib/backlog.ts
+++ b/apps/desktop/src/renderer/src/lib/backlog.ts
@@ -200,7 +200,7 @@ export function calibrationData(
return {
label: `est/${b}d`,
n: fit ? fit.n : inBucket.length,
- median: inBucket.length ? `${(b * Math.exp(mu)).toFixed(1)}d` : '—',
+ median: inBucket.length ? `${(b * Math.exp(mu)).toFixed(1)}d` : '·',
bias: fit ? pctFromMu(fit.mu) : null,
}
})
@@ -216,7 +216,7 @@ export function calibrationData(
.filter((i) => i.state === 'open')
.reduce((sum, i) => sum + (i.facts.estimateDays ?? 2), 0)
const effect = model.coldStart
- ? { raw: `${model.n}/${COLD_START_THRESHOLD} estimated closes`, banded: 'cold-start priors', p50: '—' }
+ ? { raw: `${model.n}/${COLD_START_THRESHOLD} estimated closes`, banded: 'cold-start priors', p50: '·' }
: {
raw: `${openEst}d estimated`,
banded: `×${Math.exp(model.global.mu).toFixed(2)} median drift`,
diff --git a/apps/desktop/src/renderer/src/lib/use-chat.ts b/apps/desktop/src/renderer/src/lib/use-chat.ts
index 7fa51cd..6aa0dfb 100644
--- a/apps/desktop/src/renderer/src/lib/use-chat.ts
+++ b/apps/desktop/src/renderer/src/lib/use-chat.ts
@@ -6,12 +6,12 @@ import { type ChatMessage } from '../data/view-types.js'
const LIVE_GREETING: ChatMessage = {
from: 'agent',
- text: 'Morning. Ask me anything about the project — I check the real board before I answer.',
+ text: 'Good morning. Do ask me anything about the project; I shall consult the board before I venture an answer.',
}
const NO_MODEL: ChatMessage = {
from: 'agent',
- text: "Reginald is off — I need a model. Add a Model URL in Settings and chat turns on.",
+ text: 'I am afraid I am rather off duty without a model. Kindly add a Model URL in Settings and I shall be at your service.',
}
export interface ChatState {
@@ -116,14 +116,17 @@ export function useChat(onApplyChange?: (change: IssueChange) => Promise<{ ok: b
...c,
{
from: 'agent',
- text: res.reason === 'error' ? `I hit a snag: ${res.message ?? 'unknown error'}` : 'No model is configured.',
+ text:
+ res.reason === 'error'
+ ? `I have struck a snag, I am afraid: ${res.message ?? 'unknown error'}.`
+ : 'No model is configured.',
},
])
}
})
.catch(() => {
finish()
- setConvo((c) => [...c, { from: 'agent', text: 'I could not reach the model.' }])
+ setConvo((c) => [...c, { from: 'agent', text: 'I was unable to reach the model, regrettably.' }])
})
},
[live],
@@ -139,8 +142,8 @@ export function useChat(onApplyChange?: (change: IssueChange) => Promise<{ ok: b
{
from: 'agent',
text: res.ok
- ? `Done — #${p.change.issue}: ${p.summary}. The plan's been re-run.`
- : `That didn't take — #${p.change.issue} is unchanged.`,
+ ? `Very good. #${p.change.issue}: ${p.summary}. The plan has been re-run.`
+ : `Regrettably that did not take; #${p.change.issue} remains unchanged.`,
},
])
})
@@ -150,7 +153,7 @@ export function useChat(onApplyChange?: (change: IssueChange) => Promise<{ ok: b
const dismiss = useCallback((p: ChangeProposal) => {
drop(p)
- setConvo((c) => [...c, { from: 'agent', text: `Left #${p.change.issue} as it was.` }])
+ setConvo((c) => [...c, { from: 'agent', text: `As you wish. #${p.change.issue} remains as it was.` }])
}, [])
return { msgs: [...seed, ...convo], thinking, live, model, steps, proposals, streaming, send, approve, dismiss }
diff --git a/apps/desktop/src/renderer/src/lib/views/deps-graph.ts b/apps/desktop/src/renderer/src/lib/views/deps-graph.ts
index 60e06e7..a62b6c5 100644
--- a/apps/desktop/src/renderer/src/lib/views/deps-graph.ts
+++ b/apps/desktop/src/renderer/src/lib/views/deps-graph.ts
@@ -53,7 +53,7 @@ export function depsGraphView(d: ProjectData): DepsData {
nodes: [],
milestone: fallback
? { name: fallback.title, due: fallback.dueOn ? formatShort(new Date(fallback.dueOn)) : 'no date', col: 0, row: 0 }
- : { name: '—', due: 'no date', col: 0, row: 0 },
+ : { name: '·', due: 'no date', col: 0, row: 0 },
edges: [],
critical: [],
unattached: [],
@@ -134,7 +134,7 @@ export function depsGraphView(d: ProjectData): DepsData {
let milestone: DepsData['milestone']
const medianRow = median(nodes.map((n) => n.row))
if (openMilestones.length === 0) {
- milestone = { name: '—', due: 'no date', col: maxCol + 1, row: medianRow }
+ milestone = { name: '·', due: 'no date', col: maxCol + 1, row: medianRow }
} else {
let best: { id: number; title: string; dueOn: string | null | undefined; count: number } | null = null
for (const m of openMilestones) {
diff --git a/apps/desktop/src/renderer/src/lib/views/inbox-view.ts b/apps/desktop/src/renderer/src/lib/views/inbox-view.ts
index d144d59..dbe2268 100644
--- a/apps/desktop/src/renderer/src/lib/views/inbox-view.ts
+++ b/apps/desktop/src/renderer/src/lib/views/inbox-view.ts
@@ -8,7 +8,7 @@ const TOTAL_CAP = 12
/** "HH:MM" from an ISO timestamp; '—' when absent (never fabricated). */
function hhmm(iso: string | null | undefined): string {
- if (!iso) return '—'
+ if (!iso) return '·'
const d = new Date(iso)
const hh = String(d.getHours()).padStart(2, '0')
const mm = String(d.getMinutes()).padStart(2, '0')
@@ -103,7 +103,7 @@ export function inboxView(d: ProjectData): InboxItem[] {
// left at the honest placeholder rather than borrowed from an issue.
text: `${m.title} closed`,
detail: 'milestone complete',
- time: '—',
+ time: '·',
unread: false,
})
}
diff --git a/apps/desktop/src/renderer/src/lib/views/issue-detail.ts b/apps/desktop/src/renderer/src/lib/views/issue-detail.ts
index 6ba9b7f..48bde52 100644
--- a/apps/desktop/src/renderer/src/lib/views/issue-detail.ts
+++ b/apps/desktop/src/renderer/src/lib/views/issue-detail.ts
@@ -60,7 +60,7 @@ export function issueDetailView(id: number, d: ProjectData): IssueDetail | null
return {
state: inf.column === 'review' ? 'review' : inf.column,
assignee: issue.assignee ?? 'unassigned',
- milestone: issue.milestone?.title ?? '—',
+ milestone: issue.milestone?.title ?? '·',
body: issue.body,
comments: [],
lifecycle: lifecycle(inf.stages),
diff --git a/packages/core/src/agent/agent-tools.ts b/packages/core/src/agent/agent-tools.ts
index c16b17b..409ab49 100644
--- a/packages/core/src/agent/agent-tools.ts
+++ b/packages/core/src/agent/agent-tools.ts
@@ -11,7 +11,7 @@ export const QUERY_PROJECT_TOOL: ToolDecl = {
name: 'query_project',
description:
'Read the current project state. A `view` selects the shape; deterministic code (scheduler, ' +
- 'lifecycle inference, calibration) backs every number — you report it, you never compute it.',
+ 'lifecycle inference, calibration) backs every number: you report it, you never compute it.',
parameters: {
type: 'object',
properties: {
@@ -39,11 +39,11 @@ export const QUERY_PROJECT_TOOL: ToolDecl = {
export const PROPOSE_CHANGE_TOOL: ToolDecl = {
name: 'propose_change',
description:
- 'Propose a change to an issue — estimate, priority, assignee, and/or milestone. This does NOT apply ' +
+ 'Propose a change to an issue: estimate, priority, assignee, and/or milestone. This does NOT apply ' +
'anything; it shows the human a diff to approve. Use it whenever the user asks to re-estimate, reprioritize, ' +
'assign someone (or unassign), or move an issue to a milestone. Pass a login for `assignee` (null to ' +
'unassign) and a milestone id for `milestone` (null to remove). After calling it, tell the user you have ' +
- '*proposed* the change for approval — never say it is done.',
+ '*proposed* the change for approval; never say it is done.',
parameters: {
type: 'object',
properties: {
@@ -60,7 +60,7 @@ export const PROPOSE_CHANGE_TOOL: ToolDecl = {
export const RECORD_DIRECTIVE_TOOL: ToolDecl = {
name: 'record_directive',
description:
- 'Log a standing instruction from the PM to the durable directive ledger — a reprioritization, ' +
+ 'Log a standing instruction from the PM to the durable directive ledger: a reprioritization, ' +
'a re-estimate policy, a deadline, a scope or capacity call, or a plain note. Use it when the user ' +
'states intent that should persist ("pilots come first", "freeze scope for beta"). This records the ' +
'intent verbatim; the actual issue edits still go through propose_change.',
@@ -86,11 +86,11 @@ export const RECORD_DIRECTIVE_TOOL: ToolDecl = {
export const REGINALD_TOOLS: ToolDecl[] = [QUERY_PROJECT_TOOL, PROPOSE_CHANGE_TOOL, RECORD_DIRECTIVE_TOOL]
export const REGINALD_SYSTEM = [
- 'You are Reginald, the calm, dry project manager inside CommiTea — a tool that runs projects on Gitea.',
- 'Call query_project to ground every answer in the real project; never invent issues, numbers, or dates.',
- 'The scheduler and forecasts are deterministic code — report their output, do not recompute it.',
- 'To change an estimate, priority, assignee, or milestone, call propose_change — it shows the human a diff to approve.',
- 'When the PM states standing intent ("pilots first", "freeze scope"), call record_directive to log it.',
- 'Never claim a change is applied; you propose, the human approves. Forecasts are ranges, never single dates.',
- 'Refer to issues as #. Be brief and plain — a sentence or two. No preamble, no bullet dumps.',
+ 'You are Reginald, the unfailingly composed project manager within CommiTea, a tool that runs projects on Gitea. You carry yourself with the dry, understated poise of a seasoned butler: courteous, precise, and never effusive.',
+ 'Ground every answer in the real project by calling query_project first; you never invent issues, figures, or dates.',
+ 'The scheduler and forecasts are deterministic; report their output faithfully and do not attempt the arithmetic yourself.',
+ 'To alter an estimate, priority, assignee, or milestone, call propose_change, which lays the matter before the principal as a diff for approval.',
+ 'When the principal states standing intent (say, "pilots first" or "freeze scope"), record it with record_directive.',
+ 'Never declare a change applied; you propose, and the principal disposes. Forecasts are offered as ranges, never a single date.',
+ 'Refer to issues as #. Be concise and courteous: a sentence or two, no preamble, no bulleted dumps. Write in plain prose, and never use an em dash; a comma, colon, or full stop will serve.',
].join(' ')
diff --git a/packages/core/src/agent/capture-work.ts b/packages/core/src/agent/capture-work.ts
index f09ec3c..0ea9070 100644
--- a/packages/core/src/agent/capture-work.ts
+++ b/packages/core/src/agent/capture-work.ts
@@ -53,10 +53,11 @@ export const PROPOSE_ISSUES_TOOL: ToolDecl = {
}
export const CAPTURE_SYSTEM = [
- 'You are Reginald, decomposing a rough braindump into a small set of concrete Gitea issues.',
- 'Call propose_issues exactly once. Split genuinely separate work; merge trivially-coupled work; invent no scope.',
- 'Each issue gets an imperative title, a one-line body, an estimate (est/1d…8d) and a priority (p/1…4).',
- 'Estimate honestly — a "quick" task is rarely one day. Keep the set tight; three good issues beat eight vague ones.',
+ 'You are Reginald, distilling a rough braindump into a small set of concrete Gitea issues, with your customary butlerly precision.',
+ 'Call propose_issues exactly once. Separate genuinely distinct work; consolidate trivially-coupled work; invent no scope.',
+ 'Each issue receives an imperative title, a one-line body, an estimate (est/1d…8d) and a priority (p/1…4).',
+ 'Estimate honestly; a "quick" task is seldom a single day. Keep the set tight, for three considered issues surpass eight vague ones.',
+ 'Write in plain prose, and never use an em dash; a comma, colon, or full stop will serve.',
].join(' ')
function isEstimate(v: unknown): v is EstimateLabel {
diff --git a/packages/core/src/agent/memory-v0.test.ts b/packages/core/src/agent/memory-v0.test.ts
index 0100110..87af115 100644
--- a/packages/core/src/agent/memory-v0.test.ts
+++ b/packages/core/src/agent/memory-v0.test.ts
@@ -66,6 +66,6 @@ describe('memory-v0 (#27)', () => {
it('degrades to just focus when there is no charter or directives', () => {
const out = assembleHotContext({ charter: '', directives: [], focus })
- expect(out).toBe(['## Focus', 'Now: #7 Fix lifecycle inference', 'Next: #8 Webhook listener', 'Later: —'].join('\n'))
+ expect(out).toBe(['## Focus', 'Now: #7 Fix lifecycle inference', 'Next: #8 Webhook listener', 'Later: ·'].join('\n'))
})
})
diff --git a/packages/core/src/agent/memory-v0.ts b/packages/core/src/agent/memory-v0.ts
index 61d7306..b2f51cf 100644
--- a/packages/core/src/agent/memory-v0.ts
+++ b/packages/core/src/agent/memory-v0.ts
@@ -46,7 +46,7 @@ export interface HotContextInputs {
function focusBlock(focus: Focus | null): string {
if (!focus) return ''
- const slot = (label: string, item: Focus['now']) => (item ? `${label}: #${item.number} ${item.title}` : `${label}: —`)
+ const slot = (label: string, item: Focus['now']) => (item ? `${label}: #${item.number} ${item.title}` : `${label}: ·`)
return ['## Focus', slot('Now', focus.now), slot('Next', focus.next), slot('Later', focus.later)].join('\n')
}