command hq: data model and the shared commanders directory
first commit of command-hq/command-hq.md's design. two tables plus a many-to-many for tags, no server surface yet — this is data layer only. command_hq_sessions has no name column: /chat never persists a title to postgres, renameClaudeSession appends a summary entry straight into the transcript's own jsonl, and that stays the ONLY place a commander's name can live. no status column either — liveness is derived from chat_session_events the same way the background-job tray already derives it, because a stored status would go stale the moment the harness sidecar restarts without a final task:notification and nothing would ever correct it. category is a plain FK (one per commander, confirmed in spec); tags are the many-to-many case, schema only, no ui planned yet. also: getCommandersDir(email) -> DATA_PATH/<email>/commanders, one shared directory for every commander a user has. the first design was per-commander directories and was dropped same-night: creating a fresh directory timed against the harness's own spawn is a race, and a shared pre-existing directory removes it instead of handling it. deliberately DATA_PATH-rooted even for the owner, unlike ordinary /chat which runs in the owner's real home — that's what keeps commanders out of both the owner's own project transcripts and the /chat list. bunx tsgo clean. no db:push yet — next commit is the router, and the table needs to exist before anything can call it; will note the push requirement clearly when that lands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -197,6 +197,21 @@ export const getEmailDbPath = (ownerEmail: string, accountEmail: string) =>
|
||||
export const getEmailAttachmentCacheDir = (ownerEmail: string) =>
|
||||
join(getEmailAccountsDir(ownerEmail), 'attachment_cache');
|
||||
|
||||
/**
|
||||
* Every commander a user has shares this ONE directory as its cwd — deliberately not one directory per
|
||||
* commander. The first design was per-commander, and was dropped the same night it was proposed: a fresh
|
||||
* directory would have to exist before or exactly when a commander's first turn fires, and racing that
|
||||
* creation against the harness's own spawn is precisely the kind of timing hazard Claude Code's
|
||||
* directory-per-project convention was never built to be driven by. One shared, pre-existing directory
|
||||
* removes the race instead of handling it.
|
||||
*
|
||||
* `DATA_PATH`-rooted even for the OWNER, which is a deliberate departure from ordinary `/chat` — an owner's
|
||||
* normal chat runs in `getOwnerHomeDir` (their real login home). Commanders use the managed directory
|
||||
* instead, on both sides of the account split, which is what keeps them out of the owner's own project
|
||||
* transcripts as surely as `command_hq_sessions` keeps them out of the `/chat` list. See `docs/command-hq.md`.
|
||||
*/
|
||||
export const getCommandersDir = (email: string) => join(DATA_PATH, email, 'commanders');
|
||||
|
||||
/**
|
||||
* Which mail account's store to use, found on DISK rather than by asking the database.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user