Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# GG Circuit agent guide

## Repository shape

GG Circuit is a pnpm and Cargo monorepo containing a React/TypeScript frontend and a Tauri/Rust backend.

- Frontend: `apps/desktop/src`
- Tauri application: `apps/desktop/src-tauri`
- Reusable Rust crates: `crates/gg-*`
- Runtime and developer helpers: `scripts`

Use Node.js 24, pnpm 10.12.1, and the Rust toolchain pinned in `rust-toolchain.toml`.

## Codex environment

For Codex cloud, configure:

- Setup script: `bash scripts/codex-setup.sh`
- Maintenance script: `bash scripts/codex-setup.sh --maintenance`

The setup installs the Linux dependencies required by Tauri, installs locked pnpm and Cargo dependencies, fetches the bundled Python runtime used by the application, builds the frontend, and precompiles the Rust tests.

Do not skip the root `pnpm install` postinstall step: it populates `apps/desktop/src-tauri/runtime`, which is intentionally not committed.

## Validation

Use locked dependency resolution. Do not run `pnpm test`; this repository does not currently define a JavaScript test script.

For frontend-only changes, run:

```sh
pnpm format:check
pnpm --filter @gg/desktop lint
pnpm --filter @gg/desktop build
```

For Rust changes, first ensure `apps/desktop/dist` exists because `tauri::generate_context!` embeds the frontend output, then run:

```sh
pnpm --filter @gg/desktop build
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
```

For cross-stack, dependency, build-system, or release changes, run the complete suite:

```sh
bash scripts/codex-setup.sh --verify
```

When only documentation changes, run Prettier against the changed Markdown files at minimum.

## Generated and downloaded content

Do not commit generated or downloaded directories such as:

- `node_modules`
- `apps/desktop/dist`
- `target`
- `apps/desktop/src-tauri/runtime`

Do not hand-edit lockfiles unless a dependency change requires it. Keep `package.json`, `pnpm-lock.yaml`, `Cargo.toml`, and `Cargo.lock` synchronized.

## Change discipline

- Keep frontend service calls and matching Tauri commands consistent across the TypeScript/Rust boundary.
- Put durable backend behavior in the relevant `crates/gg-*` crate rather than directly in a Tauri command wrapper.
- Add or update Rust tests near the affected crate behavior.
- Prefer the smallest relevant validation set while iterating, then run the required final checks before reporting completion.
- Report every command run and any check that could not be executed.
206 changes: 206 additions & 0 deletions scripts/codex-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#!/usr/bin/env bash
# Prepare the GG Circuit monorepo for OpenAI Codex cloud tasks.
#
# Codex environment settings:
# Setup script: bash scripts/codex-setup.sh
# Maintenance script: bash scripts/codex-setup.sh --maintenance
#
# The setup phase has internet access, so this script installs the Linux/Tauri
# build prerequisites, pins the toolchains used by CI, installs locked project
# dependencies, fetches the bundled Python runtime, and warms the build caches.
set -Eeuo pipefail

MODE="setup"
case "${1:-}" in
"") ;;
--maintenance) MODE="maintenance" ;;
--verify) MODE="verify" ;;
*)
echo "Usage: $0 [--maintenance|--verify]" >&2
exit 2
;;
esac

log() {
printf '\n[codex-setup] %s\n' "$*"
}

fail() {
printf '\n[codex-setup] ERROR: %s\n' "$*" >&2
exit 1
}

run_as_root() {
if [[ "${EUID}" -eq 0 ]]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
fail "Root privileges are required to install system packages, but sudo is unavailable."
fi
}

append_once() {
local line="$1"
local file="$2"
mkdir -p "$(dirname "$file")"
touch "$file"
grep -Fqx "$line" "$file" || printf '%s\n' "$line" >> "$file"
}

REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$REPO_ROOT"

NODE_MAJOR=24
PNPM_VERSION=10.12.1
RUST_TOOLCHAIN=1.96.0

install_system_dependencies() {
if ! command -v apt-get >/dev/null 2>&1; then
fail "This setup script currently supports the Ubuntu/Debian Codex cloud image (apt-get required)."
fi

log "Installing Tauri and native build dependencies"
run_as_root apt-get update
run_as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
cmake \
curl \
file \
libayatana-appindicator3-dev \
librsvg2-dev \
libssl-dev \
libwebkit2gtk-4.1-dev \
libxdo-dev \
pkg-config \
wget
}

load_nvm() {
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [[ -s "$NVM_DIR/nvm.sh" ]]; then
# shellcheck disable=SC1090
source "$NVM_DIR/nvm.sh"
return 0
fi
return 1
}

