fix: remove the em-dashes this release added (release review)

105 new em-dashes sat in comments, test names and one test fixture from the
foreign tmux adoption work. Replaced by hand with commas, colons or
parentheses, one reading at a time. The fixture now quotes the real refusal
text, which says "It may still be running, try again."

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-11-06 08:20:39 +01:00
1 parent 9d2f9663cb
commit 9442ea8cf4
27 files changed
+99 -99

No files matched your search

+1 -1
View File
@@ -221,7 +221,7 @@ describe('adopted container: the host is not required to have the CLI', () => {
it('derives the flag from the location metadata the session already carries', () => {
// Adoption joined the condition for the same reason docker is in it: an
// adopted session's CLI was started by a human in a process Codeman never
// spawned, so the host binary is irrelevant there too — and demanding it
// spawned, so the host binary is irrelevant there too, and demanding it
// would reject adopting a claude that lives in a container, on an ssh host,
// or simply outside the server process's PATH (the systemd/launchd case).
// What the assertion still pins is that the flag comes from the session's
+2 -2
View File
@@ -10,7 +10,7 @@
* claude: Codeman wrote `.claude/settings.local.json` into their repo on every
* restart, and answered a trust dialog that was theirs to answer.
*
* Each one is paired with a session Codeman DID start — without that control,
* Each one is paired with a session Codeman DID start: without that control,
* "nothing was written" is equally explained by a disabled setting or a loop
* that never ran.
*
@@ -86,7 +86,7 @@ describe('the boot workspace-hook sweep', () => {
expect(await sweep([adopted])).not.toContain('/home/them/repo');
});
it('still skips a plain remote session — the older rule is untouched', async () => {
it('still skips a plain remote session, the older rule is untouched', async () => {
expect(await sweep([fakeSession({ workingDir: '/srv/far', remote: { host: 'box' } })])).not.toContain('/srv/far');
});
});
+3 -3
View File
@@ -6,7 +6,7 @@
* with a ~12s timeout. Riding them along on the 8s poll stacked connections on
* a slow host, so the wide scan now runs only when the user asks. That makes a
* second property load-bearing: the periodic poll's payload cannot contain
* those rows, so they are kept apart and merged — assert only "the request was
* those rows, so they are kept apart and merged: assert only "the request was
* right" and the real failure (the next tick wiping the container rows off the
* list) sails through.
*
@@ -119,7 +119,7 @@ describe('the wide scan is one-shot', () => {
it('keeps the periodic poll local-only, and the container row survives it', async () => {
// Both halves matter. The first is the cost fix; the second is what makes it
// usable — a local-only payload has no container rows in it.
// usable: a local-only payload has no container rows in it.
const { app, calls } = wired();
app.toggleForeignScanRemote();
await vi.waitFor(() => expect(app._allForeignRows()).toHaveLength(2));
@@ -176,7 +176,7 @@ describe('an adoption failure reports what the server said', () => {
// The server deliberately tells two different stories. `_apiJson` folds a
// non-2xx to null, which collapsed both into one message and reported a
// live remote session as deleted every time the link flickered.
const msg = 'Could not reach it just now (ssh box: timeout). It may still be running — try again.';
const msg = 'Could not reach it just now (ssh box: timeout). It may still be running, try again.';
const { app, toasts } = adoptHarness(404, { success: false, error: msg, errorCode: 'NOT_FOUND' });
await app.adoptForeignSession('cand-1');
expect(toasts[0]).toBe(msg);
+11 -11
View File
@@ -1,5 +1,5 @@
/**
* Foreign tmux adoption — the pure core.
* Foreign tmux adoption: the pure core.
*
* These pin the properties that were established by MEASUREMENT against a real
* tmux (3.3a) while the feature was built, and that a plausible-looking refactor
@@ -49,7 +49,7 @@ import { hooksAvailableForMode, sessionHookOptions } from '../src/web/session-wa
// A probe transcript in exactly the shape a real run produces. The pane rows use
// the LITERAL backslash-t that tmux's `-F` emits (verified on next-3.7 and 3.3a),
// while the socket line is space-separated because `sh`'s builtin `echo` expands
// a backslash-t to a real TAB — two different meanings for one escape, two lines
// a backslash-t to a real TAB: two different meanings for one escape, two lines
// apart, which is why the socket marker carries no separator at all.
const PROBE = [
'CMFS /tmp/tmux-0/default',
@@ -65,14 +65,14 @@ const PROBE = [
].join('\n');
describe('buildForeignProbeScript', () => {
it('contains no single quote — it is wrapped in one to cross ssh and docker exec', () => {
it('contains no single quote: it is wrapped in one to cross ssh and docker exec', () => {
// The script is embedded as `ssh host '<script>'` and `docker exec c sh -lc
// '<script>'`. One single quote inside ends the wrapper early and the rest is
// re-tokenized by the remote shell.
expect(buildForeignProbeScript()).not.toContain("'");
});
it('does not disable globbing — the socket sweep IS a glob', () => {
it('does not disable globbing: the socket sweep IS a glob', () => {
// A `set -f` here turned the whole loop into one literal non-match, and the
// probe reported zero sessions on a machine that had three.
expect(buildForeignProbeScript()).not.toMatch(/\bset -f\b/);
@@ -172,7 +172,7 @@ describe('classifyForeignPaneMode', () => {
expect(classifyForeignPaneMode(pane, probe).mode).toBe('codex');
});
it('calls a plain shell a shell — the case this feature exists for', () => {
it('calls a plain shell a shell, the case this feature exists for', () => {
const pane = probe.panes.find((p) => p.sessionName === 'scratch')!;
const c = classifyForeignPaneMode(pane, probe);
expect(c.mode).toBe('shell');
@@ -294,7 +294,7 @@ describe('attach command builders', () => {
it('checks the target exists BEFORE new-session, because new-session invents one', () => {
// ⚠️ `new-session -t` does not fail on a missing target. Measured on tmux 3.3a
// with only `work-prod` present: `new-session -t work` succeeded and joined our
// view into `work-prod`'s group — someone else's session. On a socket with no
// view into `work-prod`'s group, someone else's session. On a socket with no
// server it starts one. The wrapper pane re-runs this on every respawn, and boot
// recovery respawns every dead pane, so without this guard the owner exiting
// their session leaves Codeman creating shells on their machine.
@@ -366,11 +366,11 @@ describe('attach command builders', () => {
it('never sets window-size on the shared window', () => {
// Measured: `window-size largest` is the only setting that protects an
// actively-used session's size, but it is a WINDOW option on a SHARED window
// and SURVIVES our detach — it would permanently rewrite the owner's config.
// and SURVIVES our detach: it would permanently rewrite the owner's config.
expect(buildForeignTmuxInvocation(target)).not.toContain('window-size');
});
it('leaves NO degraded fallback — it either groups or fails with a message', () => {
it('leaves NO degraded fallback: it either groups or fails with a message', () => {
// A read-only `attach-session -r` used to hang off `||`, nominally for a tmux
// too old to group. But `||` fires on ANY new-session failure, and the one that
// happens is a leftover view with the same name: measured, new-session answers
@@ -433,7 +433,7 @@ describe('attach command builders', () => {
containerName: 'my-box',
});
it('looks, then execs — never create, never start', () => {
it('looks, then execs: never create, never start', () => {
// An adopted container belongs to the user. Mirrors the adopted branch of
// buildDockerLaunchCommand, which fails closed rather than mutating it.
expect(cmd).toContain('inspect');
@@ -834,7 +834,7 @@ describe('runForeignProbe', () => {
});
describe('foreignCliSignatures', () => {
it('covers every stock CLI that declares a binary — including the one the hand-written table missed', () => {
it('covers every stock CLI that declares a binary, including the one the hand-written table missed', () => {
// The table this replaced listed eight CLI ids by hand and had already gone
// stale: `omp` shipped without a signature, so a hand-started omp pane was
// classified `shell`. Deriving from `discovery.binaries` makes that class of
@@ -845,7 +845,7 @@ describe('foreignCliSignatures', () => {
for (const id of expected) expect(covered).toContain(id);
});
it('leaves shell out — it declares no binary and is the FALLBACK answer', () => {
it('leaves shell out: it declares no binary and is the FALLBACK answer', () => {
expect(foreignCliSignatures().some((sig) => sig.mode === 'shell')).toBe(false);
});
+1 -1
View File
@@ -158,7 +158,7 @@ export function createMockRouteContext(options?: {
killSession: vi.fn(),
listSessions: vi.fn(() => []),
// A DIFFERENT method from listSessions, and the adoption routes call this
// one. Missing it is not a type error — the handler throws and the route
// one. Missing it is not a type error: the handler throws and the route
// answers 500, which reads as a broken endpoint rather than a broken mock.
getSessions: vi.fn(() => []),
getStats: vi.fn(() => ({})),
+1 -1
View File
@@ -28,7 +28,7 @@ export class MockSession extends EventEmitter {
*/
remote?: SessionRemote;
/**
* Mirrors `Session.isAdopted` — true when this session wraps a process SOMEONE
* Mirrors `Session.isAdopted`: true when this session wraps a process SOMEONE
* ELSE started (a hand-opened tmux session Codeman attached to). A plain field
* rather than a getter over `adopt`, because the routes only ever read the
* boolean and the tests only ever need to set it.
+4 -4
View File
@@ -3,7 +3,7 @@
* keep Codeman from driving a session it did not start.
*
* An adopted session wraps a process SOMEONE ELSE launched. Its `mode` is
* whatever the probe saw — very often `claude` — so every refusal here has to
* whatever the probe saw (very often `claude`), so every refusal here has to
* be its own `isAdopted` check and not a side effect of the external-CLI rule.
* The two questions are different ("is this CLI one we drive?" vs "did we start
* this process?"), and folding them into one means the day the first loosens,
@@ -47,7 +47,7 @@ import type { SessionAdopt } from '../../src/types/session.js';
const SID = 'adopted-1';
// The stand-in defaults to "found nothing", which is what real discovery gives
// under VITEST — so mocking the module does not change the tests that predate it.
// under VITEST, so mocking the module does not change the tests that predate it.
beforeEach(() => {
discoverForeignSessions.mockReset();
discoverForeignSessions.mockResolvedValue({ sessions: [], notes: [] });
@@ -173,7 +173,7 @@ describe('GET /api/mux/foreign', () => {
else process.env.CODEMAN_MULTIUSER = prev;
});
it('is admin-only in multi-user mode — it exposes every user’s processes and cwds', async () => {
it('is admin-only in multi-user mode: it exposes every user’s processes and cwds', async () => {
process.env.CODEMAN_MULTIUSER = '1';
const { app } = await createRouteTestHarness(registerMuxRoutes, {
authUser: { username: 'bob', role: 'user' },
@@ -216,7 +216,7 @@ describe('POST /api/sessions/adopt', () => {
else process.env.CODEMAN_MULTIUSER = prev;
});
it('is admin-only in multi-user mode — adopting a shell is arbitrary host execution', async () => {
it('is admin-only in multi-user mode: adopting a shell is arbitrary host execution', async () => {
process.env.CODEMAN_MULTIUSER = '1';
const { app } = await createRouteTestHarness(registerSessionRoutes, {
authUser: { username: 'bob', role: 'user' },