@seanyao/roll 2026.522.1 → 2026.522.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## v2026.522.2
4
+
5
+ ### Changed
6
+
7
+ - **Roll 改用 Antigravity (`agy`)** — Google 已退役独立 Gemini CLI,agy 是接班产品;老用户重跑 `roll setup` 即可
8
+
9
+ ### Improved
10
+
11
+ - **dashboard token 列现在只算 input/output,cache 不再混进来虚抬总量** `[loop]`
12
+ - **`roll loop status` 现在分清「没装 / 装了关了 / 正常」三种状态** — 之前看不出 loop 到底有没有起来 `[loop]`
13
+
14
+ ### Fixed
15
+
16
+ - **loop 异常中断时未推送的 commit 不再丢** — 自动开成 PR `[loop]`
17
+ - **loop 每小时弹窗不再抢前台焦点** — 后台开 Terminal,不打断你在干的事
18
+ - **`roll loop` 在非 git 目录下不再静默崩溃** `[loop]`
19
+
3
20
  ## v2026.522.1
4
21
 
5
22
  ### Fixed
package/bin/roll CHANGED
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
  # Roll — AI Agent Convention Manager
5
5
  # Single source of truth for how all AI coding agents behave.
6
6
 
7
- VERSION="2026.522.1"
7
+ VERSION="2026.522.2"
8
8
  ROLL_HOME="${ROLL_HOME:-${HOME}/.roll}"
9
9
  ROLL_CONFIG="${ROLL_HOME}/config.yaml"
10
10
  ROLL_GLOBAL="${ROLL_HOME}/conventions/global"
@@ -59,6 +59,9 @@ ai_tool_name() {
59
59
  elif [[ "$bn" == "agent" || "$bn" == "workspace" ]]; then
60
60
  bn="$(basename "$(dirname "$dir")" | sed 's/^\.//')"
61
61
  fi
62
+ # Antigravity (agy) reuses ~/.gemini/ from the deprecated Gemini CLI for
63
+ # its config dir, so a literal `gemini` basename now identifies agy.
64
+ [[ "$bn" == "gemini" ]] && bn="agy"
62
65
  echo "$bn"
63
66
  }
64
67
 
@@ -94,6 +97,123 @@ _is_ai_installed() {
94
97
  return 1
95
98
  }
96
99
 
