Skip to content

fix(copy): use consistent, conversational language across Subshell - #360

Merged
theogravity merged 14 commits into
mainfrom
feat/daemon-copy
Oct 11, 2026
Merged

theogravity merged 14 commits into
mainfrom
feat/daemon-copy

Conversation

@theogravity

@theogravity theogravity commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

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:

  • Full TypeScript tests, type checks, lint, and builds passed.
  • Browser end-to-end suite passed: 56 tests, with four existing skips. Updated its copy assertions and verified install commands against the selected trusted server address.
  • Prose, design, license, dependency, and lockfile checks passed.
  • Formatting, clippy, and tests passed for all three Rust crates.
  • CLI end-to-end setup and installer scenarios passed; the update scenario's safety guard stopped the local run because this host has an installed Subshell Server service.

SSH feature work remains separate from this PR.

theogravity and others added 13 commits October 10, 2026 20:23
…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>
@theogravity theogravity changed the title Agent means the AI agent: the daemon is the daemon, and status copy writes from the reader's seat fix(copy): use consistent, conversational language across Subshell Oct 11, 2026
@theogravity
theogravity merged commit 814194d into main Oct 11, 2026
17 checks passed
@theogravity
theogravity deleted the feat/daemon-copy branch October 11, 2026 08:18
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant