diff --git a/.agents/shell/worktree.sh b/.agents/shell/worktree.sh index 98f6dbca..a9d45c67 100644 --- a/.agents/shell/worktree.sh +++ b/.agents/shell/worktree.sh @@ -29,26 +29,26 @@ # source /.agents/shell/worktree.sh # # Uso (terminal interativo): -# worktree next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba] +# worktree next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # CLAIMA a próxima Issue claimável e cria/reutiliza o # worktree dela, cd para dentro por padrão; --issue N # claima a Issue direcionada ou reabre a já claimada -# (sem re-claim); --stay não troca; --cheap/--pro/--zen/--go/--alibaba +# (sem re-claim); --stay não troca; --cheap/--pro/--zen/--go/--alibaba/--glm/--free # escolhe o modelo por invocação (sem flag o preset permanece; at-most-one) -# worktree plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba] +# worktree plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # cria um worktree de planejamento do /plan-issue # DIFERENTE a cada chamada (sessões paralelas): com bag, # branch plans/plan-issue- (sufixo -2/-3 se o nome # já existir), sem bag o próximo plans/plan-issue- # sequencial; cd para dentro dele por padrão; --stay não # troca; flag de modelo como no `next` -# worktree new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba] +# worktree new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # cria um worktree NEUTRO (sem função pré-definida) # DIFERENTE a cada chamada: com bag, branch work/ # (sufixo -2/-3 se o nome já existir), sem bag o próximo # work/ sequencial; cd para dentro dele por padrão; # --stay não troca; flag de modelo como no `next` -# worktree fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba] +# worktree fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # cria um worktree de CORREÇÃO DE BUG (skill /bug-fix) # DIFERENTE a cada chamada: com bag (a descrição do bug), # branch fix/ (sufixo -2/-3 se o nome já existir), diff --git a/.agents/skills/local-database/SKILL.md b/.agents/skills/local-database/SKILL.md index 65c9165f..7c8f80c1 100644 --- a/.agents/skills/local-database/SKILL.md +++ b/.agents/skills/local-database/SKILL.md @@ -26,7 +26,7 @@ VMs Cloud **não rodam** `docker compose` / `pnpm db:start`. Postgres nativo: `. ## Per-worktree environments (`pnpm worktree next`) -Parallel agents must not fight over port 3000, the shared `teqo_test`, or a second Postgres container. `pnpm worktree next [--stay] [--cheap|--pro|--zen|--go|--alibaba]` provisions each worktree with a deterministic isolated env (`next`/`plan`/`new` print `cd ` by default — apply it, or pass `--stay` to suppress; `--cheap/--pro/--zen/--go/--alibaba` selects the model per invocation via `WORKTREE_MODEL_MAP`): +Parallel agents must not fight over port 3000, the shared `teqo_test`, or a second Postgres container. `pnpm worktree next [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]` provisions each worktree with a deterministic isolated env (`next`/`plan`/`new` print `cd ` by default — apply it, or pass `--stay` to suppress; `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` selects the model per invocation via `WORKTREE_MODEL_MAP`): - `slot` = numeric part of the issue code (`C15` → 15, `B164` → 164; hash fallback without digits; bumped on collision among live worktrees). - Dev server port `3100+slot`; databases `teqo_wt` (dev) and `teqo_wt_test` (tests), created on the **one shared container** with the full migration chain **and the minimal seed** applied (one-time, ~30 s each; OPS28 parity with CI, which runs `migrate → seed:minimal` before e2e — a worktree's `pnpm test:e2e` mirrors CI). diff --git a/.agents/skills/worktree-next-issue/SKILL.md b/.agents/skills/worktree-next-issue/SKILL.md index 1acd6d59..93060ed1 100644 --- a/.agents/skills/worktree-next-issue/SKILL.md +++ b/.agents/skills/worktree-next-issue/SKILL.md @@ -19,9 +19,9 @@ Prepara o ambiente git para a próxima Issue da fila de claim — **o claim é p A lógica determinística (fila → código+slug → branch → worktree) vive em **`scripts/worktree.mjs`** — fonte única, coberta por `tests/unit/worktree.unit.spec.ts`. Não a reescreva à mão aqui. ```bash -pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] # CLAIMA a Issue + cria worktree de origin/main + provisiona o ambiente -pnpm worktree plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] # worktree de PLANEJAMENTO (/plan-issue): um DIFERENTE por invocação -pnpm worktree new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] # worktree NEUTRO (sem função pré-definida): um DIFERENTE por invocação +pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # CLAIMA a Issue + cria worktree de origin/main + provisiona o ambiente +pnpm worktree plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # worktree de PLANEJAMENTO (/plan-issue): um DIFERENTE por invocação +pnpm worktree new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] # worktree NEUTRO (sem função pré-definida): um DIFERENTE por invocação pnpm worktree kill [--force] # destrói o worktree atual + remove seus bancos gerados ``` @@ -29,9 +29,9 @@ No opencode, isso é o comando **`/worktree next`** / **`/worktree kill`** (`.op `plan` é o primo do `next`: worktree de **planejamento** para rodar a skill `/plan-issue` sem ocupar o main. **Cada invocação cria um DIFERENTE** (sessões paralelas): com `bag` opcional → branch `plans/plan-issue-` (sufixo `-2`/`-3` se o nome já estiver vivo); sem `bag` → próximo sequencial `plans/plan-issue-` livre. Não é nomeado por Issue nenhuma — proposital, para um `next` posterior da próxima Issue nunca colidir em branch nem em slot (prefixo minúsculo `plans/…` vs branch `-` sempre uppercase-led). `new` é o irmão **neutro** (sem função pré-definida — explorar ideia, conversar, planejar sem registrar): mesma semântica de "um DIFERENTE por invocação", branch `work/` (sufixo `-2`/`-3` em colisão) ou `work/` sequencial, prefixo `work/…` que não colide com `next` nem `plan`. O fluxo desta skill (fila → próxima Issue → implementação) é só `next`. -**Default-go:** `next`, `plan` e `new` imprimem `cd ` na última linha **por padrão**; `--stay` suprime; modelos por invocação via `--cheap/--pro/--zen/--go/--alibaba` (mapa fixo `WORKTREE_MODEL_MAP`, at-most-one; sem flag o preset permanece); `--go` remapeado em OPS93 para o provider OpenCode Go e em OPS95 para `opencode-go/hy3` (antes no-op do OPS24). No terminal interativo, use a função `worktree()` de **`.agents/shell/worktree.sh`** (uma linha de `source` no profile) para o `cd` ser aplicado de verdade no shell que te chamou — node não consegue mudar o cwd do shell pai. `kill` também imprime `cd
` no fim (a sessão nunca fica num diretório destruído). +**Default-go:** `next`, `plan` e `new` imprimem `cd ` na última linha **por padrão**; `--stay` suprime; modelos por invocação via `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` (mapa fixo `WORKTREE_MODEL_MAP`, at-most-one; sem flag o preset permanece); `--go` remapeado em OPS93 para o provider OpenCode Go e em OPS95 para `opencode-go/hy3` (antes no-op do OPS24). No terminal interativo, use a função `worktree()` de **`.agents/shell/worktree.sh`** (uma linha de `source` no profile) para o `cd` ser aplicado de verdade no shell que te chamou — node não consegue mudar o cwd do shell pai. `kill` também imprime `cd
` no fim (a sessão nunca fica num diretório destruído). -**Launch do opencode (OPS26 + OPS33 + OPS31 + OPS93 + OPS95):** só a função shell marca `TEQO_WORKTREE_TERMINAL=1`; com o marcador, `next`/`plan`/`new` imprimem também a diretiva `launch opencode --model --auto [--prompt "/work-issue --issue "]` **antes** do `cd`, e a função a executa depois do cd — `next` abre o TUI com `/work-issue --issue ` já enviado (a Issue claimada vai no prompt; a skill lê o resto do GitHub); `plan` abre com `/plan-issue` já enviado (OPS31: o TUI já cai no fluxo de planejamento); `new` abre sem `--prompt` ("apenas conversar"). Sem `--variant` na diretiva (OPS95: o yargs do TUI rejeita o flag desconhecido e só imprime o helper — variantes ficam na config global do opencode, selecionáveis via Ctrl+T; `opencode run --variant max` segue sendo a via CLI para runs headless). Modelo por invocação via `--cheap` (cheapestinference/deepseek-v4-flash), `--pro` (deepseek/deepseek-v4-pro), `--zen` (opencode-go/ox-alpha-free), `--go` (opencode-go/hy3), `--alibaba` (alibaba-token-plan/deepseek-v4-flash) — valores corrigidos no OPS95; sem flag o preset `deepseek/deepseek-v4-flash` permanece. Sem `exec`: sair do opencode volta ao shell no worktree. Presets e mapa são constantes em `scripts/lib/worktree.mjs`. **O comando `/worktree` do opencode (e qualquer automação sem o marcador) nunca lança o TUI.** +**Launch do opencode (OPS26 + OPS33 + OPS31 + OPS93 + OPS95):** só a função shell marca `TEQO_WORKTREE_TERMINAL=1`; com o marcador, `next`/`plan`/`new` imprimem também a diretiva `launch opencode --model --auto [--prompt "/work-issue --issue "]` **antes** do `cd`, e a função a executa depois do cd — `next` abre o TUI com `/work-issue --issue ` já enviado (a Issue claimada vai no prompt; a skill lê o resto do GitHub); `plan` abre com `/plan-issue` já enviado (OPS31: o TUI já cai no fluxo de planejamento); `new` abre sem `--prompt` ("apenas conversar"). Sem `--variant` na diretiva (OPS95: o yargs do TUI rejeita o flag desconhecido e só imprime o helper — variantes ficam na config global do opencode, selecionáveis via Ctrl+T; `opencode run --variant max` segue sendo a via CLI para runs headless). Modelo por invocação via `--cheap` (cheapestinference/deepseek-v4-flash), `--pro` (deepseek/deepseek-v4-pro), `--zen` (opencode-go/ox-alpha-free), `--go` (opencode-go/hy3), `--alibaba` (alibaba-token-plan/deepseek-v4-flash) — valores corrigidos no OPS95 — e `--glm` (opencode-go/glm-5.3-flash, OPS100), `--free` (openrouter/openrouter/free, OPS100); sem flag o preset `deepseek/deepseek-v4-flash` permanece. Sem `exec`: sair do opencode volta ao shell no worktree. Presets e mapa são constantes em `scripts/lib/worktree.mjs`. **O comando `/worktree` do opencode (e qualquer automação sem o marcador) nunca lança o TUI.** ## Fluxo quando invocado como skill (agentes que não têm opencode) diff --git a/.opencode/commands/worktree.md b/.opencode/commands/worktree.md index 7cf40046..e47ac866 100644 --- a/.opencode/commands/worktree.md +++ b/.opencode/commands/worktree.md @@ -1,13 +1,13 @@ --- -description: Claima a próxima Issue (next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba]), cria o worktree dela e provisiona o ambiente; também cria worktree de planejamento (plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]), worktree neutro (new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]), worktree de correção de bug (fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]) ou destrói o atual (kill [--force]) +description: Claima a próxima Issue (next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]), cria o worktree dela e provisiona o ambiente; também cria worktree de planejamento (plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]), worktree neutro (new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]), worktree de correção de bug (fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]) ou destrói o atual (kill [--force]) --- Rode o script determinístico abaixo (não improvise a lógica) e reporte o resultado de forma concisa. -- `next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba]`: **claima** a próxima Issue claimável da fila (mesma fila/ordem e lock otimista de `pnpm agent:claim`) e cria (ou reutiliza) o worktree dela. Claim falhou → reporte o motivo — não há worktree. `--issue N` claima a Issue direcionada (`ready`) ou **reabre** uma já claimada (`in-progress`, sem re-claim). A saída avisa "já claimada — NÃO rodar `pnpm agent:claim`". Por padrão o script imprime `cd ` na última linha — aplique-o na sessão de shell atual (`cd `) e reporte o novo diretório. `--stay` suprime o `cd` (não troque de diretório) mas o claim ainda acontece. `--cheap/--pro/--zen/--go/--alibaba` escolhe o modelo por invocação no mapa fixo `WORKTREE_MODEL_MAP` (cheap=cheapestinference/deepseek-v4-flash, pro=deepseek/deepseek-v4-pro, zen=opencode-go/ox-alpha-free, go=opencode-go/hy3, alibaba=alibaba-token-plan/deepseek-v4-flash); at-most-one (múltiplas → erro). -- `plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]`: cria um worktree de planejamento **diferente a cada invocação** (branch `plans/plan-issue-`, ou `plans/plan-issue-` sequencial sem bag; sufixo `-2`/`-3` em colisão) para rodar `/plan-issue` sem ocupar o main; nunca conflita com `next`. Não claima nada. Mesmo contrato de `cd` do `next`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. -- `new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]`: cria um worktree **neutro** (sem função pré-definida — explorar ideia, conversar, planejar sem registrar nada) **diferente a cada invocação** (branch `work/`, ou `work/` sequencial sem bag; sufixo `-2`/`-3` em colisão); o prefixo minúsculo `work/…` nunca conflita com `next` nem `plan`. Não claima nada. Mesmo contrato de `cd` do `plan`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. -- `fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba]`: cria um worktree de **correção de bug** (skill `/bug-fix`) **diferente a cada invocação** (branch `fix/`, ou `fix/` sequencial sem bag; sufixo `-2`/`-3` em colisão); o prefixo minúsculo `fix/…` nunca conflita com `next`, `plan` nem `new`. **Não claima nem cria Issues** — o registro do bug é o post-mortem da skill. O bag é a descrição do bug: no terminal, o launch envia `--prompt "/bug-fix "` (a descrição chega com a skill). Mesmo contrato de `cd` do `plan`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. +- `next [--issue N] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`: **claima** a próxima Issue claimável da fila (mesma fila/ordem e lock otimista de `pnpm agent:claim`) e cria (ou reutiliza) o worktree dela. Claim falhou → reporte o motivo — não há worktree. `--issue N` claima a Issue direcionada (`ready`) ou **reabre** uma já claimada (`in-progress`, sem re-claim). A saída avisa "já claimada — NÃO rodar `pnpm agent:claim`". Por padrão o script imprime `cd ` na última linha — aplique-o na sessão de shell atual (`cd `) e reporte o novo diretório. `--stay` suprime o `cd` (não troque de diretório) mas o claim ainda acontece. `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` escolhe o modelo por invocação no mapa fixo `WORKTREE_MODEL_MAP` (cheap=cheapestinference/deepseek-v4-flash, pro=deepseek/deepseek-v4-pro, zen=opencode-go/ox-alpha-free, go=opencode-go/hy3, alibaba=alibaba-token-plan/deepseek-v4-flash, glm=opencode-go/glm-5.3-flash, free=openrouter/openrouter/free); at-most-one (múltiplas → erro). +- `plan [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`: cria um worktree de planejamento **diferente a cada invocação** (branch `plans/plan-issue-`, ou `plans/plan-issue-` sequencial sem bag; sufixo `-2`/`-3` em colisão) para rodar `/plan-issue` sem ocupar o main; nunca conflita com `next`. Não claima nada. Mesmo contrato de `cd` do `next`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. +- `new [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`: cria um worktree **neutro** (sem função pré-definida — explorar ideia, conversar, planejar sem registrar nada) **diferente a cada invocação** (branch `work/`, ou `work/` sequencial sem bag; sufixo `-2`/`-3` em colisão); o prefixo minúsculo `work/…` nunca conflita com `next` nem `plan`. Não claima nada. Mesmo contrato de `cd` do `plan`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. +- `fix [bag] [--stay] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`: cria um worktree de **correção de bug** (skill `/bug-fix`) **diferente a cada invocação** (branch `fix/`, ou `fix/` sequencial sem bag; sufixo `-2`/`-3` em colisão); o prefixo minúsculo `fix/…` nunca conflita com `next`, `plan` nem `new`. **Não claima nem cria Issues** — o registro do bug é o post-mortem da skill. O bag é a descrição do bug: no terminal, o launch envia `--prompt "/bug-fix "` (a descrição chega com a skill). Mesmo contrato de `cd` do `plan`: aplique a última linha `cd ` por padrão; `--stay` suprime; flag de modelo como no `next`. - `kill [--force]`: destrói o worktree em que você está e remove seus bancos. O script imprime `cd
` na última linha — aplique-o (`cd
`) para a sessão sair do diretório destruído. > **Este comando roda SEM o marcador `TEQO_WORKTREE_TERMINAL`, então nunca recebe a diretiva `launch`** — só o `cd`. O launch do opencode (OPS26/OPS33+OPS93+OPS95, sem `--variant` — o TUI rejeita o flag) acontece apenas na função `worktree()` de `.agents/shell/worktree.sh` (terminal interativo); nunca abra um TUI aninhado a partir daqui. diff --git a/docs/changelog/2026-08-27-ops100.md b/docs/changelog/2026-08-27-ops100.md new file mode 100644 index 00000000..a21ab786 --- /dev/null +++ b/docs/changelog/2026-08-27-ops100.md @@ -0,0 +1,29 @@ +# OPS100 — Worktree model flags `--glm` and `--free` + +**Date:** 2026-08-27 +**Issue:** — (direto do humano, config-only) +**Type:** ops, config + +## Summary + +Two new model flags in the `pnpm worktree` per-invocation menu (`next`/`plan`/`new`/`fix`): `--glm` → `opencode-go/glm-5.3-flash` (GLM-5.3-Flash via provider Opencode Go) and `--free` → `openrouter/openrouter/free` (Free Models Router via OpenRouter). Menu goes from 5 to 7 named flags; same mechanism (edit the constant/map, OPS26/OPS93), no behavior change without flags. + +## Changes + +### Scripts + +- `scripts/lib/worktree.mjs` — `WORKTREE_MODEL_MAP` gains `glm` and `free` entries; conflict error message in `resolveWorktreeModel` lists the two new flags; docblocks updated +- `scripts/worktree.mjs` — docblock + `--help` flag lists synchronized (pipe and slash forms) with the two new model IDs in the map prose + +### Tests + +- `tests/unit/worktree.unit.spec.ts` — map pin updated (7-flag map + `WORKTREE_MODEL_FLAGS` pin + single-flag resolution for `glm`/`free`) + +### Documentation + +- `.agents/shell/worktree.sh`, `.agents/skills/worktree-next-issue/SKILL.md`, `.agents/skills/local-database/SKILL.md`, `.opencode/commands/worktree.md` — flag lists and per-flag model values synchronized + +## Verification + +- `opencode models` — confirms `opencode-go/glm-5.3-flash` and `openrouter/openrouter/free` exist (models.dev display names: "GLM-5.3-Flash (2x usage)" / "Free Models Router") +- `pnpm gate:fast` — green (lint, format, typecheck, unit) diff --git a/scripts/lib/worktree.mjs b/scripts/lib/worktree.mjs index 8a040315..34e74c7d 100644 --- a/scripts/lib/worktree.mjs +++ b/scripts/lib/worktree.mjs @@ -28,22 +28,22 @@ export const WORKTREE_TERMINAL_ENV = 'TEQO_WORKTREE_TERMINAL' * direto porque o gateway está sem créditos (erros "positive credit balance" * em 24/08/2026) e porque unificar o default reduz a sobrescrita confusa de * seleção de modelo do TUI (opencode issues #8349/#13456). OPS93: com - * `--cheap/--pro/--zen/--go/--alibaba` o mapa `WORKTREE_MODEL_MAP` escolhe o - * modelo por invocação; sem flag o preset permanece. OPS95: sem `--variant` - * na diretiva (o TUI rejeita o flag) — variantes ficam na config global da - * máquina, via Ctrl+T. + * `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` o mapa `WORKTREE_MODEL_MAP` + * escolhe o modelo por invocação; sem flag o preset permanece. OPS95: sem + * `--variant` na diretiva (o TUI rejeita o flag) — variantes ficam na config + * global da máquina, via Ctrl+T. */ export const OPENCODE_PRESET_MODEL = process.env.OPENCODE_WORKTREE_MODEL || 'deepseek/deepseek-v4-flash' /** - * Per-invocation model map — fixed menu of 5 named flags (OPS93; values - * corrected in OPS95 after the OPS93 delivery shipped wrong IDs). The - * directive picks `WORKTREE_MODEL_MAP[flag]` when a single flag is present, - * otherwise falls back to `OPENCODE_PRESET_MODEL`. No `--variant` is emitted - * (the TUI yargs rejects the flag — OPS95): variants live on the machine's - * global config, selectable via Ctrl+T (`opencode run --variant max` remains - * the headless path). + * Per-invocation model map — fixed menu of named flags (OPS93; values + * corrected in OPS95 after the OPS93 delivery shipped wrong IDs; OPS100 adds + * `--glm` and `--free`). The directive picks `WORKTREE_MODEL_MAP[flag]` when + * a single flag is present, otherwise falls back to `OPENCODE_PRESET_MODEL`. + * No `--variant` is emitted (the TUI yargs rejects the flag — OPS95): + * variants live on the machine's global config, selectable via Ctrl+T + * (`opencode run --variant max` remains the headless path). */ export const WORKTREE_MODEL_MAP = { cheap: 'cheapestinference/deepseek-v4-flash', @@ -51,6 +51,8 @@ export const WORKTREE_MODEL_MAP = { zen: 'opencode-go/ox-alpha-free', go: 'opencode-go/hy3', alibaba: 'alibaba-token-plan/deepseek-v4-flash', + glm: 'opencode-go/glm-5.3-flash', + free: 'openrouter/openrouter/free', } /** Set of flag names that select a model (keys of WORKTREE_MODEL_MAP). */ @@ -65,7 +67,7 @@ export const resolveWorktreeModel = (flags = {}) => { const active = [...WORKTREE_MODEL_FLAGS].filter((flag) => flags[flag]) if (active.length > 1) { throw new Error( - `Flags de modelo conflitantes: --${active.join(' --')} (use apenas um de --cheap/--pro/--zen/--go/--alibaba)`, + `Flags de modelo conflitantes: --${active.join(' --')} (use apenas um de --cheap/--pro/--zen/--go/--alibaba/--glm/--free)`, ) } if (active.length === 1) return WORKTREE_MODEL_MAP[active[0]] @@ -187,7 +189,7 @@ const namespaceBranchName = ({ prefix, bag = '', taken = new Set(), fallback }) * --auto [--prompt ""]` (OPS95: no `--variant` — the TUI yargs * rejects the unknown flag and the helper prints instead of opening; modelo * vem do mapa `WORKTREE_MODEL_MAP` quando a flag `--cheap/--pro/--zen/ - * --go/--alibaba` está presente, senão do preset). The shell function + * --go/--alibaba/--glm/--free` está presente, senão do preset). The shell function * (`.agents/shell/worktree.sh`) applies the `cd` first, then tokenizes and * executes this line (xargs — quote-aware, never eval) — the dir is always * `/`, so the line never needs quoting diff --git a/scripts/worktree.mjs b/scripts/worktree.mjs index a0dfb423..f6696b46 100644 --- a/scripts/worktree.mjs +++ b/scripts/worktree.mjs @@ -2,7 +2,7 @@ * `pnpm worktree` — worktree management determinístico em torno da fila de * claim do projeto (mesma fila de `agent:claim` / agent pool). * - * pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] + * pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] * claima a próxima Issue claimável ANTES de criar * o worktree a partir de origin/main (mesma fila * e lock otimista de `pnpm agent:claim`; claim @@ -19,13 +19,14 @@ * terminal interativo: função `worktree()` em * `.agents/shell/worktree.sh`, sourced no profile). * `--stay` suprime a linha `cd` (o claim ainda - * acontece); `--cheap/--pro/--zen/--go/--alibaba` + * acontece); `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` * escolhe o modelo por invocação no mapa fixo * `WORKTREE_MODEL_MAP` (cheap=cheapestinference/ * deepseek-v4-flash, pro=deepseek/deepseek-v4-pro, * zen=opencode-go/ox-alpha-free, go=opencode-go/ - * hy3, alibaba=alibaba-token-plan/deepseek-v4-flash; - * OPS95) — sem flag o preset + * hy3, alibaba=alibaba-token-plan/deepseek-v4-flash, + * glm=opencode-go/glm-5.3-flash, free=openrouter/ + * openrouter/free; OPS95 + OPS100) — sem flag o preset * `deepseek/deepseek-v4-flash` permanece. * Chamado do terminal interativo (com * `TEQO_WORKTREE_TERMINAL=1`, que só a função shell @@ -59,7 +60,7 @@ * recusa a abrir com `{file:…}` pendurado. * `--no-migrate` pula migrations E o seed (que * depende do catálogo migrado). - * pnpm worktree plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] + * pnpm worktree plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] * cria um worktree de PLANEJAMENTO novo para rodar * a skill /plan-issue sem ocupar o main — cada * invocação cria UM DIFERENTE, para sessões de @@ -75,7 +76,7 @@ * abre no fluxo de planejamento, sem digitação) e * `--model ` quando a flag de modelo está * presente. - * pnpm worktree new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] + * pnpm worktree new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] * cria um worktree NEUTRO novo — sem função * pré-definida (explorar ideia, conversar, ou * planejar sem registrar nada): cada invocação @@ -91,11 +92,11 @@ * `--model ` quando a flag de modelo está * presente. * `--stay` suprime a linha `cd` e a diretiva; - * `--cheap/--pro/--zen/--go/--alibaba` escolhe o + * `--cheap/--pro/--zen/--go/--alibaba/--glm/--free` escolhe o * modelo por invocação (sem flag o preset permanece). * Migrations E seed mínimo nos dois bancos, como * o `next`/`plan` (OPS28). - * pnpm worktree fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] + * pnpm worktree fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] * cria um worktree de CORREÇÃO DE BUG (skill * /bug-fix) DIFERENTE a cada invocação: com bag, * branch `fix/` (e `-2`, `-3`, … se o nome @@ -856,9 +857,11 @@ const subcommand = positional[0] if (!subcommand) { console.log( - 'Uso: pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] | plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] | new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] | fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba] | kill [--force]', + 'Uso: pnpm worktree next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] | plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] | new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] | fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free] | kill [--force]', + ) + console.log( + ' next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]', ) - console.log(' next [--issue N] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba]') console.log(' CLAIMA a próxima Issue claimável (mesma fila/ordem e lock otimista do') console.log(' `pnpm agent:claim`) e cria o worktree dela (branch -),') console.log(' provisionando o ambiente isolado: porta de dev + bancos próprios;') @@ -881,9 +884,11 @@ if (!subcommand) { ' informada); --stay suprime cd e launch (o claim ainda acontece); --no-migrate pula migrations e o', ) console.log( - ' seed mínimo (db:seed:minimal) nos bancos novos (OPS28: paridade com a CI); at-most-one de --cheap/--pro/--zen/--go/--alibaba (múltiplas → erro)', + ' seed mínimo (db:seed:minimal) nos bancos novos (OPS28: paridade com a CI); at-most-one de --cheap/--pro/--zen/--go/--alibaba/--glm/--free (múltiplas → erro)', + ) + console.log( + `\n plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`, ) - console.log(`\n plan [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba]`) console.log( ' cria um worktree de planejamento DIFERENTE a cada invocação (sessões /plan-issue', ) @@ -895,7 +900,9 @@ if (!subcommand) { console.log( ' mesma diretiva `launch` com --prompt /plan-issue enviado (abre no fluxo de planejamento, sem digitação) e --model quando a flag está presente', ) - console.log(`\n new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba]`) + console.log( + `\n new [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`, + ) console.log(' cria um worktree NEUTRO (sem função pré-definida) DIFERENTE a cada invocação:') console.log(' com bag, branch work/ (sufixo -2/-3 se o nome já existir); sem bag, o') console.log(' próximo work/ sequencial livre; o prefixo minúsculo work/… nunca colide com') @@ -903,7 +910,9 @@ if (!subcommand) { console.log( ' terminal, mesma diretiva `launch` porém sem --prompt (apenas conversar) e --model quando a flag está presente', ) - console.log(`\n fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba]`) + console.log( + `\n fix [bag] [--stay] [--no-migrate] [--cheap|--pro|--zen|--go|--alibaba|--glm|--free]`, + ) console.log(' cria um worktree de CORREÇÃO DE BUG (skill /bug-fix) DIFERENTE a cada') console.log(' invocação: com bag (a descrição do bug), branch fix/ (sufixo -2/-3 se o') console.log(' nome já existir); sem bag, o próximo fix/ sequencial livre; o prefixo') diff --git a/tests/unit/worktree.unit.spec.ts b/tests/unit/worktree.unit.spec.ts index cab8a183..0acab872 100644 --- a/tests/unit/worktree.unit.spec.ts +++ b/tests/unit/worktree.unit.spec.ts @@ -288,16 +288,20 @@ describe('opencodeLaunchDirective (terminal-only opencode launch, OPS26 + OPS33 }) }) -describe('resolveWorktreeModel + WORKTREE_MODEL_MAP (OPS93 menu, OPS95 values)', () => { - it('pins the 5-flag map — cheap/pro/zen/go/alibaba', () => { +describe('resolveWorktreeModel + WORKTREE_MODEL_MAP (OPS93 menu, OPS95 values, OPS100 glm/free)', () => { + it('pins the 7-flag map — cheap/pro/zen/go/alibaba/glm/free', () => { expect(WORKTREE_MODEL_MAP).toEqual({ cheap: 'cheapestinference/deepseek-v4-flash', pro: 'deepseek/deepseek-v4-pro', zen: 'opencode-go/ox-alpha-free', go: 'opencode-go/hy3', alibaba: 'alibaba-token-plan/deepseek-v4-flash', + glm: 'opencode-go/glm-5.3-flash', + free: 'openrouter/openrouter/free', }) - expect(WORKTREE_MODEL_FLAGS).toEqual(new Set(['cheap', 'pro', 'zen', 'go', 'alibaba'])) + expect(WORKTREE_MODEL_FLAGS).toEqual( + new Set(['cheap', 'pro', 'zen', 'go', 'alibaba', 'glm', 'free']), + ) }) it('no flag → preset', () => { @@ -312,6 +316,8 @@ describe('resolveWorktreeModel + WORKTREE_MODEL_MAP (OPS93 menu, OPS95 values)', expect(resolveWorktreeModel({ zen: true })).toBe(WORKTREE_MODEL_MAP.zen) expect(resolveWorktreeModel({ go: true })).toBe(WORKTREE_MODEL_MAP.go) expect(resolveWorktreeModel({ alibaba: true })).toBe(WORKTREE_MODEL_MAP.alibaba) + expect(resolveWorktreeModel({ glm: true })).toBe(WORKTREE_MODEL_MAP.glm) + expect(resolveWorktreeModel({ free: true })).toBe(WORKTREE_MODEL_MAP.free) }) it('multiple flags → throws (fail-high, never guess)', () => {