feat: integrate antigravity-cli support into installer scripts and fix test suite hangs#59
feat: integrate antigravity-cli support into installer scripts and fix test suite hangs#59dpolishuk wants to merge 4 commits into
Conversation
…x test suite hangs
|
Warning Review limit reached
Your plan includes 1 review of capacity. Refill in 26 minutes and 30 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe pull request adds Antigravity CLI ( ChangesAntigravity CLI Agent Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR adds first-class Antigravity CLI (agy) host support to both installer entrypoints (scripts/install.sh and scripts/install.ts) and updates the installer test suite to avoid hangs and improve macOS bash compatibility.
Changes:
- Add
antigravityhost detection/install/status/validate/uninstall support (shell + Bun installers) and include it in Graphify/claude-mem host targeting. - Update installer execution paths and help text to recognize
antigravityas a supported host. - Harden tests by providing a modern
bashin PATH and mockingnpm/npxto prevent network-bound hangs.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/install-script.test.js | Adds PATH shims (bash/npm/npx) and adjusts spawn behavior to prevent macOS bash issues and test hangs. |
| scripts/install.ts | Adds antigravity host configuration and extends Graphify/claude-mem targeting and help text. |
| scripts/install.sh | Adds antigravity integration and expands Graphify/claude-mem agent targeting and status/validate/uninstall flows. |
| bun.lock | Updates Bun lockfile to reflect current dependency graph. |
| .beads/issues.jsonl | Adds Antigravity installer integration tracking issues/spec text. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (env.PATH) { | ||
| const parts = env.PATH.split(path.delimiter) | ||
| const firstPart = parts[0] | ||
| if (firstPart && fs.existsSync(firstPart)) { | ||
| const bashSymlink = path.join(firstPart, "bash") | ||
| if (!fs.existsSync(bashSymlink)) { | ||
| try { | ||
| const bashPath = findExecutable("bash") || "/bin/bash" | ||
| fs.symlinkSync(bashPath, bashSymlink) | ||
| } catch (e) { | ||
| // Ignore errors | ||
| } | ||
| } | ||
| const npmMock = path.join(firstPart, "npm") | ||
| if (!fs.existsSync(npmMock)) { | ||
| try { | ||
| fs.writeFileSync(npmMock, "#!/usr/bin/env bash\nexit 0\n", "utf8") | ||
| fs.chmodSync(npmMock, 0o755) | ||
| } catch (e) { | ||
| // Ignore errors | ||
| } | ||
| } | ||
| const npxMock = path.join(firstPart, "npx") | ||
| if (!fs.existsSync(npxMock)) { | ||
| try { | ||
| fs.writeFileSync(npxMock, "#!/usr/bin/env bash\nexit 0\n", "utf8") | ||
| fs.chmodSync(npxMock, 0o755) | ||
| } catch (e) { | ||
| // Ignore errors | ||
| } | ||
| } | ||
| } | ||
| } |
| detect_antigravity() { | ||
| if command -v agy &>/dev/null; then | ||
| # Verify it is our Antigravity CLI (v1.0.x) | ||
| local ver | ||
| if ver=$(timeout 2s agy --version 2>/dev/null); then |
| local agy_stderr | ||
| if [[ "$USE_SYMLINKS" == true ]]; then | ||
| # agy doesn't have a direct 'link' for local plugins that works like 'extensions link' | ||
| # but we can import it. | ||
| agy_stderr=$(timeout 10s agy plugin import "$ext_dir" 2>&1) || { | ||
| error "agy plugin import failed: ${agy_stderr}" | ||
| return 1 | ||
| } | ||
| else | ||
| agy_stderr=$(timeout 10s agy plugin import "$ext_dir" 2>&1) || { | ||
| error "agy plugin import failed: ${agy_stderr}" | ||
| return 1 | ||
| } | ||
| fi |
| {"id":"bd-4j3","title":"Feature: Hyperpowers OpenCode bundle + beads triage","description":"## Requirements (IMMUTABLE)\n- Hyperpowers installs via git clone to `~/.config/opencode/hyperpowers` with plugin symlink, matching Superpowers pattern.\n- OpenCode auto-discovers from plural directories: `.opencode/commands`, `.opencode/agents`, `.opencode/plugins`, `.opencode/skills` (no singular dirs remaining).\n- Add `/beads-triage` command and `beads-triage` skill in OpenCode bundle.\n- `beads-triage` runs `bv --robot-triage` directly; if `bv` is missing, it installs via the official install script and retries.\n- `beads-triage` accepts optional scope args (label/track/etc.) and passes them through to `bv --robot-triage`.\n- Skill output is raw JSON only (no summary).\n- Installation docs explain bundle layout, plugin symlink, and `beads-triage` usage.\n\n## Success Criteria (MUST ALL BE TRUE)\n- [ ] OpenCode discovers commands, agents, skills, and plugin from plural `.opencode/*` directories.\n- [ ] `/beads-triage` runs `bv --robot-triage` and returns raw JSON.\n- [ ] Missing `bv` triggers automated install before running triage.\n- [ ] Optional scope args are passed to `bv --robot-triage`.\n- [ ] Installation docs updated with new bundle layout and triage instructions.\n- [ ] No singular `.opencode/command`, `.opencode/agent`, `.opencode/plugin` directories remain.\n\n## Anti-Patterns (FORBIDDEN)\n- ❌ Running bare `bv` (must always use `--robot-triage` to avoid TUI blocking).\n- ❌ Summarizing triage output (raw JSON only).\n- ❌ Prompting user to manually run `bv --robot-triage` (skill must run it directly).\n- ❌ Keeping singular `.opencode/command`, `.opencode/agent`, `.opencode/plugin` directories.\n\n## Approach\nAdopt the Superpowers-style local bundle: clone to `~/.config/opencode/hyperpowers` and symlink the plugin into `~/.config/opencode/plugins/`. Migrate `.opencode` directories to plural names so OpenCode auto-discovers commands, agents, plugins, and skills. Add a `beads-triage` skill and `/beads-triage` command that executes `bv --robot-triage` with optional args; if `bv` is missing, install using the official script before executing. Update installation docs to explain the bundle layout and triage usage.\n\n## Architecture\n- `.opencode/skills/beads-triage/SKILL.md` - New skill driving `bv --robot-triage` behavior\n- `.opencode/commands/beads-triage.md` - Command wrapper for the skill\n- `.opencode/plugins/hyperpowers-skills.ts` - Plugin for `use_skill`/`find_skills` tools and bootstrap injection\n- `.opencode/INSTALL.md` - Updated installation docs\n\n## Design Rationale\n### Problem\nHyperpowers needs a one-step OpenCode installation that bundles commands, agents, hooks, and skills, plus actionable bv graph analysis via bd integration.\n\n### Research Findings\n**Codebase:**\n- `.opencode/command`, `.opencode/agent`, `.opencode/plugin` exist today (singular) and should be migrated to plural for OpenCode auto-discovery.\n- `hyperpowers-skills.ts` already provides `use_skill`/`find_skills` tool behavior.\n\n**External:**\n- OpenCode docs confirm auto-discovery from plural `.opencode/commands`, `.opencode/agents`, `.opencode/plugins`, `.opencode/skills`.\n- `bv --robot-triage` provides JSON output and is the safe non-TUI entry point.\n- `bv` official install uses a curl-based install script.\n\n### Approaches Considered\n1. **Local bundle with plural `.opencode/*` (Chosen)**\n - Pros: Matches Superpowers pattern; zero npm packaging complexity; OpenCode auto-discovery works.\n - Cons: Requires git clone + symlink step.\n - **Chosen because:** Aligns with OpenCode discovery and existing hyperpowers skill tooling.\n\n2. **Hybrid bundle + npm plugin**\n - Pros: Smaller local footprint.\n - Cons: Two install methods; more moving parts.\n - **Rejected because:** Adds complexity with little benefit.\n\n3. **Npm-only plugin**\n - Pros: Single install command.\n - Cons: OpenCode doesn’t auto-discover skills/commands from npm packages.\n - **Rejected because:** Not supported by OpenCode.\n\n### Scope Boundaries\n**In scope:**\n- Bundle layout migration to plural `.opencode/*`\n- New `beads-triage` skill + command\n- Updated installation docs\n\n**Out of scope (deferred/never):**\n- Additional bv robot modes (insights/graph) beyond triage\n- CLI wrappers outside OpenCode\n\n### Open Questions\n- None","status":"closed","priority":2,"issue_type":"epic","owner":"dmitry.polishuk@gmail.com","created_at":"2026-01-20T14:06:03.637086+03:00","created_by":"Dmitry Polishuk","updated_at":"2026-01-20T14:42:39.95947+03:00","closed_at":"2026-01-20T14:42:39.95947+03:00","close_reason":"All tasks completed; implementation reviewed and approved."} | ||
| {"id":"bd-4lt","title":"Convert executing-plans to Flow skill","description":"Convert executing-plans skill to Kimi CLI Flow format.\n\nPlan execution workflow:\n1. Load next ready task from bd\n2. Execute task\n3. Review learnings\n4. Update/create follow-up tasks\n5. Stop for user review (or continue in Ralph mode)\n\n```mermaid\nflowchart TD\n BEGIN[Start Execution] --\u003e READY[bd ready - get next task]\n READY --\u003e HAS_TASK{Task available?}\n HAS_TASK --\u003e|No| END[All tasks complete]\n HAS_TASK --\u003e|Yes| CLAIM[Mark in_progress]\n CLAIM --\u003e EXECUTE[Execute task]\n EXECUTE --\u003e VERIFY[Verify completion]\n VERIFY --\u003e PASSED{Verification passed?}\n PASSED --\u003e|No| FIX[Fix issues]\n FIX --\u003e VERIFY\n PASSED --\u003e|Yes| LEARNINGS[Document learnings]\n LEARNINGS --\u003e UPDATE[Update bd task]\n UPDATE --\u003e CLOSE[Close task]\n CLOSE --\u003e CHECKPOINT{User checkpoint?}\n CHECKPOINT --\u003e|Yes| PAUSE[Wait for user]\n PAUSE --\u003e READY\n CHECKPOINT --\u003e|No| READY\n```\n\n## Acceptance Criteria\n- [ ] type: flow in frontmatter\n- [ ] Task execution loop as Mermaid flowchart\n- [ ] bd integration points shown\n- [ ] User checkpoint decision node","status":"closed","priority":2,"issue_type":"task","owner":"dmitry.polishuk@gmail.com","created_at":"2026-02-01T20:27:42.242455611+02:00","created_by":"Dmitry Polishuk","updated_at":"2026-02-01T20:39:52.605836715+02:00","closed_at":"2026-02-01T20:39:52.605836715+02:00","close_reason":"Converted to Flow skill with Mermaid flowchart","dependencies":[{"issue_id":"bd-4lt","depends_on_id":"bd-n1c","type":"blocks","created_at":"2026-02-01T20:31:05.098994075+02:00","created_by":"Dmitry Polishuk"},{"issue_id":"bd-4lt","depends_on_id":"bd-o7a","type":"parent-child","created_at":"2026-02-01T20:31:15.495663858+02:00","created_by":"Dmitry Polishuk"}]} | ||
| {"id":"bd-5","title":"Phase 4: PostToolUse Hook (Context Tracker)","design":"## Goal\nImplement hook that tracks file edits and maintains context.\n\n## Effort Estimate\n8-10 hours\n\n## Success Criteria\n- [ ] PostToolUse hook created and configured in hooks.json\n- [ ] Hook tracks Edit and Write tool usage\n- [ ] Context logged with: timestamp, repo, file_path, tool_name\n- [ ] Log stored in hooks/context/edit-log.txt\n- [ ] Log rotation prevents unbounded growth (max 1000 lines)\n- [ ] Non-blocking operation (always returns success)\n- [ ] Hook handles missing/malformed input gracefully\n- [ ] Manual testing shows correct logging of file edits\n- [ ] Context accessible to downstream hooks (bd-6)\n- [ ] Race condition prevention via file locking\n\n## Implementation Steps (ADDED BY writing-plans, REFINED BY SRE)\n\n### Step Group 1: Create Context Storage Infrastructure\n\n**Files:**\n- Create: hooks/context/ (directory)\n- Create: hooks/post-tool-use/01-track-edits.sh\n- Modify: hooks/hooks.json\n\n**Step 1: Create directories**\nRun:\n\\`\\`\\`bash\nmkdir -p hooks/post-tool-use hooks/context\n\\`\\`\\`\n\n**Step 2: Create the edit tracker script**\n\nCreate \\`hooks/post-tool-use/01-track-edits.sh\\`:\n\n\\`\\`\\`bash\n#!/usr/bin/env bash\nset -euo pipefail\n\n# Configuration\nCONTEXT_DIR=\"$(dirname \"$0\")/../context\"\nLOG_FILE=\"$CONTEXT_DIR/edit-log.txt\"\nLOCK_FILE=\"$CONTEXT_DIR/.edit-log.lock\"\nMAX_LOG_LINES=1000\nLOCK_TIMEOUT=5\n\n# Create context dir and log if doesn't exist\nmkdir -p \"$CONTEXT_DIR\"\ntouch \"$LOG_FILE\"\n\n# Acquire lock with timeout\nacquire_lock() {\n local count=0\n while [ $count -lt $LOCK_TIMEOUT ]; do\n if mkdir \"$LOCK_FILE\" 2\u003e/dev/null; then\n return 0\n fi\n sleep 0.2\n count=$((count + 1))\n done\n # Log but don't fail - non-blocking requirement\n echo \"Warning: Could not acquire lock\" \u003e\u00262\n return 1\n}\n\n# Release lock\nrelease_lock() {\n rmdir \"$LOCK_FILE\" 2\u003e/dev/null || true\n}\n\n# Clean up lock on exit\ntrap release_lock EXIT\n\n# Function to log edit\nlog_edit() {\n local file_path=\"$1\"\n local tool_name=\"$2\"\n local timestamp=$(date +\"%Y-%m-%d %H:%M:%S\")\n local repo=$(find_repo \"$file_path\")\n\n if acquire_lock; then\n echo \"$timestamp | $repo | $tool_name | $file_path\" \u003e\u003e \"$LOG_FILE\"\n release_lock\n fi\n}\n\n# Function to find repo root\nfind_repo() {\n local file_path=\"$1\"\n if [ -z \"$file_path\" ] || [ \"$file_path\" = \"null\" ]; then\n echo \"unknown\"\n return\n fi\n\n local dir\n dir=$(dirname \"$file_path\" 2\u003e/dev/null || echo \"/\")\n while [ \"$dir\" != \"/\" ] \u0026\u0026 [ -n \"$dir\" ]; do\n if [ -d \"$dir/.git\" ]; then\n basename \"$dir\"\n return\n fi\n dir=$(dirname \"$dir\" 2\u003e/dev/null || echo \"/\")\n done\n echo \"unknown\"\n}\n\n# Read tool use event from stdin (with timeout to prevent hanging)\nif ! read -t 2 -r tool_use_json; then\n echo '{\"decision\": \"continue\"}'\n exit 0\nfi\n\n# Validate JSON to prevent injection\nif ! echo \"$tool_use_json\" | jq empty 2\u003e/dev/null; then\n echo '{\"decision\": \"continue\"}'\n exit 0\nfi\n\n# Extract tool name and file path from tool use\ntool_name=$(echo \"$tool_use_json\" | jq -r '.tool.name // .tool_name // \"unknown\"' 2\u003e/dev/null || echo \"unknown\")\nfile_path=\"\"\n\ncase \"$tool_name\" in\n \"Edit\"|\"Write\")\n file_path=$(echo \"$tool_use_json\" | jq -r '.tool.input.file_path // .tool_input.file_path // \"null\"' 2\u003e/dev/null || echo \"null\")\n ;;\n \"MultiEdit\")\n # MultiEdit has multiple files - log each\n echo \"$tool_use_json\" | jq -r '.tool.input.edits[]?.file_path // .tool_input.edits[]?.file_path // empty' 2\u003e/dev/null | while read -r path; do\n if [ -n \"$path\" ] \u0026\u0026 [ \"$path\" != \"null\" ]; then\n log_edit \"$path\" \"$tool_name\"\n fi\n done\n echo '{\"decision\": \"continue\"}'\n exit 0\n ;;\nesac\n\n# Log single edit\nif [ -n \"$file_path\" ] \u0026\u0026 [ \"$file_path\" != \"null\" ]; then\n log_edit \"$file_path\" \"$tool_name\"\nfi\n\n# Rotate log if too large (with lock)\nif acquire_lock; then\n line_count=$(wc -l \u003c \"$LOG_FILE\" 2\u003e/dev/null || echo \"0\")\n if [ \"$line_count\" -gt \"$MAX_LOG_LINES\" ]; then\n tail -n \"$MAX_LOG_LINES\" \"$LOG_FILE\" \u003e \"$LOG_FILE.tmp\"\n mv \"$LOG_FILE.tmp\" \"$LOG_FILE\"\n fi\n release_lock\nfi\n\n# Return success (non-blocking)\necho '{\"decision\": \"continue\"}'\n\\`\\`\\`\n\n**Step 3: Make script executable**\nRun:\n\\`\\`\\`bash\nchmod +x hooks/post-tool-use/01-track-edits.sh\n\\`\\`\\`\n\n### Step Group 2: Create Context Query Utilities\n\n**Step 4: Create context query utilities**\n\nCreate \\`hooks/utils/context-query.sh\\`:\n\n\\`\\`\\`bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nCONTEXT_DIR=\"$(dirname \"$0\")/../context\"\nLOG_FILE=\"$CONTEXT_DIR/edit-log.txt\"\n\n# Get files edited since timestamp\nget_recent_edits() {\n local since=\"${1:-}\"\n \n if [ ! -f \"$LOG_FILE\" ]; then\n return 0\n fi\n \n if [ -z \"$since\" ]; then\n cat \"$LOG_FILE\" 2\u003e/dev/null || true\n else\n awk -v since=\"$since\" -F '|' '$1 \u003e= since' \"$LOG_FILE\" 2\u003e/dev/null || true\n fi\n}\n\n# Get unique files edited in current session\nget_session_files() {\n local session_start=\"${1:-}\"\n \n get_recent_edits \"$session_start\" | \\\\\n awk -F '|' '{gsub(/^[ \\\\t]+|[ \\\\t]+$/, \"\", $4); print $4}' | \\\\\n sort -u\n}\n\n# Check if specific file was edited\nwas_file_edited() {\n local file_path=\"$1\"\n local since=\"${2:-}\"\n \n get_recent_edits \"$since\" | grep -q \"$(printf '%q' \"$file_path\")\" 2\u003e/dev/null\n}\n\n# Get edit count by repo\nget_repo_stats() {\n local since=\"${1:-}\"\n \n get_recent_edits \"$since\" | \\\\\n awk -F '|' '{gsub(/^[ \\\\t]+|[ \\\\t]+$/, \"\", $2); print $2}' | \\\\\n sort | uniq -c | sort -rn\n}\n\n# Clear log (for testing)\nclear_log() {\n if [ -f \"$LOG_FILE\" ]; then\n \u003e \"$LOG_FILE\"\n fi\n}\n\\`\\`\\`\n\n## Key Considerations (ADDED BY SRE REVIEW)\n\n**Race Condition Prevention**:\n- Multiple hooks may run concurrently\n- Use directory-based locking (atomic on most filesystems)\n- Timeout on lock acquisition to prevent deadlock\n- Non-blocking requirement means we log warning but continue\n\n**Input Validation**:\n- Malformed JSON could cause jq to hang or error\n- Use jq empty to validate JSON structure first\n- Read with timeout to prevent hanging on stdin\n\n**Path Security**:\n- File paths may contain spaces, quotes, or shell metacharacters\n- Use proper quoting in all path operations\n- Validate paths don't contain directory traversal (..)\n\n**Disk Full Scenarios**:\n- All writes use \u003e\u003e which will fail gracefully if disk full\n- Log rotation prevents unbounded growth\n- Non-blocking means we continue even if write fails\n\n## Anti-patterns\n- ❌ Blocking on I/O or lock acquisition\n- ❌ Unbounded log growth without rotation\n- ❌ Crashing on malformed input\n- ❌ Not handling concurrent access\n- ❌ Shell injection via unquoted paths\n- ❌ Hanging on stdin read","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-30T13:57:03.298717-04:00","updated_at":"2025-10-30T15:36:27.582323-04:00","closed_at":"2025-10-30T15:36:27.582323-04:00","dependencies":[{"issue_id":"bd-5","depends_on_id":"bd-1","type":"parent-child","created_at":"2025-10-30T13:57:10.497915-04:00","created_by":"ryan"},{"issue_id":"bd-5","depends_on_id":"bd-4","type":"blocks","created_at":"2025-10-30T13:57:16.843566-04:00","created_by":"ryan"}]} | ||
| {"id":"bd-50","title":"Feature: Antigravity-CLI Installer Integration","design":"## Requirements (IMMUTABLE)\n- Add first-class support for Antigravity-CLI (agy) to scripts/install.sh.\n- Detection must identify 'agy' in the system PATH.\n- Installation must use the extension-based approach: 'agy extensions install'.\n- Must leverage the existing .gemini-extension/ directory as the source.\n- Update --help and --hosts documentation to include 'antigravity'.\n- Ensure 'status', 'validate', and 'uninstall' flows are implemented for agy.\n\n## Success Criteria (MUST ALL BE TRUE)\n- [ ] 'detect_antigravity' correctly identifies the 'agy' binary.\n- [ ] 'install_antigravity' successfully runs 'agy extensions install'.\n- [ ] 'status_antigravity' correctly reports the installation state.\n- [ ] 'scripts/install.sh --hosts antigravity' works end-to-end.\n- [ ] All existing hosts (claude, gemini, etc.) remain functional.\n- [ ] Tests in tests/install-script.test.js are updated or verified.\n\n## Anti-Patterns (FORBIDDEN)\n- ❌ NO duplication of the .gemini-extension/ folder specifically for antigravity.\n- ❌ NO hardcoded paths to /Users/dpolishuk/ - must use generic home/PATH logic.\n- ❌ NO skipping the validation step after installation.\n\n## Approach\nImplement dedicated functions (detect, install, status, validate, uninstall) for antigravity within scripts/install.sh. Register 'antigravity' in the AGENT_ORDER and relevant mapping arrays. Use the 'agy' command for all interactions.\n\n## Architecture\n- scripts/install.sh: Main entry point and logic hub.\n- .gemini-extension/: Shared source for both Gemini and Antigravity extensions.\n\n## Design Rationale\n### Problem\nAntigravity-CLI is a key host for our users but currently lacks an automated setup flow in the unified installer, requiring manual configuration.\n\n### Research Findings\n- Binary is 'agy', version 1.0.1.\n- Supports 'extensions' subcommand similar to Gemini CLI.\n- Shares data roots but identifies as a separate host.\n\n## Scope Boundaries\n**In scope:**\n- PATH-based detection of 'agy'.\n- Extension installation to 'agy'.\n- Documentation updates.\n\n**Out of scope:**\n- Installing the 'agy' binary itself (assumed pre-installed).\n- Modifying the 'agy' extension architecture.","status":"closed","priority":2,"issue_type":"epic","owner":"dmitry.polishuk@gmail.com","created_at":"2026-05-22T15:00:16.0299+03:00","created_by":"Dmitry Polishuk","updated_at":"2026-05-24T22:39:19.633239+03:00","closed_at":"2026-05-24T22:39:19.633239+03:00","close_reason":"Closed"} |
There was a problem hiding this comment.
Fixed. Updated the bd-50 epic requirements and success criteria inside .beads/issues.jsonl to match the actual intended command/API (agy plugin import).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6fbbd622cb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if [[ "$USE_SYMLINKS" == true ]]; then | ||
| # agy doesn't have a direct 'link' for local plugins that works like 'extensions link' | ||
| # but we can import it. | ||
| agy_stderr=$(timeout 10s agy plugin import "$ext_dir" 2>&1) || { |
There was a problem hiding this comment.
Avoid hard dependency on GNU timeout for Antigravity install
install_antigravity() now wraps agy plugin import with timeout, but there is no fallback when timeout is unavailable (common on macOS where only gtimeout exists). In that environment, timeout exits 127 and the host install fails even when agy itself works, so --antigravity/--hosts antigravity cannot complete. This regression is introduced in this commit and also affects new Antigravity status/validation paths that use the same assumption.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. Added a transparent fallback shim function for the timeout command inside scripts/install.sh. If GNU timeout is not installed (e.g. default macOS), it attempts to use Homebrews gtimeout`, or executes the command directly without a timeout limit, preventing regression failures.
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/install.sh (1)
1100-1118:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPropagate uninstall failures instead of always reporting success.
Both uninstall branches swallow CLI errors with
|| true, so a timeout or rejected uninstall still prints a green check in the final summary. That leaves stale integrations behind while telling the user cleanup succeeded.🛠️ Proposed fix
uninstall_gemini() { if command -v gemini &>/dev/null; then if [[ "$DRY_RUN" == true ]]; then info "Would run: gemini extensions uninstall xpowers" else - timeout 5s gemini extensions uninstall xpowers 2>/dev/null || true + if ! timeout 5s gemini extensions uninstall xpowers 2>/dev/null; then + warn "gemini extensions uninstall xpowers failed" + return 1 + fi fi fi } uninstall_antigravity() { if command -v agy &>/dev/null; then if [[ "$DRY_RUN" == true ]]; then info "Would run: agy plugin uninstall xpowers" else - timeout 5s agy plugin uninstall xpowers 2>/dev/null || true + if ! timeout 5s agy plugin uninstall xpowers 2>/dev/null; then + warn "agy plugin uninstall xpowers failed" + return 1 + fi fi fi }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/install.sh` around lines 1100 - 1118, The uninstall functions uninstall_gemini() and uninstall_antigravity() currently swallow failures by appending "|| true" to the timeout commands, so timeouts or CLI errors always appear successful; remove the "|| true" and instead capture and propagate the command exit status (e.g., store "$?" into a variable), on failure call the existing error/logger helper or return a non-zero status so the caller can detect failures (preserve the DRY_RUN branch behavior), and ensure any error messages include which command failed (gemini/agy and the uninstall invocation) so the final summary can reflect actual success/failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.beads/issues.jsonl:
- Around line 19-21: The epic bd-50's immutable requirements still state the
installer should use "agy extensions install" but the implemented command is
"agy plugin import"; update the bd-50 description and Requirements to replace
"agy extensions install" with "agy plugin import" (and adjust any related
wording that asserts the immutable contract) so the epic accurately reflects the
shipped behavior and avoids a tracker mismatch.
In `@scripts/install.sh`:
- Around line 372-382: The
detect_antigravity/install_antigravity/validate_antigravity/uninstall_antigravity/status_antigravity
functions call GNU `timeout` directly and thus must use a portable fallback and
correct uninstall behavior; add or use a helper (e.g., find_timeout) that
prefers `timeout` or `gtimeout` and returns a command to invoke with a timeout,
replace all raw `timeout` invocations in detect_antigravity,
install_antigravity, validate_antigravity, uninstall_antigravity, and
status_antigravity to use that helper, remove the unconditional "|| true" in
uninstall_antigravity so its exit status is propagated (so the caller if
"uninstall_${agent}" can detect failure), and fix the Graphify mapping to call
"graphify antigravity install" instead of "graphify install --platform gemini"
so the correct subcommand is used.
- Around line 1568-1571: The antigravity) case currently sets
try_command="graphify install --platform gemini" and graphify_args=(install
--platform gemini), which installs the wrong layout; update the antigravity)
block to use Graphify v4's Antigravity installer by setting
try_command="graphify antigravity install" and graphify_args=(antigravity
install) (adjust the label "Antigravity CLI" remains unchanged) so the script
invokes the correct subcommand.
In `@tests/install-script.test.js`:
- Around line 48-79: The test currently writes bash/npm/npx shims into the first
entry of env.PATH (firstPart), which can mutate real user/CI PATH entries;
instead create a test-owned temporary directory (e.g., via fs.mkdtempSync or
os.tmpdir) and prepend it to env.PATH for the test, then create the bashSymlink,
npmMock and npxMock files inside that temp dir (use findExecutable to locate
real bash if needed) so only test-controlled PATH entries are modified and no
real PATH entries are written to. Ensure you replace references that use
firstPart with the new temp dir and clean up the temp dir after the test.
---
Outside diff comments:
In `@scripts/install.sh`:
- Around line 1100-1118: The uninstall functions uninstall_gemini() and
uninstall_antigravity() currently swallow failures by appending "|| true" to the
timeout commands, so timeouts or CLI errors always appear successful; remove the
"|| true" and instead capture and propagate the command exit status (e.g., store
"$?" into a variable), on failure call the existing error/logger helper or
return a non-zero status so the caller can detect failures (preserve the DRY_RUN
branch behavior), and ensure any error messages include which command failed
(gemini/agy and the uninstall invocation) so the final summary can reflect
actual success/failure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6d9d96ae-f090-42c5-b833-45ffe28e973f
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
.beads/issues.jsonlscripts/install.shscripts/install.tstests/install-script.test.js
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 44eb223b49
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…PATH shims in tests
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 637cdccd64
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…_antigravity idempotency
This PR implements full first-class integration for Antigravity-CLI (
agy) across both installer scripts (install.shandinstall.ts).Changes
install_antigravity()to import usingagy plugin import, and registersantigravityto receivegraphifycompanion configurations. Corrects missing-binary detection to exit gracefully without crashing scripts in aset -epipeline.antigravityhost metadata configuration including status checks, version pattern checks, installation, and uninstallation routines. Correctsclaude-memandgraphifyrules forantigravity.npmandnpxdynamically withininstallEnv()to prevent network-bound requests (e.g.@linear/sdk) from hanging indefinitely in sandboxed or offline testing environments.All 68 integration tests have been run and pass successfully.
Summary by CodeRabbit