ensure_node() {
local actual_major=""
if command -v node >/dev/null 2>&1; then
actual_major="$(node -p 'process.versions.node.split(".")[0]')"
fi

if [[ "$actual_major" == "$NODE_MAJOR" ]]; then
log "Node.js $(node --version) already matches CI"
return
fi

log "Selecting Node.js ${NODE_MAJOR}"
if load_nvm; then
nvm install "$NODE_MAJOR"
nvm alias default "$NODE_MAJOR"
nvm use "$NODE_MAJOR"
elif command -v mise >/dev/null 2>&1; then
mise install "node@${NODE_MAJOR}"
mise use --global "node@${NODE_MAJOR}"
eval "$(mise activate bash)"
append_once 'eval "$(mise activate bash)"' "$HOME/.bashrc"
else
fail "Node.js ${NODE_MAJOR} is required. In Codex environment settings, set the Node.js package version to ${NODE_MAJOR}."
fi

actual_major="$(node -p 'process.versions.node.split(".")[0]')"
[[ "$actual_major" == "$NODE_MAJOR" ]] || fail "Expected Node.js ${NODE_MAJOR}, found $(node --version)."
}

ensure_pnpm() {
local actual=""
if command -v pnpm >/dev/null 2>&1; then
actual="$(pnpm --version)"
fi

if [[ "$actual" == "$PNPM_VERSION" ]]; then
log "pnpm ${PNPM_VERSION} already available"
return
fi

log "Installing pnpm ${PNPM_VERSION}"
if command -v corepack >/dev/null 2>&1; then
corepack enable
corepack prepare "pnpm@${PNPM_VERSION}" --activate
else
mkdir -p "$HOME/.local"
npm install --global --prefix "$HOME/.local" "pnpm@${PNPM_VERSION}"
export PATH="$HOME/.local/bin:$PATH"
append_once 'export PATH="$HOME/.local/bin:$PATH"' "$HOME/.bashrc"
fi

[[ "$(pnpm --version)" == "$PNPM_VERSION" ]] || fail "Could not activate pnpm ${PNPM_VERSION}."
}

ensure_rust() {
if ! command -v rustup >/dev/null 2>&1; then
fail "rustup is required. In Codex environment settings, enable a Rust package version or use the universal image."
fi

log "Installing Rust ${RUST_TOOLCHAIN} with clippy and rustfmt"
rustup toolchain install "$RUST_TOOLCHAIN" \
--profile minimal \
--component clippy \
--component rustfmt

cargo "+${RUST_TOOLCHAIN}" --version
rustc "+${RUST_TOOLCHAIN}" --version
}

install_project_dependencies() {
log "Installing locked JavaScript dependencies and bundled Python runtime"
CI=1 HUSKY=0 pnpm install --frozen-lockfile

log "Fetching locked Rust dependencies"
cargo "+${RUST_TOOLCHAIN}" fetch --locked
}

warm_build_caches() {
# tauri::generate_context! embeds apps/desktop/dist during Rust compilation.
log "Building the desktop frontend required by the Tauri crate"
pnpm --filter @gg/desktop build

log "Compiling Rust tests without running them"
cargo "+${RUST_TOOLCHAIN}" test --workspace --locked --no-run
}

run_verification() {
log "Running the full repository verification suite"
pnpm format:check
pnpm --filter @gg/desktop lint
pnpm --filter @gg/desktop build
cargo "+${RUST_TOOLCHAIN}" fmt --all --check
cargo "+${RUST_TOOLCHAIN}" clippy --workspace --all-targets --locked -- -D warnings
cargo "+${RUST_TOOLCHAIN}" test --workspace --locked
}

if [[ "$MODE" != "maintenance" ]]; then
install_system_dependencies
Comment on lines +186 to +187

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid provisioning during verify mode

When --verify is used as the AGENTS.md “complete suite” after the Codex setup phase, this condition still runs install_system_dependencies, starting with apt-get update, before any checks execute. In cached task environments where package downloads are unavailable or sudo/root is not usable, verification fails even though the environment was already prepared; verify should skip provisioning like maintenance or split the check-only path from setup.

Useful? React with 👍 / 👎.

fi

ensure_node
ensure_pnpm
ensure_rust
install_project_dependencies
warm_build_caches

if [[ "$MODE" == "verify" ]]; then
run_verification
fi

log "Environment ready"
printf '%s\n' \
"Node: $(node --version)" \
"pnpm: $(pnpm --version)" \
"Rust: $(rustc +${RUST_TOOLCHAIN} --version)" \
"Python runtime: apps/desktop/src-tauri/runtime/python/bin/python3" \
"Run all checks: bash scripts/codex-setup.sh --verify"