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..591b9ee 100644
--- a/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx
+++ b/apps/desktop/src/renderer/src/components/screens/calibration-screen.tsx
@@ -112,7 +112,7 @@ export function CalibrationScreen({ onBack, data }: { onBack: () => void; data?:
estimated (x) vs actual days (y) · actuals inferred from git events, never tracked
+estimated (x) vs actual days (y)
{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..b382839 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.
- Connect your Gitea. Your token is stored encrypted on this machine and never leaves it. + Connect your Gitea.
- 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({{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..4fa6ba8 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({- 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({- Lives in pm-state. Your repo never sees any of it. -
-- I'm Reginald, your project manager. I interview you instead of making you fill in forms, I forecast in - honest ranges, and I never do the arithmetic myself — there's a scheduler for that. + I am Reginald, your project manager. I interview you rather than trouble you with forms, and I forecast + in honest ranges.
- Your plans live in your own Gitea as ordinary issues and labels. Delete me and nothing human is lost. + Your plans reside in your own Gitea as ordinary issues and labels.
) : null} @@ -196,7 +196,7 @@ export function OnboardingScreen({ onConnected }: { onConnected: (dest: 'focus' type="password" value={token} placeholder="gitea PAT" - hint="Scopes: repo, issue. Nothing more." + hint="Scopes: repo, issue." onChange={(e) => { setToken(e.target.value) setDiscovery('idle') @@ -352,14 +352,11 @@ export function OnboardingScreen({ onConnected }: { onConnected: (dest: 'focus' ))} -- No bot comments, no body frontmatter, no synthetic issues — ever. Labels are the only footprint. -
) : null} - first run · everything reversible + first run ) } diff --git a/apps/desktop/src/renderer/src/components/screens/settings-screen.tsx b/apps/desktop/src/renderer/src/components/screens/settings-screen.tsx index 5f2e32d..375a775 100644 --- a/apps/desktop/src/renderer/src/components/screens/settings-screen.tsx +++ b/apps/desktop/src/renderer/src/components/screens/settings-screen.tsx @@ -76,7 +76,6 @@ export function SettingsScreen({- The kettle’s on. — R. + The kettle is on. Yours, Reginald.
- Chat is the write-path. Destructive changes are proposed, never assumed. -
) 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 #