diff --git a/.agents/resume b/.agents/resume new file mode 100755 index 0000000..41680ce --- /dev/null +++ b/.agents/resume @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# +# Orb resume for idx-cli. +# +# The repository has no services and no private registries, so nothing here +# needs credentials. This verifies quickly that the snapshot's toolchain is +# still usable after a pause, and restores the Nix flake config if it vanished. +# Keep it fast: Amp waits at most 10 seconds. +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +nix_bin="$HOME/.nix-profile/bin/nix" +nix_conf="$HOME/.config/nix/nix.conf" +log="$HOME/.cache/amp/logs/resume-detail.log" + +mkdir -p "$(dirname "$log")" +log_line() { printf '%s idx-cli resume: %s\n' "$(date -Is)" "$*" >>"$log"; } + +fail() { + log_line "FAILED: $*" + printf 'idx-cli orb: %s\nRepair it with %s/.agents/setup\n' "$*" "$repo_root" >&2 + exit 1 +} + +if [ ! -x "$nix_bin" ]; then + fail "Nix is not installed" +fi + +if ! grep -qE '^[[:space:]]*experimental-features[[:space:]]*=.*nix-command' "$nix_conf" 2>/dev/null; then + mkdir -p "$(dirname "$nix_conf")" + printf 'experimental-features = nix-command flakes\n' >>"$nix_conf" + log_line "restored $nix_conf" +fi + +# The toolchain has to be on PATH in a clean login shell: that is the +# environment Amp's executor and supervised orb services inherit. +if ! env -i HOME="$HOME" USER="${USER:-user}" PATH=/usr/bin:/bin /bin/bash -lc 'command -v cargo >/dev/null 2>&1'; then + fail "cargo is not on PATH in a clean login shell" +fi + +log_line "ok" diff --git a/.agents/setup b/.agents/setup new file mode 100755 index 0000000..7d7cee5 --- /dev/null +++ b/.agents/setup @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +# +# Orb setup for idx-cli. +# +# A fresh orb has no Rust toolchain and no Nix, while the repository builds and +# verifies through its flake dev shell (`nix develop`). This script installs Nix +# (single-user), realizes the dev shell, makes that environment available to the +# login shells Amp and orb services start, and warms the Cargo build so the +# first agent command is incremental. +# +# Idempotent by design: an orb restored from a stale snapshot re-runs this and +# keeps /nix, ~/.cargo, and target/ instead of rebuilding them. +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +nix_profile="$HOME/.nix-profile" +nix_bin="$nix_profile/bin/nix" +nix_conf="$HOME/.config/nix/nix.conf" +bash_profile="$HOME/.bash_profile" +agent_guidance="$HOME/.config/amp/AGENTS.md" +profile_marker="# idx-cli orb dev shell (managed by .agents/setup)" +guidance_marker="" + +step() { printf '\n==> %s\n' "$*"; } + +# Runs "$@" with timing so setup.log shows which step is slow or failing. +run() { + local label="$1" + shift + local start=$SECONDS + if "$@"; then + printf ' ok: %s (%ss)\n' "$label" "$((SECONDS - start))" + return 0 + fi + local status=$? + printf ' FAILED: %s (%ss, exit %s)\n' "$label" "$((SECONDS - start))" "$status" >&2 + return "$status" +} + +# Warm-up work whose failure should not stop snapshot publication. +run_warn() { + if ! run "$@"; then + printf 'warning: %s failed; rerun .agents/setup once the cause is fixed\n' "$1" >&2 + fi +} + +step "Nix package manager" +if [ -x "$nix_bin" ]; then + printf ' ok: already installed (%s)\n' "$("$nix_bin" --version)" +else + installer="$(mktemp)" + curl -fsSL https://nixos.org/nix/install -o "$installer" + run "install nix (single-user)" sh "$installer" --no-daemon --no-modify-profile --yes + rm -f "$installer" +fi + +# The installer cannot update the environment of this already-running script. +# shellcheck source=/dev/null +if [ -f "$nix_profile/etc/profile.d/nix.sh" ]; then + . "$nix_profile/etc/profile.d/nix.sh" +fi + +step "Nix flake support" +mkdir -p "$(dirname "$nix_conf")" +touch "$nix_conf" +if ! grep -qE '^[[:space:]]*experimental-features[[:space:]]*=.*nix-command' "$nix_conf"; then + printf 'experimental-features = nix-command flakes\n' >>"$nix_conf" +fi +if ! grep -qE '^[[:space:]]*warn-dirty[[:space:]]*=' "$nix_conf"; then + printf 'warn-dirty = false\n' >>"$nix_conf" +fi +printf ' ok: %s\n' "$nix_conf" + +step "Flake dev shell" +run "realize dev shell" "$nix_bin" develop --command true + +step "Warm Cargo build (kept in the snapshot for the first agent command)" +run_warn "cargo build --locked" "$nix_bin" develop --command bash -c 'cargo build --locked' +run_warn "cargo test --no-run --locked" "$nix_bin" develop --command bash -c 'cargo test --no-run --locked' +run_warn "cargo clippy --locked -- -D warnings" "$nix_bin" develop --command bash -c 'cargo clippy --locked -- -D warnings' + +step "Login shell environment" +# Amp starts its login shells (the headless executor and orb services) from /, +# so activate the dev shell by repository path instead of by $PWD. The +# IN_NIX_SHELL guard keeps nested shells and `nix develop` itself cheap. +profile_hook() { + cat </dev/null; then + printf ' ok: dev shell hook already present in %s\n' "$bash_profile" +else + printf '\n' >>"$bash_profile" + profile_hook >>"$bash_profile" + printf ' ok: added dev shell hook to %s\n' "$bash_profile" +fi + +step "Orb guidance for agents" +mkdir -p "$(dirname "$agent_guidance")" +if grep -Fq "$guidance_marker" "$agent_guidance" 2>/dev/null; then + printf ' ok: guidance already present in %s\n' "$agent_guidance" +else + cat >>"$agent_guidance" <&2 + exit 1 +fi diff --git a/.gitignore b/.gitignore index e5145bc..877d6f4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ docs-internal/ # Large research data files research/ +# Amp orb runtime files +.amp/portals/ # Added by cargo