100
+ # ─── Spinner: TTY-aware status display for long-running steps (US-REL-003) ───
101
+ # _spin_setup [off]
102
+ # Opens FD 3 for spinner output. Without args: FD 3 → stdout if interactive,
103
+ # else stderr (best-effort visibility for the operator). With "off": FD 3
104
+ # → /dev/null, silencing all _spin output (useful for scripts that drive
105
+ # release.sh in non-interactive contexts but still want exit codes).
106
+ _spin_setup() {
107
+ if [ "${1:-}" = "off" ]; then
108
+ exec 3>/dev/null
109
+ return 0
110
+ fi
111
+ if [ -t 1 ]; then
112
+ # Interactive: spinner shares stdout with normal program output.
113
+ exec 3>&1
114
+ else
115
+ # Non-interactive (stdout redirected to file / piped): route the spinner
116
+ # trail to stderr so it stays visible in CI logs and never pollutes the
117
+ # caller's redirected stdout (e.g. > release_notes.txt). FD 3 will be
118
+ # plain-text mode whenever stderr is also not a TTY.
119
+ exec 3>&2
120
+ fi
121
+ }
122
+
123
+ # _spin <label> <cmd> [args...]
124
+ # Runs cmd with a status indicator written to FD 3 only. cmd's own
125
+ # stdout (FD 1) and stderr (FD 2) pass through untouched, so caller-side
126
+ # `>file` and `2>file` redirections on the _spin call behave normally.
127
+ #
128
+ # FD 3 is a TTY (or ROLL_SPIN_FORCE_TTY=1):
129
+ # ⠋ label [Ns] (refreshed ~10/s, line-cleared with \r\033[2K)
130
+ # final: ✓ label (Ns) on success
131
+ # ✗ label (rc=N, Ns) on failure
132
+ #
133
+ # FD 3 not a TTY (CI, pipes, `2>&1 | tee`):
134
+ # » label... on start
135
+ # done label (Ns) on success
136
+ # fail label (rc=N, Ns) on failure
137
+ #
138
+ # Returns wrapped cmd's exit code (transparent under `set -e` callers
139
+ # when used in `if`/`&&`/`||` contexts).
140
+ _spin() {
141
+ local _label="$1"
142
+ shift
143
+
144
+ local _spin_tty=0
145
+ if [ "${ROLL_SPIN_FORCE_TTY:-}" = "1" ] || [ -t 3 ]; then
146
+ _spin_tty=1
147
+ fi
148
+
149
+ local _spin_start=$SECONDS
150
+ local _spin_pid=""
151
+
152
+ if [ "$_spin_tty" = "1" ]; then
153
+ # Bash 3.2-safe: indexed array of braille frames.
154
+ local _spin_frames
155
+ _spin_frames=( $'\xe2\xa0\x8b' $'\xe2\xa0\x99' $'\xe2\xa0\xb9' $'\xe2\xa0\xb8' $'\xe2\xa0\xbc' $'\xe2\xa0\xb4' $'\xe2\xa0\xa6' $'\xe2\xa0\xa7' $'\xe2\xa0\x87' $'\xe2\xa0\x8f' )
156
+ # Print initial frame at t=0 so users see something immediately.
157
+ printf '\r\033[2K%s %s [0s]' "${_spin_frames[0]}" "$_label" >&3 2>/dev/null || true
158
+ # Only animate when FD 3 is a real TTY — when force-on for tests, skip
159
+ # the background animator so the test gets deterministic output (the
160
+ # initial frame, the cleared final frame).
161
+ if [ -t 3 ]; then
162
+ (
163
+ set +e +u 2>/dev/null
164
+ local _i=1
165
+ local _t0=$_spin_start
166
+ while :; do
167
+ sleep 0.1
168
+ local _e=$(( SECONDS - _t0 ))
169
+ printf '\r\033[2K%s %s [%ds]' "${_spin_frames[$_i]}" "$_label" "$_e" >&3 2>/dev/null || true
170
+ _i=$(( (_i + 1) % 10 ))
171
+ done
172
+ ) &
173
+ _spin_pid=$!
174
+ # Kill spinner on Ctrl-C / SIGTERM / EXIT. Save no prior trap because
175
+ # release.sh and its callers install no traps of their own; if a
176
+ # future caller does, _spin's scope is short and traps are restored
177
+ # to default after reaping.
178
+ # shellcheck disable=SC2064
179
+ trap "kill ${_spin_pid} 2>/dev/null; wait ${_spin_pid} 2>/dev/null; trap - INT TERM EXIT; exit 130" INT TERM
180
+ # shellcheck disable=SC2064
181
+ trap "kill ${_spin_pid} 2>/dev/null; wait ${_spin_pid} 2>/dev/null" EXIT
182
+ fi
183
+ else
184
+ printf '» %s...\n' "$_label" >&3 2>/dev/null || true
185
+ fi
186
+
187
+ local _spin_rc=0
188
+ if [ "$#" -gt 0 ]; then
189
+ "$@" || _spin_rc=$?
190
+ fi
191
+
192
+ if [ -n "$_spin_pid" ]; then
193
+ kill "$_spin_pid" 2>/dev/null || true
194
+ wait "$_spin_pid" 2>/dev/null || true
195
+ trap - INT TERM EXIT
196
+ fi
197
+
198
+ local _spin_elapsed=$(( SECONDS - _spin_start ))
199
+
200
+ if [ "$_spin_tty" = "1" ]; then
201
+ if [ "$_spin_rc" -eq 0 ]; then
202
+ printf '\r\033[2K✓ %s (%ds)\n' "$_label" "$_spin_elapsed" >&3 2>/dev/null || true
203
+ else
204
+ printf '\r\033[2K✗ %s (rc=%d, %ds)\n' "$_label" "$_spin_rc" "$_spin_elapsed" >&3 2>/dev/null || true
205
+ fi
206
+ else
207
+ if [ "$_spin_rc" -eq 0 ]; then
208
+ printf 'done %s (%ds)\n' "$_label" "$_spin_elapsed" >&3 2>/dev/null || true
209
+ else
210
+ printf 'fail %s (rc=%d, %ds)\n' "$_label" "$_spin_rc" "$_spin_elapsed" >&3 2>/dev/null || true
211
+ fi
212
+ fi
213
+
214
+ return "$_spin_rc"
215
+ }
216
+
97
217
  # ─── Helper: read config value ───────────────────────────────────────────────
