From 1fe1f26010d1bb5fdbb8edb240cadf3a54c658e4 Mon Sep 17 00:00:00 2001 From: Marcos Santanna <2573094+mv2sa@users.noreply.github.com> Date: Sun, 25 Oct 2026 08:50:03 -0700 Subject: [PATCH 1/4] fix(opencode): anchor checkGaGraph path check to /src/ so antigravity checkout dirs build --- packages/opencode/scripts/build-tui.test.ts | 9 ++++++++- packages/opencode/scripts/build-tui.ts | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/opencode/scripts/build-tui.test.ts b/packages/opencode/scripts/build-tui.test.ts index 22d7500c..10c286b2 100644 --- a/packages/opencode/scripts/build-tui.test.ts +++ b/packages/opencode/scripts/build-tui.test.ts @@ -742,7 +742,14 @@ test('graph.ga_roots', async () => { }) test('graph.ga_policy_refusals', async () => { - const ok = { files: ['/x/src/ga/tui/host-ga.tsx'], externals: ['solid-js'] } + const ok = { + files: [ + '/x/src/ga/tui/host-ga.tsx', + '/work/antigravity/packages/opencode/src/ga/tui/host-ga.tsx', + '/work/antigravity/packages/opencode/src/common-auth-embedded/quota/codec.js', + ], + externals: ['solid-js'], + } checkGaGraph(ok, 'source') const refusals: Array< [Parameters[0], 'source' | 'runtime', string] diff --git a/packages/opencode/scripts/build-tui.ts b/packages/opencode/scripts/build-tui.ts index 7be0503f..01f1d403 100644 --- a/packages/opencode/scripts/build-tui.ts +++ b/packages/opencode/scripts/build-tui.ts @@ -160,9 +160,13 @@ export function checkGaGraph( graph: Graph, emitted: 'source' | 'raw' | 'runtime', ) { - for (const path of graph.files) - if (GA_FORBIDDEN_SOURCE.test(portable(path))) + for (const path of graph.files) { + const normalized = portable(path) + const srcIndex = normalized.lastIndexOf('/src/') + const candidate = srcIndex >= 0 ? normalized.slice(srcIndex) : normalized + if (GA_FORBIDDEN_SOURCE.test(candidate)) throw new Error(`graph.ga: forbidden GA source ${path}`) + } for (const edge of graph.externals) { if (emitted === 'runtime') { // Emitted runtime code must name host runtime modules, never a package From aee66164117bc032e26a2d08fcceb786085cdc02 Mon Sep 17 00:00:00 2001 From: Marcos Santanna <2573094+mv2sa@users.noreply.github.com> Date: Mon, 26 Oct 2026 18:15:23 -0700 Subject: [PATCH 2/4] fix(opencode): anchor checkGaGraph and auditGraph paths to packageRoot --- packages/opencode/scripts/build-tui.test.ts | 99 +++++++++++++++++---- packages/opencode/scripts/build-tui.ts | 47 ++++++++-- 2 files changed, 125 insertions(+), 21 deletions(-) diff --git a/packages/opencode/scripts/build-tui.test.ts b/packages/opencode/scripts/build-tui.test.ts index 10c286b2..ffb59f61 100644 --- a/packages/opencode/scripts/build-tui.test.ts +++ b/packages/opencode/scripts/build-tui.test.ts @@ -713,7 +713,7 @@ test('graph.ga_roots', async () => { 'src/tui/quota-layout.tsx', 'src/tui/route-layout.ts', ]) - checkGaGraph(source, 'source') + checkGaGraph(source, 'source', product) const map = JSON.parse(await readFile(join(product, GA_TUI_ROOT.map), 'utf8')) expect(map.compiler).toBe('@cortexkit/common-auth/tui-build@0.24.0') for (const [variant, tree, entry, kind] of [ @@ -721,7 +721,7 @@ test('graph.ga_roots', async () => { [map.runtime, GA_TUI_ROOT.runtime, GA_TUI_ROOT.runtimeEntry, 'runtime'], ] as const) { const graph = await auditGraph(join(product, tree, entry)) - checkGaGraph(graph, kind) + checkGaGraph(graph, kind, product) expect(graph.files.length).toBe(source.files.length) expect( variant.files @@ -742,32 +742,90 @@ test('graph.ga_roots', async () => { }) test('graph.ga_policy_refusals', async () => { - const ok = { - files: [ - '/x/src/ga/tui/host-ga.tsx', - '/work/antigravity/packages/opencode/src/ga/tui/host-ga.tsx', - '/work/antigravity/packages/opencode/src/common-auth-embedded/quota/codec.js', - ], - externals: ['solid-js'], - } - checkGaGraph(ok, 'source') + const pkgRoot = '/x' + const antigravityPkgRoot = '/work/antigravity/packages/opencode' + checkGaGraph( + { + files: ['/x/src/ga/tui/host-ga.tsx'], + externals: ['solid-js'], + }, + 'source', + pkgRoot, + ) + checkGaGraph( + { + files: [ + '/work/antigravity/packages/opencode/src/ga/tui/host-ga.tsx', + '/work/antigravity/packages/opencode/src/common-auth-embedded/quota/codec.js', + ], + externals: ['solid-js'], + }, + 'source', + antigravityPkgRoot, + ) const refusals: Array< - [Parameters[0], 'source' | 'runtime', string] + [ + Parameters[0], + 'source' | 'runtime', + string, + string | undefined, + ] > = [ [ { files: ['/x/src/rpc/port-file.ts'], externals: [] }, 'source', 'forbidden GA source', + pkgRoot, + ], + [ + { + files: ['/work/antigravity/packages/opencode/src/rpc/port-file.ts'], + externals: [], + }, + 'source', + 'forbidden GA source', + antigravityPkgRoot, + ], + [ + { + files: ['/work/antigravity/packages/opencode/src/plugin/src/storage.ts'], + externals: [], + }, + 'source', + 'forbidden GA source', + antigravityPkgRoot, + ], + [ + { + files: [ + '/work/antigravity/packages/opencode/src/antigravity/src/client.ts', + ], + externals: [], + }, + 'source', + 'forbidden GA source', + antigravityPkgRoot, + ], + [ + { + files: ['/work/other/src/ga/tui/host-ga.tsx'], + externals: [], + }, + 'source', + 'forbidden GA source', + antigravityPkgRoot, ], [ { files: ['/x/src/tui/host-v1.tsx'], externals: [] }, 'source', 'forbidden GA source', + pkgRoot, ], [ { files: ['/x/src/sidebar-state.ts'], externals: [] }, 'source', 'forbidden GA source', + pkgRoot, ], [ { @@ -776,16 +834,19 @@ test('graph.ga_policy_refusals', async () => { }, 'source', 'forbidden GA source', + pkgRoot, ], [ { files: ['/x/src/plugin/storage.ts'], externals: [] }, 'source', 'forbidden GA source', + pkgRoot, ], [ { files: [], externals: ['@opencode-ai/plugin/tui'] }, 'source', 'forbidden GA external', + pkgRoot, ], [ { @@ -794,21 +855,29 @@ test('graph.ga_policy_refusals', async () => { }, 'source', 'forbidden GA external', + pkgRoot, ], [ { files: [], externals: ['@opentui/solid-ga'] }, 'source', 'forbidden GA external', + pkgRoot, + ], + [ + { files: [], externals: ['solid-js'] }, + 'runtime', + 'not a host module', + pkgRoot, ], - [{ files: [], externals: ['solid-js'] }, 'runtime', 'not a host module'], [ { files: [], externals: ['opentui:runtime-module:solid-js-ga'] }, 'runtime', 'not a host module', + pkgRoot, ], ] - for (const [graph, kind, message] of refusals) - expect(() => checkGaGraph(graph, kind)).toThrow(message) + for (const [graph, kind, message, root] of refusals) + expect(() => checkGaGraph(graph, kind, root)).toThrow(message) }) test('build.roots_failure_removes_every_root', async () => { diff --git a/packages/opencode/scripts/build-tui.ts b/packages/opencode/scripts/build-tui.ts index 01f1d403..ca86bbd1 100644 --- a/packages/opencode/scripts/build-tui.ts +++ b/packages/opencode/scripts/build-tui.ts @@ -159,11 +159,19 @@ const RUNTIME_MODULE = 'opentui:runtime-module:' export function checkGaGraph( graph: Graph, emitted: 'source' | 'raw' | 'runtime', + packageRoot: string = PACKAGE_ROOT, ) { for (const path of graph.files) { - const normalized = portable(path) - const srcIndex = normalized.lastIndexOf('/src/') - const candidate = srcIndex >= 0 ? normalized.slice(srcIndex) : normalized + const rel = relative(packageRoot, path) + if ( + rel === '' || + rel === '..' || + rel.startsWith(`..${sep}`) || + rel.startsWith('../') || + isAbsolute(rel) + ) + throw new Error(`graph.ga: forbidden GA source ${path}`) + const candidate = `/${portable(rel)}` if (GA_FORBIDDEN_SOURCE.test(candidate)) throw new Error(`graph.ga: forbidden GA source ${path}`) } @@ -215,6 +223,22 @@ function checkExternal(specifier: string, tui: boolean, types: boolean) { throw new Error(`graph: forbidden TUI external ${specifier}`) } +function findPackageRoot(entry: string): string { + let current = dirname(resolve(entry)) + if (existsSync(current)) { + try { + current = realpathSync(current) + } catch {} + } + while (true) { + if (existsSync(join(current, 'package.json'))) return current + const parent = dirname(current) + if (parent === current) break + current = parent + } + return dirname(resolve(entry)) +} + /** * Independently check imports and re-exports, plus import()/require() targets * expressed as string literals, const aliases or string concatenations. Refuse @@ -222,14 +246,25 @@ function checkExternal(specifier: string, tui: boolean, types: boolean) { */ export async function auditGraph( entry: string, - { tui = true, types = false } = {}, + { + tui = true, + types = false, + packageRoot, + }: { tui?: boolean; types?: boolean; packageRoot?: string } = {}, ): Promise { + const rootDir = packageRoot + ? existsSync(packageRoot) + ? realpathSync(packageRoot) + : resolve(packageRoot) + : findPackageRoot(entry) const files = new Set() const externals = new Set() async function visit(path: string): Promise { path = realpathSync(path) if (files.has(path)) return - const embedded = portable(path).split('/common-auth-embedded/')[1] + const rel = relative(rootDir, path) + const candidate = `/${portable(rel)}` + const embedded = candidate.split('/common-auth-embedded/')[1] if ( embedded && !types && @@ -244,7 +279,7 @@ export async function auditGraph( tui && !types && /(?:\/rpc\/(?:index|rpc-server|server-registry)\.[jt]s$|\/plugin\/(?:storage|accounts|account-manager|account-storage|quota|rotation|logger|debug)\.|\/common-auth-embedded\/(?:fs\/(?!private-files\.js$)|store\/)|\/tools\/)/.test( - portable(path), + candidate, ) ) throw new Error(`graph: forbidden TUI source ${path}`) From b462e79f288823014fdc4b589f59797baa94caaa Mon Sep 17 00:00:00 2001 From: Marcos Santanna <2573094+mv2sa@users.noreply.github.com> Date: Mon, 26 Oct 2026 18:54:37 -0700 Subject: [PATCH 3/4] fix(opencode): forward packageRoot in buildTui and preserve path when root discovery fails --- packages/opencode/scripts/build-tui.ts | 32 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/opencode/scripts/build-tui.ts b/packages/opencode/scripts/build-tui.ts index ca86bbd1..a26f2939 100644 --- a/packages/opencode/scripts/build-tui.ts +++ b/packages/opencode/scripts/build-tui.ts @@ -223,7 +223,7 @@ function checkExternal(specifier: string, tui: boolean, types: boolean) { throw new Error(`graph: forbidden TUI external ${specifier}`) } -function findPackageRoot(entry: string): string { +function findPackageRoot(entry: string): string | undefined { let current = dirname(resolve(entry)) if (existsSync(current)) { try { @@ -236,7 +236,7 @@ function findPackageRoot(entry: string): string { if (parent === current) break current = parent } - return dirname(resolve(entry)) + return undefined } /** @@ -262,8 +262,15 @@ export async function auditGraph( async function visit(path: string): Promise { path = realpathSync(path) if (files.has(path)) return - const rel = relative(rootDir, path) - const candidate = `/${portable(rel)}` + const rel = rootDir !== undefined ? relative(rootDir, path) : undefined + const insideRoot = + rel !== undefined && + rel !== '' && + rel !== '..' && + !rel.startsWith(`..${sep}`) && + !rel.startsWith('../') && + !isAbsolute(rel) + const candidate = insideRoot ? `/${portable(rel)}` : portable(path) const embedded = candidate.split('/common-auth-embedded/')[1] if ( embedded && @@ -633,14 +640,14 @@ export async function buildTui({ verifyPrerequisites(), ) const source = await buildPhase(`buildTui.auditGraph source ${entry}`, () => - auditGraph(join(packageRoot, entry)), + auditGraph(join(packageRoot, entry), { packageRoot }), ) const types = await buildPhase(`buildTui.auditGraph types ${entry}`, () => - auditGraph(join(packageRoot, entry), { types: true }), + auditGraph(join(packageRoot, entry), { types: true, packageRoot }), ) if (ga) { - checkGaGraph(source, 'source') - checkGaGraph(types, 'source') + checkGaGraph(source, 'source', packageRoot) + checkGaGraph(types, 'source', packageRoot) } await buildPhase('buildTui.mkdir dist', () => mkdir(join(packageRoot, 'dist'), { recursive: true }), @@ -693,9 +700,14 @@ export async function buildTui({ if (!file.output.endsWith('/selector.js')) { const emitted = await buildPhase( `buildTui.auditGraph emitted ${file.output}`, - () => auditGraph(join(packageRoot, file.output)), + () => auditGraph(join(packageRoot, file.output), { packageRoot }), ) - if (ga) checkGaGraph(emitted, variant === map.raw ? 'raw' : 'runtime') + if (ga) + checkGaGraph( + emitted, + variant === map.raw ? 'raw' : 'runtime', + packageRoot, + ) } } for (const edge of variant.externals) checkExternal(edge, true, false) From e3bb67fc249b646f9436268bb520677a42378a87 Mon Sep 17 00:00:00 2001 From: Marcos Santanna <2573094+mv2sa@users.noreply.github.com> Date: Mon, 26 Oct 2026 18:57:49 -0700 Subject: [PATCH 4/4] fix(opencode): anchor auditGraph on packageRoot and format with biome --- packages/opencode/scripts/build-tui.test.ts | 4 ++- packages/opencode/scripts/build-tui.ts | 40 +++++---------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/packages/opencode/scripts/build-tui.test.ts b/packages/opencode/scripts/build-tui.test.ts index ffb59f61..8bf036cd 100644 --- a/packages/opencode/scripts/build-tui.test.ts +++ b/packages/opencode/scripts/build-tui.test.ts @@ -788,7 +788,9 @@ test('graph.ga_policy_refusals', async () => { ], [ { - files: ['/work/antigravity/packages/opencode/src/plugin/src/storage.ts'], + files: [ + '/work/antigravity/packages/opencode/src/plugin/src/storage.ts', + ], externals: [], }, 'source', diff --git a/packages/opencode/scripts/build-tui.ts b/packages/opencode/scripts/build-tui.ts index a26f2939..48ff2dd1 100644 --- a/packages/opencode/scripts/build-tui.ts +++ b/packages/opencode/scripts/build-tui.ts @@ -223,22 +223,6 @@ function checkExternal(specifier: string, tui: boolean, types: boolean) { throw new Error(`graph: forbidden TUI external ${specifier}`) } -function findPackageRoot(entry: string): string | undefined { - let current = dirname(resolve(entry)) - if (existsSync(current)) { - try { - current = realpathSync(current) - } catch {} - } - while (true) { - if (existsSync(join(current, 'package.json'))) return current - const parent = dirname(current) - if (parent === current) break - current = parent - } - return undefined -} - /** * Independently check imports and re-exports, plus import()/require() targets * expressed as string literals, const aliases or string concatenations. Refuse @@ -249,28 +233,20 @@ export async function auditGraph( { tui = true, types = false, - packageRoot, + packageRoot = PACKAGE_ROOT, }: { tui?: boolean; types?: boolean; packageRoot?: string } = {}, ): Promise { - const rootDir = packageRoot - ? existsSync(packageRoot) - ? realpathSync(packageRoot) - : resolve(packageRoot) - : findPackageRoot(entry) + const rootDir = existsSync(packageRoot) + ? realpathSync(packageRoot) + : resolve(packageRoot) const files = new Set() const externals = new Set() async function visit(path: string): Promise { path = realpathSync(path) if (files.has(path)) return - const rel = rootDir !== undefined ? relative(rootDir, path) : undefined - const insideRoot = - rel !== undefined && - rel !== '' && - rel !== '..' && - !rel.startsWith(`..${sep}`) && - !rel.startsWith('../') && - !isAbsolute(rel) - const candidate = insideRoot ? `/${portable(rel)}` : portable(path) + const candidate = isInsideDirectory(rootDir, path) + ? `/${portable(relative(rootDir, path))}` + : portable(path) const embedded = candidate.split('/common-auth-embedded/')[1] if ( embedded && @@ -586,7 +562,7 @@ export async function verifySelectors( ) const graph = await buildPhase( `selectors.auditGraph ${tree}/${entry}`, - () => auditGraph(join(packageRoot, tree, entry)), + () => auditGraph(join(packageRoot, tree, entry), { packageRoot }), ) if (graph.files.some((path) => path.endsWith('/selector.js'))) throw new Error('build.selector_inert: imported selector copy')