a deleted commander stays deleted, and the header shows its name
two things that should have been settled already.
commanders/46 came back as an empty directory after a clean delete. not a
surviving loop — nothing from 46 was running. resolveChatCwd did
`mkdirSync(dir, {recursive:true})` on every commander turn, so one
in-flight turn from the conversation that outlived the row recreated it.
an empty directory is worse than none: a commander with no CLAUDE.md that
knows nothing about itself, showing up in the file browser as something
that still exists.
the directory is created by POST /command-hq/commanders before any turn
spawns, so a missing one means deleted. no mkdir here — fall back to the
home and say so, the same degradation the missing-row branch already
reports.
and the detail header showed the harness's own summary title, which it
makes from the first prompt: "You have been named "Voice Memos". Look in
`/home/…`", on a commander whose name was correct everywhere else. the list
route already prefers row.name. this now does too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -39,7 +39,7 @@ import {
|
|||||||
import { resolveHomeDir } from '@@/user-home';
|
import { resolveHomeDir } from '@@/user-home';
|
||||||
import { renameClaudeSession, type ChatIdentity } from './claude-sessions';
|
import { renameClaudeSession, type ChatIdentity } from './claude-sessions';
|
||||||
import { claudeLoginState } from '@@/os-user-claude';
|
import { claudeLoginState } from '@@/os-user-claude';
|
||||||
import { mkdirSync } from 'node:fs';
|
import { mkdirSync, existsSync } from 'node:fs';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import { isSuperAdmin } from '@@/super-admin';
|
import { isSuperAdmin } from '@@/super-admin';
|
||||||
import { snapshotClaudeUsage } from './usage-store';
|
import { snapshotClaudeUsage } from './usage-store';
|
||||||
@@ -201,8 +201,25 @@ async function resolveChatCwd(
|
|||||||
`[command-hq] no commander row for ${msg.commanderId !== undefined ? `id ${msg.commanderId}` : `session ${msg.resumeSessionId ?? '(none given)'}`} — falling back to the account home`,
|
`[command-hq] no commander row for ${msg.commanderId !== undefined ? `id ${msg.commanderId}` : `session ${msg.resumeSessionId ?? '(none given)'}`} — falling back to the account home`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const dir = row ? getCommanderDir(email, row.dirName) : home;
|
if (!row) return home;
|
||||||
mkdirSync(dir, { recursive: true });
|
|
||||||
|
/*
|
||||||
|
The directory must already exist. `POST /command-hq/commanders` creates it with its `CLAUDE.md`
|
||||||
|
before any turn spawns, so a missing one means the commander was DELETED — and a late turn from the
|
||||||
|
conversation that outlived it would otherwise recreate it here.
|
||||||
|
|
||||||
|
That happened: an empty `commanders/46` reappeared after a clean delete, from one in-flight turn
|
||||||
|
calling this. An empty directory is worse than none, because it is a commander with no CLAUDE.md
|
||||||
|
that knows nothing about itself, and it shows up in the file browser as something that still exists.
|
||||||
|
|
||||||
|
So: no mkdir. Fall back to the home, and say so — the same degradation the missing-row branch above
|
||||||
|
reports, for the same reason.
|
||||||
|
*/
|
||||||
|
const dir = getCommanderDir(email, row.dirName);
|
||||||
|
if (!existsSync(dir)) {
|
||||||
|
console.warn(`[command-hq] ${row.dirName}: directory is gone — deleted mid-turn? Falling back to the home.`);
|
||||||
|
return home;
|
||||||
|
}
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
if (msg.context === 'email') return resolveEmailCwd(email, msg.contextId);
|
if (msg.context === 'email') return resolveEmailCwd(email, msg.contextId);
|
||||||
|
|||||||
@@ -676,7 +676,14 @@ function ResumedCommander({ sessionId, resume }: { sessionId: string; resume: Re
|
|||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col">
|
||||||
<MetaBar
|
<MetaBar
|
||||||
sessionId={sessionId}
|
sessionId={sessionId}
|
||||||
title={resume.title ?? undefined}
|
/*
|
||||||
|
The commander's NAME, not the transcript's title.
|
||||||
|
|
||||||
|
The harness titles its own summary record from the first prompt, so this header read "You have
|
||||||
|
been named "Voice Memos". Look in `/home/…`" — the opening brief, verbatim — on a commander whose
|
||||||
|
name was right everywhere else. The list route already prefers `row.name`; this did not.
|
||||||
|
*/
|
||||||
|
title={commander?.name ?? resume.title ?? undefined}
|
||||||
isConnected={chat.isConnected}
|
isConnected={chat.isConnected}
|
||||||
isGenerating={chat.isGenerating}
|
isGenerating={chat.isGenerating}
|
||||||
onDisconnect={chat.disconnectSession}
|
onDisconnect={chat.disconnectSession}
|
||||||
|
|||||||
Reference in New Issue
Block a user