98
218
  config_get() {
99
219
  local key="$1"
@@ -136,7 +256,7 @@ _ensure_config_entries() {
136
256
 
137
257
  local -a default_keys=(
138
258
  "ai_claude:~/.claude|CLAUDE.md|CLAUDE.md"
139
- "ai_gemini:~/.gemini|GEMINI.md|GEMINI.md"
259
+ "ai_agy:~/.gemini|GEMINI.md|GEMINI.md"
140
260
  "ai_kimi:~/.kimi|AGENTS.md|AGENTS.md"
141
261
  "ai_codex:~/.codex|AGENTS.md|AGENTS.md"
142
262
  "ai_cursor:~/.cursor|.cursor-rules|.cursor-rules"
@@ -2495,19 +2615,23 @@ _peer_route() {
2495
2615
  }
2496
2616
 
2497
2617
  # Open a Terminal.app window attached to the given tmux session (peer
2498
- # auto-attach). No-ops when muted, non-macOS, or osascript unavailable.
2618
+ # auto-attach). No-ops when muted or non-macOS.
2499
2619
  # FIX-054: terminal selection removed — always dispatches to macOS
2500
2620
  # Terminal.app for predictability (per-user detection silently failed on
2501
2621
  # Ghostty upgrades).
2622
+ # Uses `open -g` so the window appears in the background and does not steal
2623
+ # focus from the user's active app (replaces a prior osascript-based
2624
+ # capture-frontmost / restore-focus dance that triggered LaunchServices
2625
+ # "where is <app>" prompts when the active process name differed from its
2626
+ # .app bundle name, e.g. MSTeams vs Microsoft Teams.app).
2502
2627
  _peer_auto_attach() {
2503
2628
  local session="$1"
2504
2629
  [ "$(uname)" = "Darwin" ] || return 0
2505
2630
  [ -f "$_LOOP_MUTE_FILE" ] && return 0
2506
- command -v osascript >/dev/null 2>&1 || return 0
2507
- osascript \
2508
- -e 'tell application "System Events" to set _prev to name of first application process whose frontmost is true' \
2509
- -e "tell application \"Terminal\" to do script \"tmux attach -t $session\"" \
2510
- -e 'delay 0.3' -e 'try' -e 'tell application _prev to activate' -e 'end try' >/dev/null 2>&1 || true
2631
+ local attach_cmd="${_SHARED_ROOT}/loop/attach-${session}.command"
2632
+ printf '#!/bin/bash\nexec tmux attach -t %s\n' "$session" > "$attach_cmd" 2>/dev/null || return 0
2633
+ chmod +x "$attach_cmd" 2>/dev/null || return 0
2634
+ open -g -a Terminal "$attach_cmd" >/dev/null 2>&1 || true
2511
2635
  }
2512
2636
 
2513
2637
  # Dispatch a peer CLI command inside an existing tmux session (window 0).
@@ -2976,10 +3100,13 @@ _agent_argv() {
2976
3100
  interactive) _AGENT_ARGV=(opencode "$prompt") ;;
2977
3101
  *) _AGENT_ARGV=(opencode run "$prompt") ;;
2978
3102
  esac ;;
2979
- gemini)
2980
- # gemini integration is interactive-only for now (used by onboard flow).
3103
+ agy)
3104
+ # Antigravity (agy) replaces the deprecated Google Gemini CLI as of
3105
+ # late 2025. agy reuses ~/.gemini/ for config and reads GEMINI.md
3106
+ # natively, so the convention sync target is unchanged — only the
3107
+ # invoked binary changes. Interactive-only (used by onboard flow).
2981
3108
  case "$mode" in
