teqo-backup/docs/plans/ops110-attach-detach-runs-agent.md

7.7 KiB
Raw Permalink Blame History

OPS110 — Acompanhar runs longos de agente por attach/detach, sem manter terminal aberto

Status: rascunho Atualizado em: 2026-09-15 Issue: #1019 Priority: P2 Impeccable: A — N/A (ferramenta/ops; sem UI de produto) Rascunho UI: N/A — sem UI Appetite: ~1–2 dias eng Responsável: —

Intenção

Hoje cada run de agente exige presença: o opencode roda no terminal do workstation e, se o TUI fechar (ou a sessão SSH cair), o run para. O fsolla quer largar um /work-issue ou /plan-issue longo no workstation e ir embora — almoço, reunião, fim de expediente — acompanhando do laptop ou do celular, entrando e saindo da sessão quantas vezes quiser enquanto o agente trabalha.

Não é um pedido de "rodar agentes em background" solto: é o mesmo run de hoje, com o ciclo de vida desacoplado do terminal que o observa. O que os agentes fazem não muda; muda como o humano os acompanha. O painel de Issues (OPS109) também quer abrir a sessão do run daquela Issue — para isso este item precisa deixar a sessão endereçável, não só persistente.

Persona e fluxo

  • Persona / contexto: fsolla no workstation, com worktrees de agente ativos; longe dele, no laptop ou celular, por SSH ou rede confiável. Não quer vigiar em tempo real — quer poder espiar, sair e voltar.
  • Job principal: iniciar um run longo, desconectar, e (re)entrar na sessão de outro dispositivo quando quiser, sem interromper o agente.
  • Fluxo desejado:
    1. Dispara o run do jeito que já dispara hoje (worktree + skill, ex. /work-issue).
    2. Fecha o terminal do workstation ou perde o SSH; o agente continua trabalhando.
    3. Do laptop ou celular, entra na sessão existente e vê o histórico/estado do agente; acompanha ou digita se quiser.
    4. Sai de novo — quantas vezes quiser — sem matar o run.
    5. Quando decidir encerrar, encerra de forma explícita, nunca por acidente ao fechar o cliente.
  • Anti-goals de produto:
    • Não vira pool/supervisor de agentes (o pool morreu na OPS65; não ressuscitar).
    • Não automatiza produção nem cria caminho que burle gates humanos (PR/CI/approval).
    • Não cria um segundo jeito de iniciar sessão que ignore o worktree/claim vigente.
    • Não exige terminal aberto no workstation nem processo pendurado em SSH.
    • Não abre porta pública na internet.

Objetivo e aceite

  • O run continua trabalhando quando nenhum cliente está olhando (nenhum terminal/SSH aberto no workstation).
  • (Re)entrar na sessão de outro dispositivo retoma exatamente onde estava — mesma sessão, mesmo worktree, mesmo histórico.
  • Sair do cliente nunca é o mesmo que encerrar o run; encerrar é ato explícito.
  • Nada novo escutando além do loopback sem credencial: se alguma superfície passar de 127.0.0.1, exige autenticação e só em rede confiável (SSH/tailnet) — fail-closed sem credencial.
  • O worktree/branch em que o agente roda continua sendo o contrato de ambiente; não há nova forma de claim nem de sessão órfã.
  • A sessão de um run é endereçável a partir da Issue/worktree (dá para saber como chegar nela sem adivinhar) — pré-requisito do "abrir a sessão do agente" do painel OPS109.

Dados (intenção)

  • Vou apresentar dados? Não.
  • Decisões desbloqueadas: N/A.
  • Forma: N/A — Dados: N/A — ferramenta/ops de operação de agentes; sem métrica, gráfico ou dado eleitoral/de contato envolvido.

Dados da decisão (literais)

  • Se algo escutar além do loopback, a credencial é a do próprio opencode por ambiente: OPENCODE_SERVER_PASSWORD (e OPENCODE_SERVER_USERNAME); valores reais vivem fora do repo (workstation), nunca commitados — sem credencial, a superfície responde 401.
  • "Loopback" aqui é 127.0.0.1, o default atual do modo servidor do opencode 1.18.31.
  • Os nomes acima são o contrato disponível hoje; porta, host de bind, paths de log/socket e nome de serviço são hipóteses do plano de implementação, não de contrato de produto.
  • O painel OPS109 consome este endereçamento (abrir a sessão da Issue); o artefato/mecanismo concreto de descoberta é decisão do plano de implementação — sem mapa paralelo.

Direção no codebase (hipótese)

  • Áreas prováveis: scripts/lib/worktree.mjs (diretiva launch, ~207–233) e .agents/shell/worktree.sh (~104–112, executa o launch); documentação em docs/AGENT-OPS.md e AGENTS.md.
  • Duas direções citáveis, sem escolha aqui: (a) servidor nativo persistente do opencode (opencode serve, dono da sessão) com cliente opencode attach <url> de qualquer dispositivo (replay/--continue); ou (b) multiplexador de terminal mantendo o TUI vivo entre anexações. A forma é decisão do plano de implementação; o aceite de produto é o mesmo.
  • Precedente a olhar: OPS106 scripts/auto-unblock.mjs (spawn destacado + log + flock) mostra o padrão local de processo que sobrevive ao invocador, embora não seja sessão interativa; OPS40 scripts/dev.mjs mostra wrapper de CLI passando flags.
  • Risco de acoplamento: o launch atual nasce da shell function e depende do cd/worktree — qualquer modo destacado precisa preservar worktree/branch e não duplicar a porta de entrada; o painel OPS109 consome o mesmo endereçamento (sem mapa paralelo). Expor bind além do loopback é o risco nº 1: a workstation não tem IP tailnet documentado (só o homeserver) e o repo não tem precedente de acesso remoto a ela.

Dependências

  • Nenhuma dura. Depende de capacidades já presentes no opencode instalado (servidor + attach). O OPS109 (painel) depende deste item para abrir a sessão da Issue — o endereçamento da sessão é aceite daqui.

Fora de escopo

  • Multi-usuário ou servir agentes para terceiros.
  • Web UI como produto — se útil na implementação, é meio, não aceite.
  • Notificações/push de progresso, painel de frota de runs, métricas de agentes.
  • Mudanças no fluxo de claim/worktree ou nos gates de PR/deploy.

Rabbit holes de produto

  • "Já que tem servidor, vira painel de frota". Se alguém "só completar": status de todos os runs, iniciar/parar agentes, retomar por lista. Corte neste item: uma sessão, um worktree, attach/detach — nada de orquestração.
  • "Expõe na tailnet e pronto". Se alguém "só completar": bind aberto sem auth "porque a rede é confiável". Corte neste item: qualquer superfície além do loopback exige credencial, fail-closed.
  • "Persistência própria de sessão". Se alguém "só completar": banco/daemon próprio guardando estado do run. Corte neste item: usar o que o opencode já persiste; nada de um segundo dono da sessão.

Questões em aberto (produto)

  • Servidor nativo vs multiplexador? Opções: A servidor persistente + attach | B multiplexador de terminal mantendo o TUI | C os dois. Recomendação: deixa ao impl plan decidir; produto só exige o mesmo aceite (run sobrevive sem cliente, reattach exato, encerramento explícito, auth fora do loopback). (assumido — validar com produto)
  • De onde se acompanha no celular? Opções: A SSH/TUI no terminal do celular | B navegador (web UI) | C só laptop por enquanto. Recomendação: A — reaproveita a superfície TUI já validada; B adiciona escopo de UI que o aceite não exige.

Referências

  • GitHub Issue #1019
  • scripts/lib/worktree.mjs (diretiva launch) e .agents/shell/worktree.sh (execução do launch) — de onde o run nasce hoje
  • scripts/auto-unblock.mjs — precedente OPS106 de processo local destacado
  • docs/AGENT-OPS.md — operação de agentes paralelos; AGENTS.md — convenções do repo
  • docs/ops/teqo-1313-deploy.md — topologia de rede (homeserver × workstation)
  • opencode 1.18.31 instalado: opencode serve, opencode attach, opencode run --attach e opencode web (help local)