From 5e60dd5d10f9b514aa43fa9e3001a8bc5a21fe13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Mon, 10 Aug 2026 22:37:07 +0100 Subject: [PATCH] feat(web): center settings save surface (#2466) --- AGENTS.md | 7 + CHANGELOG.md | 18 +- apps/backend/cmd/mock-agent/handler.go | 12 +- apps/backend/cmd/mock-agent/scenarios.go | 8 +- apps/backend/cmd/mock-agent/sequences.go | 8 +- apps/backend/internal/agent/agents/helpers.go | 2 +- .../runtime/lifecycle/executor_sprites.go | 2 +- apps/backend/internal/i18n/i18n_test.go | 4 +- apps/backend/internal/i18n/locales/en.json | 4 +- .../backend/internal/i18n/locales/pseudo.json | 4 +- apps/backend/internal/i18n/locales/pt-pt.json | 4 +- apps/backend/internal/i18n/locales/zh-cn.json | 4 +- .../internal/task/share/gist_html_test.go | 2 +- apps/web/AGENTS.md | 25 +- apps/web/app/auth/setup-wizard.tsx | 2 +- .../dashboard/components/latest-run-card.tsx | 2 +- .../components/success-rate-chart.tsx | 2 +- .../[id]/runs/components/run-header.tsx | 4 +- .../[id]/runs/components/tasks-touched.tsx | 2 +- .../agents/[id]/runs/runs-list-view.tsx | 4 +- apps/web/app/office/components/agent-card.tsx | 2 +- .../office/components/routing/route-panel.tsx | 4 +- apps/web/app/office/page-client.tsx | 2 +- .../routines/[id]/routine-detail-view.tsx | 2 +- .../workspace/activity/activity-row.tsx | 2 +- .../components/agent-preview-table.tsx | 4 +- .../settings/sync/sync-diff-pane.tsx | 2 +- apps/web/app/stats/stats-charts.tsx | 2 +- apps/web/app/stats/stats-sections.tsx | 2 +- apps/web/app/stats/stats-utils.test.ts | 8 +- apps/web/app/stats/stats-utils.ts | 8 +- .../automation-repository-selection.ts | 2 +- .../automations/schedule-selector.tsx | 2 +- .../github-pr-merged-config.test.tsx | 4 +- .../azure-devops-work-item-detail.tsx | 2 +- .../config-chat/config-chat-panel.tsx | 2 +- .../components/editors/lsp-status-button.tsx | 2 +- .../components/github/issue-watch-table.tsx | 2 +- .../github/my-github/action-presets.ts | 2 +- .../components/github/pr-checks-section.tsx | 4 +- apps/web/components/github/pr-ci-popover.tsx | 2 +- .../components/github/pr-detail-panel.test.ts | 7 +- .../components/github/pr-reviews-section.tsx | 4 +- .../components/github/pr-topbar-button.tsx | 2 +- .../components/jira/jira-secret-help.test.tsx | 2 +- .../components/jira/jira-ticket-common.tsx | 2 +- .../components/linear/linear-issue-dialog.tsx | 2 +- apps/web/components/review/types.test.ts | 2 +- apps/web/components/runs/automation-rows.ts | 6 +- apps/web/components/runs/run-feed-item.tsx | 2 +- .../runs/use-manual-trigger.test.ts | 4 +- .../sentry/sentry-issue-watchers-section.tsx | 2 +- .../session/prepare-progress.test.tsx | 6 +- .../settings/command-prefix-field.test.tsx | 2 +- .../model-config-resolution-status.test.tsx | 4 + .../model-config-resolution-status.tsx | 7 +- .../model-fallback-settings-shell.tsx | 6 +- .../settings/plugins/marketplace-browser.tsx | 2 +- .../plugins/marketplace-entry-row.test.tsx | 2 +- .../plugins/marketplace-entry-row.tsx | 2 +- .../settings/plugins/plugin-manifest-card.tsx | 2 +- .../settings/profile-advanced-options.tsx | 51 +++ .../remote-credentials-card.test.tsx | 2 +- .../settings/profile-form-fields.test.tsx | 116 ++++++- .../settings/profile-form-fields.tsx | 114 ++++--- .../settings/repository-secret-bindings.tsx | 2 +- .../settings/settings-floating-save.tsx | 114 +++++-- .../settings/settings-layout-client.test.tsx | 1 + .../settings/settings-layout-client.tsx | 14 +- .../settings/settings-save-provider.test.tsx | 172 +++++++++- .../settings/settings-save-provider.tsx | 121 +++++-- .../settings/ssh-agent-readiness-card.tsx | 2 +- .../components/settings/ssh-sessions-card.tsx | 4 +- .../use-workflow-draft-contributor.ts | 16 +- .../workflow-pipeline-editor-helpers.tsx | 20 +- .../workflow-sync-status-banner.test.tsx | 2 +- .../components/task-create-dialog-effects.ts | 2 +- .../task-create-dialog-remote-repo-chip.tsx | 2 +- .../components/task-create-dialog-submit.tsx | 2 +- .../task/changes-panel-hooks.test.ts | 12 +- .../chat/chat-input-toolbar-primitives.tsx | 6 +- .../task/chat/token-usage-display.test.tsx | 4 +- .../chat/use-chat-input-container.test.ts | 2 +- .../task/dockview-add-panel-items.tsx | 2 +- .../task/executor-settings-button.test.tsx | 2 +- .../components/task/passthrough-toolbar.tsx | 2 +- .../task/sidebar-filter/view-manager.tsx | 2 +- apps/web/components/task/sidebar-mock-data.ts | 2 +- .../simple/components/agents-multi-picker.tsx | 2 +- .../components/task/task-archived-context.tsx | 2 +- .../components/task/task-cleanup-summary.ts | 4 +- .../task/task-detail-context-panel.tsx | 2 +- apps/web/e2e/fixtures/backend.ts | 22 ++ apps/web/e2e/fixtures/docker-test-base.ts | 1 + apps/web/e2e/fixtures/ssh-test-base.ts | 1 + apps/web/e2e/fixtures/test-base.ts | 1 + apps/web/e2e/pages/session-page.ts | 6 +- .../chat/agent-message-attribution.spec.ts | 6 +- .../tests/chat/context-window-source.spec.ts | 4 +- apps/web/e2e/tests/chat/mcp-status.spec.ts | 2 +- .../chat/mobile-context-window-source.spec.ts | 4 +- .../mobile-entity-reference-composer.spec.ts | 4 +- .../e2e/tests/chat/mobile-mcp-status.spec.ts | 2 +- .../e2e/tests/chat/tool-completion.spec.ts | 5 +- .../tests/docker/storage-maintenance.spec.ts | 51 ++- .../e2e/tests/git/git-changes-panel.spec.ts | 1 + .../github-authentication.spec.ts | 3 +- .../github-workspace-settings.spec.ts | 40 ++- .../hide-disabled-integrations-nav.spec.ts | 12 +- .../mobile-github-workspace-settings.spec.ts | 19 +- apps/web/e2e/tests/lsp/lsp-e2e-helpers.ts | 23 +- apps/web/e2e/tests/pr/pr-checks-timer.spec.ts | 33 +- .../review/mobile-review-multi-pr.spec.ts | 6 +- .../e2e/tests/review/review-multi-pr.spec.ts | 6 +- .../review/review-sidebar-resize.spec.ts | 9 +- .../settings/config-chat-popover.spec.ts | 51 +++ .../tests/settings/config-management.spec.ts | 36 ++- ...bile-agent-profile-config-selector.spec.ts | 21 +- .../mobile-config-chat-popover.spec.ts | 38 ++- .../settings/mobile-general-settings.spec.ts | 37 ++- .../mobile-no-silent-model-fallback.spec.ts | 14 + .../mobile-repository-secrets.spec.ts | 2 +- .../settings/no-silent-model-fallback.spec.ts | 34 ++ .../settings/settings-manual-save.spec.ts | 40 +++ .../ssh/lsp-unsupported-executor.spec.ts | 5 +- .../web/e2e/tests/task/autopilot-mode.spec.ts | 4 +- .../tests/task/mobile-autopilot-mode.spec.ts | 23 +- .../e2e/tests/terminal/terminal-agent.spec.ts | 40 ++- .../domains/session/use-session-messages.ts | 2 +- .../session/use-session-resumption.test.ts | 4 +- .../domains/session/use-session-resumption.ts | 2 +- .../domains/settings/use-dynamic-models.ts | 133 ++++++-- .../use-profile-model-capabilities.ts | 22 ++ apps/web/hooks/use-lazy-load-messages.ts | 4 +- apps/web/lib/i18n/index.test.ts | 2 +- apps/web/lib/review/format.ts | 2 +- apps/web/package.json | 2 +- apps/web/scripts/check-no-em-dash-ui.mjs | 305 ++++++++++++++++++ apps/web/scripts/check-no-em-dash-ui.test.ts | 79 +++++ apps/web/src/locales/en/account.json | 2 +- apps/web/src/locales/en/agents.json | 2 +- apps/web/src/locales/en/auth.json | 2 +- apps/web/src/locales/en/automations.json | 18 +- apps/web/src/locales/en/chat.json | 6 +- apps/web/src/locales/en/common.json | 18 +- apps/web/src/locales/en/diff.json | 4 +- apps/web/src/locales/en/executors.json | 2 +- apps/web/src/locales/en/github.json | 18 +- apps/web/src/locales/en/gitlab.json | 6 +- apps/web/src/locales/en/integrations.json | 4 +- apps/web/src/locales/en/jira.json | 20 +- apps/web/src/locales/en/linear.json | 14 +- apps/web/src/locales/en/office.json | 26 +- apps/web/src/locales/en/plugins.json | 4 +- apps/web/src/locales/en/review.json | 6 +- apps/web/src/locales/en/sentry.json | 24 +- apps/web/src/locales/en/settings.json | 17 +- apps/web/src/locales/en/system.json | 6 +- apps/web/src/locales/en/task.json | 38 +-- apps/web/src/locales/en/tasks.json | 4 +- apps/web/src/locales/en/workflows.json | 28 +- apps/web/src/locales/pseudo/account.json | 2 +- apps/web/src/locales/pseudo/agents.json | 2 +- apps/web/src/locales/pseudo/auth.json | 2 +- apps/web/src/locales/pseudo/automations.json | 18 +- apps/web/src/locales/pseudo/chat.json | 6 +- apps/web/src/locales/pseudo/common.json | 18 +- apps/web/src/locales/pseudo/diff.json | 4 +- apps/web/src/locales/pseudo/executors.json | 2 +- apps/web/src/locales/pseudo/github.json | 18 +- apps/web/src/locales/pseudo/gitlab.json | 6 +- apps/web/src/locales/pseudo/integrations.json | 4 +- apps/web/src/locales/pseudo/jira.json | 20 +- apps/web/src/locales/pseudo/linear.json | 14 +- apps/web/src/locales/pseudo/office.json | 26 +- apps/web/src/locales/pseudo/plugins.json | 4 +- apps/web/src/locales/pseudo/review.json | 6 +- apps/web/src/locales/pseudo/sentry.json | 24 +- apps/web/src/locales/pseudo/settings.json | 17 +- apps/web/src/locales/pseudo/system.json | 6 +- apps/web/src/locales/pseudo/task.json | 38 +-- apps/web/src/locales/pseudo/tasks.json | 4 +- apps/web/src/locales/pseudo/workflows.json | 28 +- apps/web/src/locales/pt-pt/account.json | 2 +- apps/web/src/locales/pt-pt/agents.json | 2 +- apps/web/src/locales/pt-pt/auth.json | 2 +- apps/web/src/locales/pt-pt/automations.json | 16 +- apps/web/src/locales/pt-pt/chat.json | 6 +- apps/web/src/locales/pt-pt/common.json | 18 +- apps/web/src/locales/pt-pt/diff.json | 4 +- apps/web/src/locales/pt-pt/executors.json | 2 +- apps/web/src/locales/pt-pt/github.json | 18 +- apps/web/src/locales/pt-pt/gitlab.json | 6 +- apps/web/src/locales/pt-pt/integrations.json | 4 +- apps/web/src/locales/pt-pt/jira.json | 20 +- apps/web/src/locales/pt-pt/linear.json | 14 +- apps/web/src/locales/pt-pt/office.json | 26 +- apps/web/src/locales/pt-pt/plugins.json | 4 +- apps/web/src/locales/pt-pt/review.json | 6 +- apps/web/src/locales/pt-pt/sentry.json | 24 +- apps/web/src/locales/pt-pt/settings.json | 17 +- apps/web/src/locales/pt-pt/system.json | 6 +- apps/web/src/locales/pt-pt/task.json | 38 +-- apps/web/src/locales/pt-pt/tasks.json | 4 +- apps/web/src/locales/pt-pt/workflows.json | 28 +- apps/web/src/locales/zh-cn/account.json | 2 +- apps/web/src/locales/zh-cn/agents.json | 10 +- apps/web/src/locales/zh-cn/auth.json | 2 +- apps/web/src/locales/zh-cn/automations.json | 16 +- apps/web/src/locales/zh-cn/chat.json | 6 +- apps/web/src/locales/zh-cn/common.json | 16 +- apps/web/src/locales/zh-cn/diff.json | 4 +- apps/web/src/locales/zh-cn/editors.json | 4 +- apps/web/src/locales/zh-cn/executors.json | 2 +- apps/web/src/locales/zh-cn/github.json | 8 +- apps/web/src/locales/zh-cn/gitlab.json | 6 +- apps/web/src/locales/zh-cn/integrations.json | 4 +- apps/web/src/locales/zh-cn/jira.json | 14 +- apps/web/src/locales/zh-cn/linear.json | 10 +- apps/web/src/locales/zh-cn/office.json | 26 +- apps/web/src/locales/zh-cn/plugins.json | 4 +- apps/web/src/locales/zh-cn/review.json | 6 +- apps/web/src/locales/zh-cn/sentry.json | 20 +- apps/web/src/locales/zh-cn/settings.json | 17 +- apps/web/src/locales/zh-cn/system.json | 22 +- apps/web/src/locales/zh-cn/task.json | 47 +-- apps/web/src/locales/zh-cn/tasks.json | 4 +- apps/web/src/locales/zh-cn/workflows.json | 28 +- .../0046-settings-route-save-coordinator.md | 6 +- docs/decisions/INDEX.md | 2 +- .../settings-save-action-redesign/plan.md | 204 ++++++++++++ .../task-01-centered-save-surface.md | 87 +++++ .../task-02-save-surface-e2e.md | 84 +++++ docs/specs/ui/settings-manual-save.md | 13 +- 234 files changed, 2730 insertions(+), 963 deletions(-) create mode 100644 apps/web/components/settings/profile-advanced-options.tsx create mode 100644 apps/web/scripts/check-no-em-dash-ui.mjs create mode 100644 apps/web/scripts/check-no-em-dash-ui.test.ts create mode 100644 docs/plans/settings-save-action-redesign/plan.md create mode 100644 docs/plans/settings-save-action-redesign/task-01-centered-save-surface.md create mode 100644 docs/plans/settings-save-action-redesign/task-02-save-surface-e2e.md diff --git a/AGENTS.md b/AGENTS.md index d7dccc8ec7..ef7bd8ed2f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -109,6 +109,13 @@ it **skips anything assigned to a SCREAMING_CASE identifier** — so a those by eye. The pseudo-locale (Settings → General → Appearance, dev/e2e builds) is the completeness check. Full guide: [`docs/i18n.md`](docs/i18n.md). +UI punctuation is plain and intentional: do not use the Unicode em dash (U+2014) +in user-facing copy or locale values. Use a period, colon, comma, semicolon, or +parentheses instead. This applies to English, pseudo, and translated catalogs, +rendered fallback strings. `pnpm run i18n:check` enforces it. Historical +`CHANGELOG.md` entries are excluded because the changelog is generated release +history and remains immutable. + ### Knowledge - **Public docs:** Website-ready user documentation lives in `docs/public/**`. Use `/docs-maintainer` when a change affects CLI commands, config keys, install/deploy flows, workflows, executors, public APIs, screenshots, or user-facing terminology. - **Specs:** Feature specs live in `docs/specs//spec.md` — the durable "what & why" of a feature, written before coding. Use `/spec` to write or update a spec. See `docs/specs/INDEX.md`. diff --git a/CHANGELOG.md b/CHANGELOG.md index ce21efe6db..5a0498baa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -681,7 +681,7 @@ All notable changes to Kandev. - improve ACP model configuration summaries ([#1723](https://github.com/kdlbs/kandev/pull/1723)) - warn about workflow replay cycles ([#1720](https://github.com/kdlbs/kandev/pull/1720)) - route agents through execution profiles ([#1725](https://github.com/kdlbs/kandev/pull/1725)) -- richer frontend SDK — page chrome, nav icons, more host UI ([#1759](https://github.com/kdlbs/kandev/pull/1759)) +- richer frontend SDK: page chrome, nav icons, more host UI ([#1759](https://github.com/kdlbs/kandev/pull/1759)) - add repository defaults to saved GitHub queries ([#1758](https://github.com/kdlbs/kandev/pull/1758)) - add cmd+shift+g shortcut to open the task's github pr ([#1757](https://github.com/kdlbs/kandev/pull/1757)) - typed capability-gated Host data API (ADR 0043) ([#1753](https://github.com/kdlbs/kandev/pull/1753)) @@ -1322,13 +1322,13 @@ All notable changes to Kandev. - inject MCP servers in CLI passthrough mode per agent ([#1158](https://github.com/kdlbs/kandev/pull/1158)) - make chat reverse-i-search shortcut configurable ([#1255](https://github.com/kdlbs/kandev/pull/1255)) -- full GitLab integration — parity with GitHub ([#1120](https://github.com/kdlbs/kandev/pull/1120)) +- full GitLab integration: parity with GitHub ([#1120](https://github.com/kdlbs/kandev/pull/1120)) - support ** and brace globs in copy_files patterns ([#1248](https://github.com/kdlbs/kandev/pull/1248)) - resizable review dialog sidebar with persistence ([#1245](https://github.com/kdlbs/kandev/pull/1245)) - chat history nav with ArrowUp/Down and Ctrl+R fuzzy search ([#1246](https://github.com/kdlbs/kandev/pull/1246)) - include associated PRs in task-listing tools ([#1236](https://github.com/kdlbs/kandev/pull/1236)) - add reverse direction to recent task switcher ([#1241](https://github.com/kdlbs/kandev/pull/1241)) -- multi-branch tasks — N (repo, branch) pairs per task ([#1226](https://github.com/kdlbs/kandev/pull/1226)) +- multi-branch tasks: N (repo, branch) pairs per task ([#1226](https://github.com/kdlbs/kandev/pull/1226)) - add voice mode to task create dialog ([#1230](https://github.com/kdlbs/kandev/pull/1230)) - service-managed UI self-update ([#1210](https://github.com/kdlbs/kandev/pull/1210)) - show inline download progress for Whisper Web model ([#1228](https://github.com/kdlbs/kandev/pull/1228)) @@ -1386,7 +1386,7 @@ All notable changes to Kandev. - retry transient provider 529 errors with visible backoff ([#1173](https://github.com/kdlbs/kandev/pull/1173)) - per-session ACP debug logs with rotation and retention ([#1172](https://github.com/kdlbs/kandev/pull/1172)) - auto-expand the first group in the changes panel ([#1169](https://github.com/kdlbs/kandev/pull/1169)) -- remote tab in task-create dialog — multi-row GitHub repo picker ([#1116](https://github.com/kdlbs/kandev/pull/1116)) +- remote tab in task-create dialog: multi-row GitHub repo picker ([#1116](https://github.com/kdlbs/kandev/pull/1116)) - annotate debug logs with task_id for per-task filtering ([#1168](https://github.com/kdlbs/kandev/pull/1168)) - add PR closed banner and hide CI chip on terminal state ([#1161](https://github.com/kdlbs/kandev/pull/1161)) - collapse mobile task search into a topbar icon ([#1157](https://github.com/kdlbs/kandev/pull/1157)) @@ -1502,7 +1502,7 @@ All notable changes to Kandev. - add per-agent-profile environment variables ([#1040](https://github.com/kdlbs/kandev/pull/1040)) by @Foprta - copy gitignored files from repo into new worktrees ([#946](https://github.com/kdlbs/kandev/pull/946)) ([#950](https://github.com/kdlbs/kandev/pull/950)) - make webhook trigger usable end-to-end ([#1051](https://github.com/kdlbs/kandev/pull/1051)) -- first-class user terminals — stable seq, rename, park/resume ([#1009](https://github.com/kdlbs/kandev/pull/1009)) +- first-class user terminals: stable seq, rename, park/resume ([#1009](https://github.com/kdlbs/kandev/pull/1009)) - roomier pane caps + remember user-set widths ([#1005](https://github.com/kdlbs/kandev/pull/1005)) - inspect mode with pin and area annotations ([#917](https://github.com/kdlbs/kandev/pull/917)) - add Share to session tab context menu ([#1050](https://github.com/kdlbs/kandev/pull/1050)) @@ -1827,7 +1827,7 @@ All notable changes to Kandev. - eager-init agent on profile selection ([#747](https://github.com/kdlbs/kandev/pull/747)) - add message_task_kandev tool ([#745](https://github.com/kdlbs/kandev/pull/745)) - deferred task move with hand-off prompt + boot/turn-end event split ([#743](https://github.com/kdlbs/kandev/pull/743)) -- mobile terminal key-bar — Ctrl/Shift modify OS-keyboard input + iOS keyboard fixes ([#741](https://github.com/kdlbs/kandev/pull/741)) +- mobile terminal key-bar: Ctrl/Shift modify OS-keyboard input + iOS keyboard fixes ([#741](https://github.com/kdlbs/kandev/pull/741)) - make --port the user-facing port flag ([#737](https://github.com/kdlbs/kandev/pull/737)) - expose MCP server to external coding agents ([#732](https://github.com/kdlbs/kandev/pull/732)) - hide Jira buttons when disabled or auth failing ([#725](https://github.com/kdlbs/kandev/pull/725)) @@ -1846,7 +1846,7 @@ All notable changes to Kandev. - close tooltips on popover close and refine branch chip UX ([#808](https://github.com/kdlbs/kandev/pull/808)) - make executors_running the single source of truth for agent_execution_id ([#799](https://github.com/kdlbs/kandev/pull/799)) - use shared prompt template with placeholder autocomplete ([#801](https://github.com/kdlbs/kandev/pull/801)) -- tab session bugs — primary star drift + tab close re-creation ([#800](https://github.com/kdlbs/kandev/pull/800)) +- tab session bugs: primary star drift + tab close re-creation ([#800](https://github.com/kdlbs/kandev/pull/800)) - retry session commits fetch when workspace not ready ([#789](https://github.com/kdlbs/kandev/pull/789)) - focus task name on create dialog open ([#788](https://github.com/kdlbs/kandev/pull/788)) - dedupe cancel-turn clicks to stop "turn cancelled" cascade ([#784](https://github.com/kdlbs/kandev/pull/784)) @@ -1940,7 +1940,7 @@ All notable changes to Kandev. ### Bug Fixes -- ui polish — unified topbar, selector consistency, quick actions editor improvements ([#693](https://github.com/kdlbs/kandev/pull/693)) +- ui polish: unified topbar, selector consistency, quick actions editor improvements ([#693](https://github.com/kdlbs/kandev/pull/693)) - subtask sessions inherit agent profile from parent task ([#692](https://github.com/kdlbs/kandev/pull/692)) - recover from stale execution ID when auto-starting agent on prepared workspace ([#690](https://github.com/kdlbs/kandev/pull/690)) - apply initialValues when TaskCreateDialog mounts already-open ([#688](https://github.com/kdlbs/kandev/pull/688)) @@ -1986,7 +1986,7 @@ All notable changes to Kandev. ### Features -- sidebar filter UX polish — align ops, group steps by workflow ([#647](https://github.com/kdlbs/kandev/pull/647)) +- sidebar filter UX polish: align ops, group steps by workflow ([#647](https://github.com/kdlbs/kandev/pull/647)) - explain why Start task button is disabled via hover tooltip ([#649](https://github.com/kdlbs/kandev/pull/649)) - add filter/group/sort and saved views to task sidebar ([#644](https://github.com/kdlbs/kandev/pull/644)) - vscode-style preview tabs for files, diffs, and commits ([#622](https://github.com/kdlbs/kandev/pull/622)) diff --git a/apps/backend/cmd/mock-agent/handler.go b/apps/backend/cmd/mock-agent/handler.go index b4bbc542f5..e632e4ffa3 100644 --- a/apps/backend/cmd/mock-agent/handler.go +++ b/apps/backend/cmd/mock-agent/handler.go @@ -19,7 +19,7 @@ import ( // orchestrator's routingerr classifier matches the "529 ... Overloaded" // signature in this string and routes it to the retry-with-backoff path. const overloaded529Message = "Internal error: API Error: 529 Overloaded. This is a server-side issue, " + - "usually temporary — try again in a moment. If it persists, check https://status.claude.com." + "usually temporary. Try again in a moment. If it persists, check https://status.claude.com." // overloadedCmdRe matches `/overloaded` or `/e2e:overloaded`, optionally // followed by `:N` — the number of consecutive prompts to fail with a 529 @@ -90,7 +90,7 @@ func (a *mockAgent) handleOverloaded(ctx context.Context, sid acp.SessionId, pro // turn completes (and the orchestrator clears the retry budget). _ = os.Remove(overloadedCounterPath(sid)) e := &emitter{ctx: ctx, conn: a.conn, sid: sid} - e.text(fmt.Sprintf("Provider recovered after %d transient failure(s) — here is your response.", failTimes)) + e.text(fmt.Sprintf("Provider recovered after %d transient failure(s). Here is your response.", failTimes)) return acp.PromptResponse{StopReason: acp.StopReasonEndTurn}, nil, true } @@ -161,7 +161,7 @@ func emitBulk(e *emitter, count int) { e.text(fmt.Sprintf("Generating %d messages to populate the chat history…", count)) for i := 1; i <= count; i++ { e.text(fmt.Sprintf( - "Bulk message %d of %d — filler content for testing chat pagination and the load-older button.", + "Bulk message %d of %d: filler content for testing chat pagination and the load-older button.", i, count)) // The tool-call start flushes the text above into its own message row. toolID := nextToolID() @@ -171,7 +171,7 @@ func emitBulk(e *emitter, count int) { fixedDelay(8) } e.text(fmt.Sprintf( - "Done — emitted %d messages. Scroll up and use “Load older messages” to page through them.", + "Done. Emitted %d messages. Scroll up and use “Load older messages” to page through them.", count)) } @@ -229,6 +229,8 @@ var kandevSystemRegex = regexp.MustCompile(`[\s\S]*? Programs must be written for people to read, and only incidentally for machines to execute.\n" + - "> — Harold Abelson\n\n" + + "> Harold Abelson\n\n" + "> A second blockquote paragraph to verify spacing between consecutive quote blocks " + "and to ensure the left-border styling extends for the full height of wrapped lines.\n\n" + "---\n\n" + diff --git a/apps/backend/internal/agent/agents/helpers.go b/apps/backend/internal/agent/agents/helpers.go index f7789c59b9..6ecb5a367c 100644 --- a/apps/backend/internal/agent/agents/helpers.go +++ b/apps/backend/internal/agent/agents/helpers.go @@ -15,7 +15,7 @@ var agentctlAutoApproveSetting = PermissionSetting{ Supported: true, Default: false, Label: "Auto-approve all permissions", - Description: "Kandev allows every agent permission request without prompting you. Dangerous — use only in trusted workspaces.", + Description: "Kandev allows every agent permission request without prompting you. Dangerous. Use only in trusted workspaces.", ApplyMethod: PermissionApplyMethodAgentctlAutoApprove, } diff --git a/apps/backend/internal/agent/runtime/lifecycle/executor_sprites.go b/apps/backend/internal/agent/runtime/lifecycle/executor_sprites.go index 76429423fe..53dc13146b 100644 --- a/apps/backend/internal/agent/runtime/lifecycle/executor_sprites.go +++ b/apps/backend/internal/agent/runtime/lifecycle/executor_sprites.go @@ -278,7 +278,7 @@ func (r *SpritesExecutor) fallbackToFreshSandbox( }) notice := beginStep("Reconnecting cloud sandbox") - notice.Warning = "Previous sandbox is no longer available — provisioning a fresh one for this branch." + notice.Warning = "Previous sandbox is no longer available; provisioning a fresh one for this branch." notice.WarningDetail = fmt.Sprintf( "The Sprites sandbox %s could not be reached (it was likely destroyed or expired). "+ "Kandev is starting a fresh sandbox %s on the same branch %s; this typically takes 30–60 seconds.", diff --git a/apps/backend/internal/i18n/i18n_test.go b/apps/backend/internal/i18n/i18n_test.go index 65c8019854..e795d4285e 100644 --- a/apps/backend/internal/i18n/i18n_test.go +++ b/apps/backend/internal/i18n/i18n_test.go @@ -67,7 +67,7 @@ func TestTf(t *testing.T) { want string }{ {"interpolates a placeholder", "en", "share.pageTitle", - map[string]any{"title": "Fix the flake"}, "Fix the flake — kandev share"}, + map[string]any{"title": "Fix the flake"}, "Fix the flake; kandev share"}, {"count of one selects the singular", "en", "share.messageCount", map[string]any{"count": 1}, "1 message"}, {"count of zero selects the plural", "en", "share.messageCount", @@ -94,7 +94,7 @@ func TestTf(t *testing.T) { // A placeholder with no value stays visible; a silent hole in a // sentence is much harder to notice in review than "{{title}}". {"missing var leaves the placeholder", "en", "share.pageTitle", - nil, "{{title}} — kandev share"}, + nil, "{{title}}; kandev share"}, {"unsupported locale falls back to en", "klingon", "share.messageCount", map[string]any{"count": 2}, "2 messages"}, {"non-numeric count is ignored", "en", "share.untitledTask", diff --git a/apps/backend/internal/i18n/locales/en.json b/apps/backend/internal/i18n/locales/en.json index 13949f9337..9a9af9d161 100644 --- a/apps/backend/internal/i18n/locales/en.json +++ b/apps/backend/internal/i18n/locales/en.json @@ -17,8 +17,8 @@ "share.noMetadata": "no metadata", "share.openRenderedView": "**[Open the rendered view →]({{url}})** for a properly styled conversation.", "share.openShareHTML": "**Open {{file}}** for the rendered conversation.", - "share.pageTitle": "{{title}} — kandev share", - "share.pitch": "Shared from **[kandev]({{url}})** — the open-source agentic dev environment.", + "share.pageTitle": "{{title}}; kandev share", + "share.pitch": "Shared from **[kandev]({{url}})**; the open-source agentic dev environment.", "share.rawExport": "Raw export:", "share.redacted": "Redacted:", "share.redactedBeforePublish": "Redacted before publish:", diff --git a/apps/backend/internal/i18n/locales/pseudo.json b/apps/backend/internal/i18n/locales/pseudo.json index 7aadea0158..3db213e0a7 100644 --- a/apps/backend/internal/i18n/locales/pseudo.json +++ b/apps/backend/internal/i18n/locales/pseudo.json @@ -17,8 +17,8 @@ "share.noMetadata": "ńō ḿēţàďàţà", "share.openRenderedView": "**[Ōƥēń ţĥē ŕēńďēŕēď vĩēŵ →]({{url}})** ƒōŕ à ƥŕōƥēŕĺŷ śţŷĺēď ćōńvēŕśàţĩōń.", "share.openShareHTML": "**Ōƥēń {{file}}** ƒōŕ ţĥē ŕēńďēŕēď ćōńvēŕśàţĩōń.", - "share.pageTitle": "{{title}} — ķàńďēv śĥàŕē", - "share.pitch": "Śĥàŕēď ƒŕōḿ **[ķàńďēv]({{url}})** — ţĥē ōƥēń-śōũŕćē àĝēńţĩć ďēv ēńvĩŕōńḿēńţ.", + "share.pageTitle": "{{title}}; ķàńďēv śĥàŕē", + "share.pitch": "Śĥàŕēď ƒŕōḿ **[ķàńďēv]({{url}})**; ţĥē ōƥēń-śōũŕćē àĝēńţĩć ďēv ēńvĩŕōńḿēńţ.", "share.rawExport": "Ŕàŵ ēxƥōŕţ:", "share.redacted": "Ŕēďàćţēď:", "share.redactedBeforePublish": "Ŕēďàćţēď ƀēƒōŕē ƥũƀĺĩśĥ:", diff --git a/apps/backend/internal/i18n/locales/pt-pt.json b/apps/backend/internal/i18n/locales/pt-pt.json index f87fb72d22..8ec4626928 100644 --- a/apps/backend/internal/i18n/locales/pt-pt.json +++ b/apps/backend/internal/i18n/locales/pt-pt.json @@ -17,8 +17,8 @@ "share.noMetadata": "sem metadados", "share.openRenderedView": "**[Abrir a vista renderizada →]({{url}})** para ver a conversa devidamente formatada.", "share.openShareHTML": "**Abra {{file}}** para ver a conversa renderizada.", - "share.pageTitle": "{{title}} — partilha do kandev", - "share.pitch": "Partilhado a partir do **[kandev]({{url}})** — o ambiente de desenvolvimento com agentes de código aberto.", + "share.pageTitle": "{{title}}; partilha do kandev", + "share.pitch": "Partilhado a partir do **[kandev]({{url}})**; o ambiente de desenvolvimento com agentes de código aberto.", "share.rawExport": "Exportação em bruto:", "share.redacted": "Censurado:", "share.redactedBeforePublish": "Censurado antes da publicação:", diff --git a/apps/backend/internal/i18n/locales/zh-cn.json b/apps/backend/internal/i18n/locales/zh-cn.json index 84949b67e8..22e3841814 100644 --- a/apps/backend/internal/i18n/locales/zh-cn.json +++ b/apps/backend/internal/i18n/locales/zh-cn.json @@ -17,8 +17,8 @@ "share.noMetadata": "无元数据", "share.openRenderedView": "**[打开渲染视图 →]({{url}})**,查看正确排版的对话。", "share.openShareHTML": "**打开 {{file}}** 查看渲染后的对话。", - "share.pageTitle": "{{title}} — kandev 分享", - "share.pitch": "由 **[kandev]({{url}})** 分享——开源的智能代理开发环境。", + "share.pageTitle": "{{title}}; kandev 分享", + "share.pitch": "由 **[kandev]({{url}})** 分享--开源的智能代理开发环境。", "share.rawExport": "原始导出:", "share.redacted": "已脱敏:", "share.redactedBeforePublish": "发布前已脱敏:", diff --git a/apps/backend/internal/task/share/gist_html_test.go b/apps/backend/internal/task/share/gist_html_test.go index 81d8f56a06..4c75822343 100644 --- a/apps/backend/internal/task/share/gist_html_test.go +++ b/apps/backend/internal/task/share/gist_html_test.go @@ -43,7 +43,7 @@ func TestBuildShareHTML_RendersChatLayout(t *testing.T) { doc := BuildShareHTML(snap, "en") assertContains(t, doc, "") - assertContains(t, doc, "Investigate <flaky> test — kandev share") + assertContains(t, doc, "Investigate <flaky> test; kandev share") assertContains(t, doc, "