2982
- interactive) _AGENT_ARGV=(gemini "$prompt") ;;
3109
+ interactive) _AGENT_ARGV=(agy -i "$prompt") ;;
2983
3110
  *) return 1 ;;
2984
3111
  esac ;;
2985
3112
  *) return 1 ;;
@@ -3072,7 +3199,7 @@ _slides_lib() {
3072
3199
  # Returns 0 + prints the path if the template exists, else returns 1.
3073
3200
  _slides_template_path() {
3074
3201
  local name="$1"
3075
- local tpl="${ROLL_PKG_DIR}/site/slides/templates/${name}.html"
3202
+ local tpl="${ROLL_PKG_DIR}/lib/slides/templates/${name}.html"
3076
3203
  if [[ -f "$tpl" ]]; then
3077
3204
  printf '%s' "$tpl"
3078
3205
  return 0
@@ -3702,8 +3829,12 @@ _slug_migrate_from_legacy() {
3702
3829
  [[ "$(uname -s 2>/dev/null)" == "Darwin" ]] || return 0
3703
3830
  # Compute the pre-FIX-056 slug: same algorithm but without realpath.
3704
3831
  local raw_path; raw_path=$(pwd 2>/dev/null)
3832
+ # FIX-094: `_common=$(...)` as a standalone assignment statement inherits the
3833
+ # command's exit code; `set -e` aborts the whole script when cwd is non-git
3834
+ # (git rev-parse exits 128). `|| true` keeps probing semantics — we WANT to
3835
+ # detect "no git" by empty output, not by killing the script.
3705
3836
  local _common
3706
- _common=$(git -C "$raw_path" rev-parse --git-common-dir 2>/dev/null)
3837
+ _common=$(git -C "$raw_path" rev-parse --git-common-dir 2>/dev/null) || true
3707
3838
  if [[ -n "$_common" && "$_common" == *"/.git" ]]; then
3708
3839
  raw_path="${_common%/.git}"
3709
3840
  fi
@@ -4195,14 +4326,26 @@ _inner_cleanup() {
4195
4326
  && [ -n "\${CYCLE_ID:-}" ]; then
4196
4327
  _unpushed=\$(cd "\$WT" && git rev-list --count "origin/main..HEAD" 2>/dev/null || echo 0)
4197
4328
  if [ "\${_unpushed:-0}" -gt 0 ]; then
4198
- _orphan_tag="loop-orphan-\${CYCLE_ID}"
4199
- if ( cd "\$WT" && git push origin "\$BRANCH" 2>/dev/null \\
4200
- && git tag "\$_orphan_tag" 2>/dev/null \\
4201
- && git push origin "\$_orphan_tag" 2>/dev/null ); then
4202
- _loop_event cycle_end "\${CYCLE_ID}" "\${BRANCH:-}" "orphan" 2>/dev/null || true
4329
+ # FIX-091: prefer a real PR so auto-merge lands the work; tag-only is the
4330
+ # last-resort because it requires manual cherry-pick. Emit cycle_end "done"
4331
+ # (canonical success status the dashboard recognizes) when PR publishes.
4332
+ _slug=""
4333
+ if _gh_resolve _slug \\
4334
+ && ( cd "\$WT" && _loop_publish_pr "\$BRANCH" "loop cycle \${CYCLE_ID}" ) >/dev/null 2>&1; then
4335
+ _loop_event cycle_end "\${CYCLE_ID}" "\${BRANCH:-}" "done" 2>/dev/null || true
4203
4336
  _CYCLE_END_WRITTEN=1
4204
- _runs_append "orphan" 0 "[]" 2>/dev/null || true
4205
- _worktree_alert "cycle \${CYCLE_ID}: aborted with \${_unpushed} commits; FIX-086 pushed orphan tag \${_orphan_tag}" 2>/dev/null || true
4337
+ _runs_append "done" 0 "[]" 2>/dev/null || true
4338
+ _worktree_alert "cycle \${CYCLE_ID}: aborted with \${_unpushed} commits; FIX-091 published as PR" 2>/dev/null || true
4339
+ else
4340
+ _orphan_tag="loop-orphan-\${CYCLE_ID}"
4341
+ if ( cd "\$WT" && git push origin "\$BRANCH" 2>/dev/null \\
4342
+ && git tag "\$_orphan_tag" 2>/dev/null \\
4343
+ && git push origin "\$_orphan_tag" 2>/dev/null ); then
4344
+ _loop_event cycle_end "\${CYCLE_ID}" "\${BRANCH:-}" "orphan" 2>/dev/null || true
4345
+ _CYCLE_END_WRITTEN=1
4346
+ _runs_append "orphan" 0 "[]" 2>/dev/null || true
4347
+ _worktree_alert "cycle \${CYCLE_ID}: aborted with \${_unpushed} commits; FIX-086 pushed orphan tag \${_orphan_tag}" 2>/dev/null || true
4348
+ fi
4206
4349
  fi
4207
4350
  fi
4208
4351
  fi
@@ -4588,13 +4731,16 @@ if command -v tmux >/dev/null 2>&1; then
4588
4731
  # to the tmux session so the user can watch the loop work in real time.
4589
4732
  # FIX-054: terminal selection removed — fixed to macOS Terminal.app for
4590
4733
  # predictability (per-user detection silently failed on Ghostty upgrades).
4591
- # Best-effort focus retention: capture the current frontmost app and
4592
- # re-activate after.
4593
- if [ -z "\${ROLL_LOOP_NO_POPUP:-}" ] && [ -z "\${BATS_TEST_NUMBER:-}" ] && [ ! -f "\$HOME/.shared/roll/loop/mute-${slug}" ] && [ "\$(uname)" = "Darwin" ] && command -v osascript >/dev/null 2>&1; then
4594
- osascript \\
4595
- -e 'tell application "System Events" to set _prev to name of first application process whose frontmost is true' \\
4596
- -e "tell application \"Terminal\" to do script \"tmux attach -t \$SESSION\"" \\
4597
- -e 'delay 0.3' -e 'try' -e 'tell application _prev to activate' -e 'end try' >/dev/null 2>&1 || true
4734
+ # Uses \`open -g\` so the window appears in the background and does not steal
4735
+ # focus. Replaces a prior osascript capture-frontmost / restore-focus dance
4736
+ # that triggered LaunchServices "where is <app>" prompts when the active
4737
+ # process name differed from its .app bundle name (e.g. MSTeams vs
4738
+ # Microsoft Teams.app).
4739
+ if [ -z "\${ROLL_LOOP_NO_POPUP:-}" ] && [ -z "\${BATS_TEST_NUMBER:-}" ] && [ ! -f "\$HOME/.shared/roll/loop/mute-${slug}" ] && [ "\$(uname)" = "Darwin" ]; then
4740
+ _attach_cmd="\$HOME/.shared/roll/loop/attach-\$SESSION.command"
4741
+ printf '#!/bin/bash\\nexec tmux attach -t %s\\n' "\$SESSION" > "\$_attach_cmd" 2>/dev/null || true
4742
+ chmod +x "\$_attach_cmd" 2>/dev/null || true
4743
+ open -g -a Terminal "\$_attach_cmd" >/dev/null 2>&1 || true
4598
4744
  fi
4599
4745
  _OUTER_TIMEOUT=\$(( \${ROLL_LOOP_CYCLE_TIMEOUT_SEC:-2700} + 300 ))
4600
4746
  _outer_wait_start=\$(date +%s)
@@ -4687,21 +4833,43 @@ _install_launchd_plists() {
4687
4833
  local after; after=$(cat "$plist")
4688
4834
  if [[ "$before" != "$after" ]]; then
4689
4835
  updated=$((updated + 1))
4690
- if _launchd_is_loaded "$label"; then
4691
- # FIX-027: use bootout/bootstrap so we don't disturb the label's
4692
- # enabled flag in the launchd overrides db (which legacy
4693
- # unload/load no-`-w` wipes on macOS Sonoma+, causing
4694
- # `roll loop status` to falsely report off after `roll update`).
4695
- local uid; uid=$(id -u)
4696
- launchctl bootout "gui/${uid}/${label}" 2>/dev/null || true
4697
- launchctl bootstrap "gui/${uid}" "$plist" 2>/dev/null || true
4698
- elif [[ -z "$before" ]]; then
4699
- # FIX-059: brand-new plist macOS FSEvents auto-bootstraps any new
4700
- # file dropped in ~/Library/LaunchAgents/, so projects never enabled
4701
- # via 'roll loop on' would fire every hour. Immediately mark disabled
4702
- # in the overrides db to block that auto-load.
4703
- local uid; uid=$(id -u)
4704
- launchctl disable "gui/${uid}/${label}" 2>/dev/null || true
4836
+ # FIX-090: gate launchctl writes so a sandboxed plist never gets
4837
+ # registered into the user's REAL gui/<uid> domain. Without this,
4838
+ # `launchctl bootstrap gui/<uid> <sandbox-plist>` outlives TEST_TMP
4839
+ # cleanup as a zombie that either fails silently (EX_CONFIG) or, when
4840
+ # the label collides with the dev's project slug, displaces the real
4841
+ # registration and kills the autonomous loop. Two gate paths:
4842
+ # - explicit: integration_setup exports _LAUNCHD_SKIP_REGISTRY=1
4843
+ # - implicit: if _LAUNCHD_DIR was auto-sandboxed under _SHARED_ROOT
4844
+ # (FIX-087 inner-runner.sh re-source path) we infer skip — callers
4845
+ # that genuinely want the launchctl flow override _LAUNCHD_DIR to
4846
+ # a path outside _SHARED_ROOT (unit tests; production has no
4847
+ # _SHARED_ROOT match against ~/Library/LaunchAgents).
4848
+ # See helpers.bash and tests/unit/launchd_sandbox.bats.
4849
+ local _skip_reg="${_LAUNCHD_SKIP_REGISTRY:-}"
4850
+ if [[ -z "$_skip_reg" ]]; then
4851
+ case "${_LAUNCHD_DIR:-}/" in
4852
+ "${_SHARED_ROOT:-/nonexistent}"/*) _skip_reg=1 ;;
4853
+ *) _skip_reg=0 ;;
4854
+ esac
4855
+ fi
4856
+ if [[ "$_skip_reg" != "1" ]]; then
4857
+ if _launchd_is_loaded "$label"; then
4858
+ # FIX-027: use bootout/bootstrap so we don't disturb the label's
4859
+ # enabled flag in the launchd overrides db (which legacy
4860
+ # unload/load no-`-w` wipes on macOS Sonoma+, causing
4861
+ # `roll loop status` to falsely report off after `roll update`).
4862
+ local uid; uid=$(id -u)
4863
+ launchctl bootout "gui/${uid}/${label}" 2>/dev/null || true
4864
+ launchctl bootstrap "gui/${uid}" "$plist" 2>/dev/null || true
4865
+ elif [[ -z "$before" ]]; then
4866
+ # FIX-059: brand-new plist — macOS FSEvents auto-bootstraps any new
4867
+ # file dropped in ~/Library/LaunchAgents/, so projects never enabled
4868
+ # via 'roll loop on' would fire every hour. Immediately mark disabled
4869
+ # in the overrides db to block that auto-load.
4870
+ local uid; uid=$(id -u)
4871
+ launchctl disable "gui/${uid}/${label}" 2>/dev/null || true
4872
+ fi
4705
4873
  fi
4706
4874
  fi
4707
4875
  done
@@ -7,7 +7,7 @@
7
7
  sync_claude: ~/.claude/CLAUDE.md
8
8
  sync_kimi: ~/.kimi/AGENTS.md
9
9
  sync_codex: ~/.codex/AGENTS.md
10
- sync_gemini: ~/.gemini/GEMINI.md
10
+ sync_agy: ~/.gemini/GEMINI.md # Antigravity (agy) reuses the legacy ~/.gemini/ path
11
11
 
12
12
  # User preferences
13
13
  default_language: zh
@@ -133,7 +133,7 @@ conventions, deploy targets.
133
133
  |---|---|---|
134
134
  | `conventions/global/AGENTS.md` | `conventions/templates/<type>/AGENTS.md` | All agents |
135
135
  | `conventions/global/CLAUDE.md` | `conventions/templates/<type>/CLAUDE.md` | Claude Code |
136
- | `conventions/global/GEMINI.md` | `conventions/templates/<type>/GEMINI.md` | Gemini CLI |
136
+ | `conventions/global/GEMINI.md` | `conventions/templates/<type>/GEMINI.md` | Antigravity (agy) — reads `~/.gemini/GEMINI.md` natively |
137
137
  | `conventions/global/project_rules.md` | `conventions/templates/<type>/project_rules.md` | Trae IDE |
138
138
 
139
139
  The CLAUDE / GEMINI / project_rules global files themselves declare they
@@ -1,9 +1,14 @@
1
- # Global Preferences — Gemini CLI
1
+ # Global Preferences — Antigravity (agy)
2
2
 
3
3
  > Extends AGENTS.md in this directory — read that first for shared conventions.
4
- > This file adds Gemini CLI-specific configuration only.
4
+ > This file adds Antigravity-specific configuration only.
5
+ >
6
+ > File is named `GEMINI.md` because agy reads `~/.gemini/GEMINI.md` natively
7
+ > (it reuses the legacy Gemini CLI config dir). The filename is the canonical
8
+ > agy-side filename; the content here is for agy.
5
9
 
6
- ## Gemini-Specific
10
+ ## Antigravity-Specific
7
11
 
8
12
  - When running shell commands, prefer the most specific tool available.
9
13
  - When a project has Roll workflow, follow the AGENTS.md conventions and use Roll skills.
14
+ - Invoke interactively with `agy -i "<prompt>"`; non-interactive with `agy -p "<prompt>"`.
@@ -1,6 +1,6 @@
1
- # Project Preferences — Backend Service (Gemini CLI)
1
+ # Project Preferences — Backend Service (Antigravity)
2
2
 
3
- > Extends global GEMINI.md + project AGENTS.md.
3
+ > Extends global GEMINI.md (Antigravity) + project AGENTS.md.
4
4
 
5
5
  ## Stack
6
6
 
@@ -8,7 +8,7 @@
8
8
  - Database: Prisma or Drizzle ORM
9
9
  - Testing: Vitest + Supertest
10
10
 
11
- ## Gemini Notes
11
+ ## Antigravity (agy) Notes
12
12
 
13
13
  - No frontend in this project. API-only service.
14
14
  - Write integration tests that hit real endpoints, not mocked handlers.
@@ -1,6 +1,6 @@
1
- # Project Preferences — CLI Tool (Gemini CLI)
1
+ # Project Preferences — CLI Tool (Antigravity)
2
2
 
3
- > Extends global GEMINI.md + project AGENTS.md.
3
+ > Extends global GEMINI.md (Antigravity) + project AGENTS.md.
4
4
 
5
5
  ## Stack
6
6
 
@@ -8,7 +8,7 @@
8
8
  - CLI framework: commander or citty
9
9
  - Testing: Vitest
10
10
 
11
- ## Gemini Notes
11
+ ## Antigravity (agy) Notes
12
12
 
13
13
  - No server, no frontend. CLI tool only.
14
14
  - Test commands by running them, not just unit tests.
@@ -1,13 +1,13 @@
1
- # Project Preferences — Frontend Only (Gemini CLI)
1
+ # Project Preferences — Frontend Only (Antigravity)
2
2
 
3
- > Extends global GEMINI.md + project AGENTS.md.
3
+ > Extends global GEMINI.md (Antigravity) + project AGENTS.md.
4
4
 
5
5
  ## Stack
6
6
 
7
7
  - React + shadcn/ui + Tailwind CSS + Vite
8
8
  - Testing: Vitest + Playwright
9
9
 
10
- ## Gemini Notes
10
+ ## Antigravity (agy) Notes
11
11
 
12
12
  - No backend in this project. All data via external API consumption.
13
13
  - Run `npm run build` to verify production bundle compiles before pushing.
@@ -1,6 +1,6 @@
1
- # Project Preferences — Fullstack Web (Gemini CLI)
1
+ # Project Preferences — Fullstack Web (Antigravity)
2
2
 
3
- > Extends global GEMINI.md + project AGENTS.md.
3
+ > Extends global GEMINI.md (Antigravity) + project AGENTS.md.
4
4
 
5
5
  ## Stack
6
6
 
@@ -8,7 +8,7 @@
8
8
  - Backend: Node.js API (Express/Hono/Fastify)
9
9
  - Testing: Vitest (unit) + Playwright (E2E)
10
10
 
11
- ## Gemini Notes
11
+ ## Antigravity (agy) Notes
12
12
 
13
13
  - When modifying API contracts, update both `api/types.ts` and `src/shared/types/` in the same commit.
14
14
  - Run `npm run build` to verify both frontend and backend compile before pushing.
@@ -12,15 +12,26 @@ to sonnet rates with a stderr warning so dashboards don't blank out.
12
12
  import sys
13
13
  from typing import Dict, Optional
14
14
 
15
- # Rates per million tokens (USD).
15
+ # Rates per million tokens (USD). cache_create = 5-minute cache write (1.25x
16
+ # input). 1-hour cache writes (2x input) are not modeled — Roll loop uses the
17
+ # default 5m caching only.
18
+ # Source: https://platform.claude.com/docs/en/about-claude/pricing
16
19
  PRICES: Dict[str, Dict[str, float]] = {
17
- # Claude 4.x family (current as of 2026-05).
18
- "claude-opus-4-7": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
19
- "claude-opus-4-6": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
20
+ # Claude 4.x Opus family 2026-05 repricing: Opus 4.5+ moved to
21
+ # $5/$25 base, 3x cheaper than Opus 4 / 4.1.
22
+ "claude-opus-4-7": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
23
+ "claude-opus-4-6": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
24
+ "claude-opus-4-5": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
25
+ "claude-opus-4-1": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
26
+ "claude-opus-4": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
27
+ # Claude 4.x Sonnet family.
20
28
  "claude-sonnet-4-6": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
29
+ "claude-sonnet-4-5": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
21
30
  "claude-sonnet-4": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
31
+ # Claude 4.x Haiku family.
22
32
  "claude-haiku-4-5": {"in": 1.00, "out": 5.00, "cache_create": 1.25, "cache_read": 0.10},
23
- # Older fallbacks
33
+ # Older / retired models (Bedrock & Vertex only for 3.5 Haiku).
34
+ "claude-haiku-3-5": {"in": 0.80, "out": 4.00, "cache_create": 1.00, "cache_read": 0.08},
24
35
  "claude-3-5-sonnet": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
25
36
  }
26
37