Skip to content

Commit 9134357

Browse files
committed
fix(loop): require isolated historical worktree
1 parent 898999f commit 9134357

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

loops/issue-dev-loop/scripts/lib/github-identity.mjs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,7 @@ async function assertCleanExactDurableWorktree({
13641364
run,
13651365
expectedHead,
13661366
}) {
1367-
const [branch, head, status, indexState] = await Promise.all([
1367+
const [branch, head, status, gitDirectory, commonDirectory, indexState] = await Promise.all([
13681368
execFileAsync(realGit, ['branch', '--show-current'], {
13691369
cwd: repositoryRoot,
13701370
env: environment,
@@ -1378,12 +1378,23 @@ async function assertCleanExactDurableWorktree({
13781378
env: environment,
13791379
maxBuffer: 1024 * 1024,
13801380
}),
1381+
execFileAsync(realGit, ['rev-parse', '--path-format=absolute', '--git-dir'], {
1382+
cwd: repositoryRoot,
1383+
env: environment,
1384+
}),
1385+
execFileAsync(realGit, ['rev-parse', '--path-format=absolute', '--git-common-dir'], {
1386+
cwd: repositoryRoot,
1387+
env: environment,
1388+
}),
13811389
execFileAsync(realGit, ['ls-files', '-v', '-z'], {
13821390
cwd: repositoryRoot,
13831391
env: environment,
13841392
maxBuffer: 8 * 1024 * 1024,
13851393
}),
13861394
])
1395+
if (gitDirectory.stdout.trim() === commonDirectory.stdout.trim()) {
1396+
throw new Error('historical target validation requires an isolated linked Git worktree')
1397+
}
13871398
const concealedIndexEntries = indexState.stdout
13881399
.split('\0')
13891400
.filter(Boolean)

loops/issue-dev-loop/tests/github-identity-routing.test.mjs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ async function createFixture({
7272
remoteCheckpoint = true,
7373
removeLocalRun = false,
7474
terminalFinalization = false,
75+
isolatedWorktree = true,
7576
} = {}) {
7677
const parent = await mkdtemp(path.join(os.tmpdir(), 'echo-ui-identity-routing-'))
7778
const loopRoot = path.join(parent, 'issue-dev-loop')
@@ -626,6 +627,18 @@ if [ "$1 $2" = "rev-parse HEAD" ]; then
626627
echo "${'b'.repeat(40)}"
627628
exit 0
628629
fi
630+
if [ "$1 $2 $3" = "rev-parse --path-format=absolute --git-dir" ]; then
631+
echo ${JSON.stringify(
632+
isolatedWorktree
633+
? path.join(parent, '.git', 'worktrees', 'issue-123')
634+
: path.join(parent, '.git'),
635+
)}
636+
exit 0
637+
fi
638+
if [ "$1 $2 $3" = "rev-parse --path-format=absolute --git-common-dir" ]; then
639+
echo ${JSON.stringify(path.join(parent, '.git'))}
640+
exit 0
641+
fi
629642
if [ "$1 $2 $3" = "status --porcelain=v1 --untracked-files=all" ]; then
630643
if [ -f ${JSON.stringify(path.join(parent, 'dirty-git'))} ]; then
631644
echo " M src/unsafe.ts"
@@ -927,6 +940,32 @@ test('wrapped activation allows an exact durable target ahead of its committed l
927940
})
928941
})
929942

943+
test('wrapped activation rejects an exact durable target in the primary checkout', async () => {
944+
const fixture = await createFixture({
945+
historicalActivation: true,
946+
isolatedWorktree: false,
947+
})
948+
await assert.rejects(
949+
execFileAsync(
950+
routerLauncherPath,
951+
[
952+
'--loop-root',
953+
fixture.loopRoot,
954+
'automation',
955+
'--',
956+
process.execPath,
957+
fixture.loopctlPath,
958+
'validate',
959+
'--activation',
960+
'--loop-root',
961+
fixture.loopRoot,
962+
],
963+
{ env: fixture.env },
964+
),
965+
/historical target validation requires an isolated linked Git worktree/,
966+
)
967+
})
968+
930969
test('wrapped activation rejects historical validation without a remote durable checkpoint', async () => {
931970
const fixture = await createFixture({
932971
historicalActivation: true,

0 commit comments

Comments
 (0)