Repository navigation
fix(copy): use consistent, conversational language across Subshell - #360
Merged
Merged
Conversation
…e reader's seat The operator ruled (2026-10-10) that 'agent' confuses users when it names the node's background program: the daemon is the daemon (or node daemon), and a space-tight column header reads Version. STYLE.md gains the Daemon/Agent glossary rows, the ban on 'node agent' and an 'Agent' column for the daemon, and a new Status and problem sentences section: name what is true of the reader's machine, then the action that remains; no protocol verbs, no possessive riddles. The worked pair is the held-node line, before and after. .claude/rules/design-system.md carries the two-line pointer so UI agents see the ruling without opening the guide. Co-Authored-By: Claude <noreply@anthropic.com>
The word 'agent' now means only the AI agent a pane drives (ruling 2026-10-10, doctrine committed last commit). This applies it: - SPA: the Nodes table's Agent column becomes Version (the detail page already said Node version); the update card says the daemon restarts itself, and the held-node line becomes the operator-approved sentence 'The server will not accept this machine's Subshell daemon version. You can still update it from here.' replacing the refuse-its-agent original. - Node CLI, setup questions, probe warnings, update refusals, the 4406 exit line, maintenance/service/reset/env-forced messages: daemon, with the reader-seat rewrite where the old text described what the protocol layer did. 'KICKS' prose becomes 'disconnects'. - The daemon's own log file becomes logs/daemon.log. No migration: the plane's agent_log_read, the loopback dashboard, status --json, reset, and the desktop app's reveal-a-log ladder all fall back to agent.log until the daemon has written under the new name; tests pin the ladder on both the node and desktop side. Wire field names (agentLog, agentLogPath, agentVersion, kind 'agent') are identifiers and stay. - Desktop: app descriptions, the downgrade refusal, and the no-log hint. - docs: paths.mdx and security.md name the daemon log (and the quoted Nodes-dialog string is corrected to the label the dialog actually shows); node agent in-repo docs follow the file rename. Kept per the ruling: 'launchd agent' (Apple's term for server supervision) and every AI-meaning agent (Add an Agent, the harness card, Send prompt to agent?). Full suites green: node 905, server 3953, rust fmt/clippy/test, design tokens, prose. Co-Authored-By: Claude <noreply@anthropic.com>
The bun suite stubs every service seam, so the renamed log file and the reworded reset line land invisible to it; the compiled scenario is the thing that drives the real binary. It seeded logs/agent.log and grepped 'left the agent', both of which this branch renames. Co-Authored-By: Claude <noreply@anthropic.com>
The rail header (and the home tiles) carried the invisible node's full id as tooltip text, a kept-over reveal from the retired node pill whose point was telling machines apart. An operator, shown the uuid, asked the obvious question: if you can't see it, why is it shown? An id with no page behind it names nothing to act on; title now equals label, and both consumers' equal-title branch renders no tooltip. The cold arm keeps its reveal (a short id becoming the full one) because there the machine IS the reader's, merely not loaded yet. Co-Authored-By: Claude <noreply@anthropic.com>
…refusal, OpenAPI prose Four minor, four nit, all quote-verified: the transfer refusals named the daemon 'the agent on node X' (the double meaning this PR exists to kill, sharpest where a harness reads the sentence about itself); the re-register refusal told the wizard's reader a row 'cannot re-register as an agent'; node-assistant.md still named agent.log as the first rung; the 4409 line said 'another subshell' for a daemon; the rollback lines kept the verb 'refused' the new STYLE section bans in status prose; 'agent node' in shipped OpenAPI descriptions reads as the AI sense. The readable-path docblock now names the one accepted switchover cost (a held poll offset the startup burst outgrows between polls skips bytes until a reload), and the Rust ladder test now also pins legacy-before-manager ordering. Co-Authored-By: Claude <noreply@anthropic.com>
…rap, the schema twins
All quote-verified. The successful-rollback log line still said 'the
control plane refused' where its two failure siblings became 'would not
accept'; the MCP wrap around the transfer-too-old error said 'the agent on
the target node' three times around the (already fixed) interpolated
server sentence; the transfer tool's own z.string description was the
schema twin of the OpenAPI line round one renamed; three comments still
promised the hover reveal the tooltip ruling removed; the 4406 tail asked
for 'a newer subshell'; the restart fallback note kept 'refused'; the
cli-e2e step title kept the old word beside its renamed log file; and the
desktop package.json line this PR edited still shipped an em dash.
The rollback line now has a test pin (daemon.test.ts, 4406 revert path):
'would not accept 9.9.9' present, 'the control plane refused' absent. The
4406 fixture strings now quote the server's real phrasing ('this node is').
Co-Authored-By: Claude <noreply@anthropic.com>
@internal/server-web is on changesets' ignore list; the SPA ships embedded in the server binary, and every prior SPA-only changeset (#356's stale- detection entry among them) names @internal/server. An ignored key here would ride NO release. Co-Authored-By: Claude <noreply@anthropic.com>
…e dashboard verbs
The 4406 revert fallback recorded 'the control plane refused it' into
update-failed.json, which the loopback dashboard prints raw and which the
rewritten rollback line interpolated — 'no reason was given' now, with a
test that closes 4406 WITHOUT a reason and pins both the record and the
log line. The dashboard's three error fallbacks ('The update was refused'
et al) became plain outcomes, matching the update.ts note round two fixed.
The log-file test restores the preload's config home instead of deleting
the variable, so a test added below it cannot resolve the developer's real
~/.config/subshell.
Co-Authored-By: Claude <noreply@anthropic.com>
The MCP tool's shipped description told harnesses (and the humans reading them) that transfers run 'between two AGENT nodes', and one HTTP refusal in the same route family said it plainly - while the refusal it quotes about itself now says 'the daemon'. Both re-worded to machine nodes; the route's own docblock follows its text. Co-Authored-By: Claude <noreply@anthropic.com>
…s, and three strays
The transfer-route test pinned toContain('agent nodes'), a shorter
fragment than the message the last commit re-worded: it failed the moment
that shipped (9/9 now, on 'machine nodes'). The public MCP tools page
duplicated the server description's two sentences verbatim, so it moved
with them. Three OpenAPI prose sites join the swept class ('an agent
node' -> 'a machine node', 'an enrolled agent' -> 'an enrolled machine
node', per the models.ts and reregister precedent this PR set). The
Subshell Server app's reset confirmation - the app no sweep had visited -
says 'a node agent on this machine keep running'; that is the node
daemon. And the dashboard's maxBytes schema line says agent log beside a
file this PR renamed.
Co-Authored-By: Claude <noreply@anthropic.com>
The reset confirmation that gained 'node daemon' renders inside Subshell Server's window; no entry named @internal/desktop-server, so the app would have carried a wording change with no version. Co-Authored-By: Claude <noreply@anthropic.com>
cargo fmt --check on the runner re-wrapped an assert_eq! into one line and re-split an assert! into three; the local toolchain accepted both prior shapes, so rust:check stayed green while CI's fmt gate saw the diff. Content unchanged - wrapping only. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Product copy used inconsistent terms, technical phrasing, and variable-length dialog titles. This change makes UI copy, backend errors, CLI output, notifications, MCP descriptions, website content, and public documentation follow one conversational style. “Agent” consistently means the AI agent; the node background process is the daemon.
The content guide records the approved voice, fixed titles, precise action labels, and confirmation guidance. Prompt insertion clearly distinguishes typing from submitting, and maintenance and lockdown explain that stopping sessions can fail. The docs also reflect current administrator permissions.
Subshells shared with a viewer appear under Shared with you when their node isn't visible. Viewer-specific sharing and permission updates now survive live-feed snapshots without overwriting newer session state. Regression tests cover grants, grouping, and snapshot updates.
Validation:
SSH feature work remains separate from this PR.