diff --git a/plugins/crew/.claude-plugin/plugin.json b/plugins/crew/.claude-plugin/plugin.json index a2dbe3e..283122c 100644 --- a/plugins/crew/.claude-plugin/plugin.json +++ b/plugins/crew/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "crew", "displayName": "Crew", - "version": "0.4.0", + "version": "0.4.1", "author": { "name": "4nrry", "url": "https://github.com/4nrry" diff --git a/plugins/crew/README.md b/plugins/crew/README.md index 24b2c92..264a0ea 100644 --- a/plugins/crew/README.md +++ b/plugins/crew/README.md @@ -149,6 +149,19 @@ Python e `unittest`: | delegate depois do endurecimento do guard (allowlist de ferramentas, git so leitura, `.git` e redirect negados, `realpath`), com o mesmo `gate_once.py` | `ok`, 71 s, `finish` negado na 1a tentativa e gate verde na 2a. Nenhuma chamada legitima negada: 7 `run_command`, 3 `replace_file_content`, 2 `view_file`, todos permitidos | | review `--diff HEAD --prompt-file` sobre esse diff | `ok`, 16 s, `approve` sem findings, arvore e `.git` inalterados, so `view_file` | +Na 0.4.1, dois runs com `gemini-4-argon-medium` no agy **1.4.2** (2026-10-18, +repo descartavel com um modulo Python, `unittest` e um checador de formato so +com stdlib no lugar do `ruff`, que nao estava instalado; mesma fatia `slugify` +\+ 3 testes): + +| run | resultado | +|---|---| +| sem `.gitignore` no repo | `ok: false`, culpa do lab: o `unittest` do gate escreveu `__pycache__`, que a checagem de escopo pos-run acusou. O diff do worker estava certo. O Argon pediu um caminho absoluto inventado (um segmento do caminho do repo duplicado) e o guard negou | +| com `__pycache__/` no `.gitignore` | `ok`, 66 s, ~55 mil tokens, gate verde na 1a passada. Diff correto e no estilo do arquivo; uma unica negacao: o worker tentou rodar o checador do gate, que fica fora do repo | + +O preflight de quota checou o grupo "Gemini 4 Argon", nao o "Gemini Models". +Nenhum desses runs mostra que o Argon acerta o que o Flash erra. + ## O que nao foi medido - **Nenhuma comparacao** com o Claude fazendo a mesma tarefa: nem qualidade, @@ -433,6 +446,17 @@ checagem de que o `hooks.json` aponta para um executavel. ## Changelog +**0.4.1** (2026-10-18) + +- Preflight de quota do agy: o grupo era achado pela familia do modelo + (`gemini`), que no agy 1.4.2 casa tambem com o grupo novo "Gemini 4 Argon". + Um Argon esgotado recusava todo run do Flash, e vice-versa, embora no plano + Pro as duas quotas sejam separadas. Agora o grupo e achado pela linha do + modelo (`flash`, `argon`, `sonnet`, `oss`), e pela familia so como fallback. +- Escalada do agy: Flash, depois `gemini-4-argon-medium`, depois + `claude-sonnet-5-5-medium`. O Argon tem quota propria e nao gasta a dos + Claude. Dois runs de fumaca, acima. + **0.4.0** (2026-10-13) - Renomeado de `agy-worker` para `crew`: diretorio, manifesto, comandos diff --git a/plugins/crew/scripts/crew.py b/plugins/crew/scripts/crew.py index 23333f5..51d3556 100755 --- a/plugins/crew/scripts/crew.py +++ b/plugins/crew/scripts/crew.py @@ -1179,14 +1179,30 @@ def parse_models(text: str) -> list: if "\t" in ln and ln.split("\t", 1)[0].strip()] +EFFORT_SUFFIXES = {"low", "medium", "high", "xhigh", "max"} + + +def quota_groups_for(groups: list, model: str) -> list: + """The /usage groups that meter `model`. The family alone ("gemini") is too + wide since agy 1.4.2: "Gemini 4 Argon" is its own group next to "Gemini + Models" (Flash, Pro), and on a Pro plan the two are separate quotas, so an + exhausted Argon must not refuse a Flash run nor the reverse. Match on the + model line first (flash, argon, sonnet, oss), the family only as fallback.""" + def text(g): + return (str(g.get("name", "")) + " " + str(g.get("description", ""))).lower() + parts = model.lower().split("-") + lines = [p for p in parts[1:] if p not in EFFORT_SUFFIXES and not any(c.isdigit() for c in p)] + hits = [g for g in groups if any(re.search(rf"\b{re.escape(p)}\b", text(g)) for p in lines)] + return hits or [g for g in groups if parts[0] in text(g)] + + def evaluate_quota(envelope: dict, model: str, min_quota: float): """None when there is headroom, else a refusal message.""" groups = (((envelope or {}).get("command") or {}).get("data") or {}).get("groups") if not isinstance(groups, list): return "nao consegui ler os grupos de quota de `agy -p /usage --output-format json`" family = model.split("-", 1)[0].lower() - hits = [g for g in groups if family in (str(g.get("name", "")) + " " - + str(g.get("description", ""))).lower()] + hits = quota_groups_for(groups, model) if not hits: return f"nenhum grupo de quota menciona {family!r}; formato do /usage mudou?" for g in hits: @@ -3048,6 +3064,20 @@ def cphook(event, payload): check(msg and "esgotada" in msg and "2026-10-15" in msg, "quota claude esgotada") check(evaluate_quota(usage, "gpt-oss-120b-medium", 0.05), "gpt no mesmo grupo esgotado") check(evaluate_quota({}, "gemini-x", 0.05), "usage ilegivel recusa") + # agy 1.4.2 (2026-10-18) adds Argon as its own group; on a Pro plan it is a separate quota + argon = {"name": "Gemini 4 Argon", "description": "For paid Pro plans, Argon quota is separate. Higher " + "Argon quota (included as part of the larger Gemini quota bucket) is available on Ultra plans.", + "buckets": [{"name": "Gemini 4 Argon Weekly Limit", "remaining_fraction": 0.01, + "reset_time": "2026-10-25T01:46:00Z"}]} + groups = usage["command"]["data"]["groups"] + groups.append(argon) + check(evaluate_quota(usage, "gemini-3.8-flash-high", 0.05) is None, "argon esgotado nao barra o flash") + msg = evaluate_quota(usage, "gemini-4-argon-medium", 0.05) + check(msg and "Gemini 4 Argon" in msg, "argon esgotado barra o argon") + argon["buckets"][0]["remaining_fraction"] = 0.9 + groups[0]["buckets"][0]["remaining_fraction"] = 0 + check(evaluate_quota(usage, "gemini-4-argon-high", 0.05) is None, "flash esgotado nao barra o argon") + check(evaluate_quota(usage, "gemini-3.8-flash-low", 0.05), "flash esgotado barra o flash") models = parse_models("gemini-3.8-flash-low\tGemini 3.8 Flash (Low)\nFetching available models...\n") check(models == ["gemini-3.8-flash-low"], "parse de agy models") diff --git a/plugins/crew/skills/agy/SKILL.md b/plugins/crew/skills/agy/SKILL.md index 22d2bce..8bbe749 100644 --- a/plugins/crew/skills/agy/SKILL.md +++ b/plugins/crew/skills/agy/SKILL.md @@ -1,6 +1,6 @@ --- name: agy -description: Especificos do backend agy (Antigravity CLI, Gemini) do plugin crew - flags do run, modelo padrao gemini-3.8-flash-high, escalada so para claude-sonnet-5-5-medium e nunca Opus, preflight de quota, hooks em .agents/hooks.json e os comandos que o agy joga para segundo plano. Use quando for delegar uma fatia ou pedir review pelo agy. +description: Especificos do backend agy (Antigravity CLI, Gemini) do plugin crew - flags do run, modelo padrao gemini-3.8-flash-high, escalada para gemini-4-argon-medium e depois claude-sonnet-5-5-medium, nunca Opus, preflight de quota, hooks em .agents/hooks.json e os comandos que o agy joga para segundo plano. Use quando for delegar uma fatia ou pedir review pelo agy. --- # crew pelo agy @@ -28,7 +28,12 @@ nenhuma no lab: nao conte com ele. - Comece no `gemini-3.8-flash-high` (padrao). - Se o Flash nao der conta de uma fatia (gate vermelho ate o limite, ou diff - que nao sobrevive a revisao), suba para `claude-sonnet-5-5-medium`. + que nao sobrevive a revisao), suba para `gemini-4-argon-medium`. O Argon + tem quota semanal propria no plano Pro: nao gasta a dos Gemini Flash nem a + dos Claude. `-high` so se o `-medium` tambem falhar. +- Se o Argon tambem nao der conta, `claude-sonnet-5-5-medium`. +- O Argon so passou por fumaca (n=1, fatia trivial; ver "Smoke tests" no README): nada + diz ainda que ele resolve o que o Flash erra. Revise o diff igual. - **Nunca Opus pelo agy.** Os modelos Claude do agy dividem uma quota semanal, e o Opus a esgota em poucas fatias. - O modelo e validado contra `agy models` antes de rodar. @@ -37,7 +42,11 @@ nenhuma no lab: nao conte com ele. O preflight le `agy -p /usage` (responde sem turno de modelo) e recusa, saida 2, se o grupo do modelo tiver menos que `min_quota` (padrao 0.05) restante, -dizendo quando renova. `--no-quota-probe` pula. Com a quota esgotada, o +dizendo quando renova. O grupo e achado pela linha do modelo (`flash`, +`argon`, `sonnet`, `oss`) no nome ou na descricao do grupo, e so pela familia +(`gemini`, `claude`) se nenhum grupo citar a linha: no agy 1.4.2 o Argon tem +grupo proprio ao lado de "Gemini Models", e no plano Pro as duas quotas sao +separadas. `--no-quota-probe` pula. Com a quota esgotada, o `opencode` e a alternativa gratis (skill `crew:opencode`). ## Antes do primeiro run