fix(setup): ship supabase/config.sh with every host runtime root

Distinct from the lib/-beside-bin/ defect: gstack-telemetry-sync,
gstack-update-check, gstack-security-dashboard and
gstack-community-dashboard all source $GSTACK_DIR/supabase/config.sh to
resolve GSTACK_SUPABASE_URL, where GSTACK_DIR is the installed root
(parent of bin/). The [ -f ... ] guard means a root without the file
degrades SILENTLY — telemetry and update checks just stop resolving the
project URL on non-Claude installs. Closes #2215.

setup now links supabase/config.sh (file-level on purpose — migrations/
and functions/ are dev-only) via _link_or_copy at all five host-install
sites: the PR's four (Codex, Factory, OpenCode runtime roots + the Kiro
block) plus the .agents sidecar, whose bin/ resolves the same relative
path and which the PR predates covering.

The runtime-root test now asserts supabase/config.sh is present in
every built root, on both the symlink and Windows-copy branches.

Contributed by @jizusun (PR #2216).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan 2026-08-14 19:19:46 -07:00
parent b57c898dfb
commit d10aa39408
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
2 changed files with 36 additions and 1 deletions

27
setup
View File

@ -780,6 +780,13 @@ create_agents_sidecar() {
fi
fi
done
# supabase/config.sh — required by gstack-telemetry-sync to resolve GSTACK_SUPABASE_URL
# (file-level on purpose: migrations/ and functions/ are dev-only)
if [ -f "$SOURCE_GSTACK_DIR/supabase/config.sh" ]; then
mkdir -p "$agents_gstack/supabase"
_link_or_copy "$SOURCE_GSTACK_DIR/supabase/config.sh" "$agents_gstack/supabase/config.sh"
fi
}
# ─── Helper: create a minimal ~/.codex/skills/gstack runtime root ───────────
@ -829,6 +836,11 @@ create_codex_runtime_root() {
if [ -f "$gstack_dir/ETHOS.md" ]; then
_link_or_copy "$gstack_dir/ETHOS.md" "$codex_gstack/ETHOS.md"
fi
# supabase/config.sh — required by gstack-telemetry-sync to resolve GSTACK_SUPABASE_URL
if [ -f "$gstack_dir/supabase/config.sh" ]; then
mkdir -p "$codex_gstack/supabase"
_link_or_copy "$gstack_dir/supabase/config.sh" "$codex_gstack/supabase/config.sh"
fi
}
create_factory_runtime_root() {
@ -870,6 +882,11 @@ create_factory_runtime_root() {
if [ -f "$gstack_dir/ETHOS.md" ]; then
_link_or_copy "$gstack_dir/ETHOS.md" "$factory_gstack/ETHOS.md"
fi
# supabase/config.sh — required by gstack-telemetry-sync to resolve GSTACK_SUPABASE_URL
if [ -f "$gstack_dir/supabase/config.sh" ]; then
mkdir -p "$factory_gstack/supabase"
_link_or_copy "$gstack_dir/supabase/config.sh" "$factory_gstack/supabase/config.sh"
fi
}
create_opencode_runtime_root() {
@ -926,6 +943,11 @@ create_opencode_runtime_root() {
if [ -f "$gstack_dir/ETHOS.md" ]; then
_link_or_copy "$gstack_dir/ETHOS.md" "$opencode_gstack/ETHOS.md"
fi
# supabase/config.sh — required by gstack-telemetry-sync to resolve GSTACK_SUPABASE_URL
if [ -f "$gstack_dir/supabase/config.sh" ]; then
mkdir -p "$opencode_gstack/supabase"
_link_or_copy "$gstack_dir/supabase/config.sh" "$opencode_gstack/supabase/config.sh"
fi
}
link_factory_skill_dirs() {
@ -1142,6 +1164,11 @@ if [ "$INSTALL_KIRO" -eq 1 ]; then
if [ -f "$SOURCE_GSTACK_DIR/ETHOS.md" ]; then
_link_or_copy "$SOURCE_GSTACK_DIR/ETHOS.md" "$KIRO_GSTACK/ETHOS.md"
fi
# supabase/config.sh — required by gstack-telemetry-sync to resolve GSTACK_SUPABASE_URL
if [ -f "$SOURCE_GSTACK_DIR/supabase/config.sh" ]; then
mkdir -p "$KIRO_GSTACK/supabase"
_link_or_copy "$SOURCE_GSTACK_DIR/supabase/config.sh" "$KIRO_GSTACK/supabase/config.sh"
fi
# gstack-upgrade skill
if [ -f "$AGENTS_DIR/gstack-upgrade/SKILL.md" ]; then
_link_or_copy "$AGENTS_DIR/gstack-upgrade/SKILL.md" "$KIRO_GSTACK/gstack-upgrade/SKILL.md"

View File

@ -34,7 +34,7 @@ function extractFunction(name: string): string {
// a complete statement list.
function extractKiroBlock(): string {
const startAnchor = 'KIRO_GSTACK="$KIRO_SKILLS/gstack"';
const endAnchor = '_link_or_copy "$SOURCE_GSTACK_DIR/browse/bin" "$KIRO_GSTACK/browse/bin"';
const endAnchor = '_link_or_copy "$SOURCE_GSTACK_DIR/supabase/config.sh" "$KIRO_GSTACK/supabase/config.sh"\n fi';
const start = SETUP_SRC.indexOf(startAnchor);
const end = SETUP_SRC.indexOf(endAnchor, start);
if (start < 0 || end < 0) throw new Error('Could not locate the Kiro install block in setup');
@ -48,6 +48,7 @@ interface CommandResult {
runStderr: string;
learningsWritten: boolean;
libIsSymlink: boolean | null;
supabaseConfigPresent: boolean;
}
// Build one host runtime root inside a sandbox using the real setup shell code
@ -93,6 +94,11 @@ function buildRootAndRunCommand(
runStderr: run.stderr,
learningsWritten,
libIsSymlink: libLst ? libLst.isSymbolicLink() : null,
// Distinct defect (#2215): telemetry-class bin scripts source
// $GSTACK_DIR/supabase/config.sh to resolve GSTACK_SUPABASE_URL. The
// [ -f ... ] guard means a missing file degrades SILENTLY, so only a
// presence check on the installed root catches it.
supabaseConfigPresent: fs.existsSync(path.join(rootDir, 'supabase', 'config.sh')),
};
} finally {
fs.rmSync(sandbox, { recursive: true, force: true });
@ -158,6 +164,7 @@ describe.skipIf(process.platform === 'win32')('setup: bin commands resolve sibli
expect(r.runStderr).not.toContain('lib/jsonl-store.ts');
expect(r.runStatus).toBe(0);
expect(r.learningsWritten).toBe(true);
expect(r.supabaseConfigPresent).toBe(true);
});
test(`${host} root (Windows copy install): gstack-learnings-log imports ../lib and writes the learning`, () => {
@ -168,6 +175,7 @@ describe.skipIf(process.platform === 'win32')('setup: bin commands resolve sibli
expect(r.runStderr).not.toContain('lib/jsonl-store.ts');
expect(r.runStatus).toBe(0);
expect(r.learningsWritten).toBe(true);
expect(r.supabaseConfigPresent).toBe(true);
});
}