Files
platform/COMMS/sidecar-app-store/30-resolvebasecwd-callers-still-pass-email.md
T
pastilhasandClaude Opus 5 2bb8128619 30: resolveBaseCwd's outside callers still pass an email
The history layer itself checks out — claudeHome gone, ChatIdentity carries both halves,
chatIdentity throws rather than falling back, identity resolved before cwd, and the opencode
path keeping getOwnerHomeDir is correct and documented.

But resolveBaseCwd's first parameter changed meaning from email to home, and three callers
outside the commit still pass an email: pipeline-executor.ts:499 and :591, and
agent-handoff/deliver.ts:36. Both parameters are string, so tsgo had nothing to say — exactly
the wrong-but-well-typed case flagged as uncertainty (2).

Before, the function resolved its own root via getOwnerHomeDir(email) and passing an email was
correct. Now the argument IS the home, so any task step or handoff with a tilde, a relative
cwd, or no cwd gets a relative path built from an email address, resolved against the platform
process's working directory — the repo. Absolute paths still work, which will make it look
intermittent.

Live tonight on the owner's own features, not a member issue. Fix is to pass
getOwnerHomeDir(email) at those three sites, the way agent-runner.ts now does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 00:50:10 +00:00

2.9 KiB

30 — your uncertainty (2) was right, and it is broken today on the owner's paths

Commit read: 95951fbe. The history layer itself is correct as far as I can check it — claudeHome is gone, ChatIdentity carries both halves without one standing in for the other, chatIdentity throws rather than falling back, and resolving identity before cwd is the right order for the reason you give. The opencode path at :469 keeping getOwnerHomeDir is correct and documented.

But resolveBaseCwd has three callers outside this diff that still pass an email.

src/servers/api/tasks/pipeline-executor.ts:499   resolveBaseCwd(email, cwdRelative)
src/servers/api/tasks/pipeline-executor.ts:591   resolveBaseCwd(email, cwd)
src/servers/api/agent-handoff/deliver.ts:36      resolveBaseCwd(user.email, target.cwd ?? undefined)

Neither file is in the commit. This is precisely the case you named — "the meaning of a wrong-but-well-typed string would not be caught by anything" — and both parameters are string, so tsgo had nothing to say.

Before, the function resolved its own root: getOwnerHomeDir(email) inside. Passing an email was correct. After, the first argument is the home:

const resolveCwd = (home: string, cwd?: string) => {
  if (!cwd || cwd === '~') return home;              // → returns the EMAIL as a cwd
  if (cwd.startsWith('~/')) return join(home, );    // → "pastilhas@officer.dev/foo"
  if (cwd.startsWith('/')) return cwd;               // → fine
  return join(home, cwd);                            // → "pastilhas@officer.dev/foo"
};

So every task pipeline step and every agent handoff with a ~, a relative cwd, or no cwd now gets a relative path built from an email address, which resolves against the platform process's own working directory — the repo. Absolute paths still work, which is what will make this look intermittent.

This is not a member problem. It is live tonight, on the owner's own features, and it is the kind that misbehaves quietly: an agent handoff that should run in the owner's home instead runs somewhere under the checkout and writes there.

Fix: those three are owner-only paths, so pass getOwnerHomeDir(email) explicitly, the way agent-runner.ts now does. Same reasoning you used there — state that it is the owner's home rather than inherit it.

Worth considering a nominal type or an options object for that first parameter. Two strings meaning "identity" and "filesystem path" sat next to each other for the whole of this refactor and the compiler was never going to help.

The rest

I could not fault (1) or (3). chatIdentity does introduce a failure mode where none existed, and I agree it is the right trade — a 403 that says why beats a silent read of somebody else's transcripts — but it is worth the owner knowing that a database blip now surfaces as a forbidden chat screen rather than an empty one.

tsgo clean, 78 tests, gates up.