fix: attribute dotdot-prefixed usage paths

This commit is contained in:
Neil
2026-05-30 04:57:41 -07:00
parent 2e4c90ecf3
commit 48b9907de9
4 changed files with 75 additions and 3 deletions
+30
View File
@@ -228,6 +228,36 @@ describe('attributeCodexUsageEvent', () => {
expect(attributed?.worktreeId).toBe('repo-2::/workspace/repo/app2')
})
it('attributes cwd paths under dotdot-prefixed child directories to the worktree', async () => {
const attributed = await attributeCodexUsageEvent(
{
sessionId: 'session-1',
timestamp: '2026-04-09T10:00:00.000Z',
cwd: '/workspace/repo/..fixtures/session',
model: 'gpt-5.2-codex',
hasInferredPricing: false,
inputTokens: 100,
cachedInputTokens: 10,
outputTokens: 25,
reasoningOutputTokens: 10,
totalTokens: 125
},
[
{
repoId: 'repo-1',
worktreeId: 'repo-1::/workspace/repo',
path: '/workspace/repo',
displayName: 'Repo',
canonicalPath: '/workspace/repo'
}
]
)
expect(attributed?.projectKey).toBe('worktree:repo-1::/workspace/repo')
expect(attributed?.projectLabel).toBe('Repo')
expect(attributed?.worktreeId).toBe('repo-1::/workspace/repo')
})
it('does not treat different Windows drives as containing paths', async () => {
const attributed = await attributeCodexUsageEvent(
{
+8 -1
View File
@@ -454,7 +454,14 @@ function isContainingPath(candidatePath: string, targetPath: string): boolean {
const isAbsoluteRelative = useWin32
? win32.isAbsolute(relativePath)
: posix.isAbsolute(relativePath)
return !isAbsoluteRelative && !relativePath.startsWith('..') && relativePath !== '.'
const parentPrefix = useWin32 ? `..${win32.sep}` : `..${posix.sep}`
// Why: `..name` is a valid child path; only `..` and `../...` escape.
return (
!isAbsoluteRelative &&
relativePath !== '..' &&
!relativePath.startsWith(parentPrefix) &&
relativePath !== '.'
)
}
function findContainingWorktree(
+29 -1
View File
@@ -3,7 +3,11 @@ import { mkdtempSync, rmSync } from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
import { afterEach, describe, expect, it } from 'vitest'
import { parseOpenCodeUsageDatabase, parseOpenCodeUsageRow } from './scanner'
import {
attributeOpenCodeUsageEvent,
parseOpenCodeUsageDatabase,
parseOpenCodeUsageRow
} from './scanner'
const WORKTREE = '/workspace/repo'
@@ -72,6 +76,30 @@ describe('parseOpenCodeUsageRow', () => {
})
})
describe('attributeOpenCodeUsageEvent', () => {
it('attributes cwd paths under dotdot-prefixed child directories to the worktree', async () => {
const attributed = await attributeOpenCodeUsageEvent(
{
sessionId: 'session-1',
timestamp: '2026-04-09T10:00:00.000Z',
cwd: `${WORKTREE}/..fixtures/session`,
model: 'anthropic/claude-sonnet-4-5',
estimatedCostUsd: 0.012,
inputTokens: 100,
cachedInputTokens: 10,
outputTokens: 25,
reasoningOutputTokens: 10,
totalTokens: 125
},
worktrees()
)
expect(attributed?.projectKey).toBe('worktree:repo-1::/workspace/repo')
expect(attributed?.projectLabel).toBe('Repo')
expect(attributed?.worktreeId).toBe('repo-1::/workspace/repo')
})
})
describe('parseOpenCodeUsageDatabase', () => {
afterEach(() => {
for (const dir of tempDirs) {
+8 -1
View File
@@ -428,7 +428,14 @@ function isContainingPath(candidatePath: string, targetPath: string): boolean {
const isAbsoluteRelative = useWin32
? win32.isAbsolute(relativePath)
: posix.isAbsolute(relativePath)
return !isAbsoluteRelative && !relativePath.startsWith('..') && relativePath !== '.'
const parentPrefix = useWin32 ? `..${win32.sep}` : `..${posix.sep}`
// Why: `..name` is a valid child path; only `..` and `../...` escape.
return (
!isAbsoluteRelative &&
relativePath !== '..' &&
!relativePath.startsWith(parentPrefix) &&
relativePath !== '.'
)
}
async function buildWorktreesWithCanonicalPaths(