mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
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:
1 parent
9d2f9663cb
commit
9442ea8cf4
27 files changed
+99
-99
No files matched your search
@@ -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
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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(() => ({})),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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' },
|
||||
|
||||
Reference in new issue
Block a user