From 6d861958cef6fc0d6d1dfea1fa8f6871dfb8dd76 Mon Sep 17 00:00:00 2001 From: hermes Date: Tue, 4 Aug 2026 18:24:29 -0300 Subject: [PATCH 1/5] feat(tooling): add dev-orchestrator script + workflow guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dev-orchestrator: OpenSpec + OpenCode dev→QA loop with git worktrees - WORKFLOW.md: complete usage guide and architecture documentation Commands: init, spec, build, status, clean Zero heavy dependencies — only git, opencode, openspec --- tooling/WORKFLOW.md | 192 +++++++++++++++++++++++++++ tooling/dev-orchestrator | 277 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 469 insertions(+) create mode 100644 tooling/WORKFLOW.md create mode 100755 tooling/dev-orchestrator diff --git a/tooling/WORKFLOW.md b/tooling/WORKFLOW.md new file mode 100644 index 0000000..02bb0ec --- /dev/null +++ b/tooling/WORKFLOW.md @@ -0,0 +1,192 @@ +# Dev Orchestrator — AI Workflow Guide + +Workflow de desenvolvimento com IA usando **OpenCode** + **OpenSpec** + **git worktrees**, com orquestração automática do loop dev→QA. + +``` +Você (review specs) → Orquestrador (specs) → Dev Agent (implementa) → QA Agent (revisa) + ↑ │ + └─────────────────── FAIL ──────────────────────────┘ + PASS → merge → archive +``` + +--- + +## Pré-requisitos + +```bash +# Instalar as 2 dependências +npm install -g opencode-ai@latest +npm install -g @fission-ai/openspec@latest + +# Configurar provedor (OpenRouter, Anthropic, etc.) +opencode auth login +``` + +--- + +## Comandos + +| Comando | O que faz | +|---|---| +| `dev-orchestrator init` | Configura o repo com OpenSpec (roda 1x por projeto) | +| `dev-orchestrator spec ` | Cria spec OpenSpec + worktree isolado + preenche spec via IA | +| `dev-orchestrator build ` | Roda dev→QA loop no worktree, merge automático no main se QA passar | +| `dev-orchestrator status` | Visão kanban dos features ativos | +| `dev-orchestrator clean ` | Remove worktree + branch (para features abandonadas) | + +--- + +## Fluxo Completo + +### 1. Inicializar o projeto + +```bash +cd ~/projetos/meu-app +dev-orchestrator init +``` + +Isso cria a pasta `openspec/`, configura o OpenCode, e adiciona `.worktrees/` ao `.gitignore`. + +### 2. Criar spec de uma feature + +```bash +dev-orchestrator spec add-oauth-login +``` + +O que acontece: +1. Cria `openspec/changes/add-oauth-login/` com os templates +2. Cria um **git worktree** isolado em `../.worktrees/add-oauth-login/` no branch `dev-flow/add-oauth-login` +3. Roda `npm install` (ou `pip install`) dentro do worktree +4. Chama o **orquestrador** (OpenCode) que lê o código, preenche os specs, valida + +### 3. Revisar os specs + +```bash +# Ver arquivos gerados +ls openspec/changes/add-oauth-login/ +cat openspec/changes/add-oauth-login/spec.md + +# Validar +openspec validate add-oauth-login --strict +``` + +**Aqui você está no controle.** Revise os specs, ajuste o que quiser. +Só prossiga quando estiver satisfeito. + +### 4. Disparar o build + +```bash +dev-orchestrator build add-oauth-login +``` + +O que acontece: +``` +── Dev Phase (attempt 1/3) ── + → OpenCode implementa no worktree + → Roda testes + +── QA Review ── + → OpenCode revisa: spec compliance, testes, regressões, edge cases + +PASS → merge no main, archive spec, remove worktree +FAIL → volta pro dev (até 3 tentativas) +``` + +Se o QA falhar 3 vezes, o worktree é mantido pra você inspecionar e corrigir manualmente. + +### 5. Ver status de tudo + +```bash +dev-orchestrator status +``` + +Exemplo de output: +``` +# FEATURE COMMITS SPEC WORKTREE +─── ───────────────────────────── ───────── ───────── ────────────── +1. add-oauth-login 3 2/4 ../.worktrees/add-oauth-login/ +2. fix-payment-timeout 1 active ../.worktrees/fix-payment-timeout/ +``` + +--- + +## Estrutura de diretórios + +``` +~/projetos/meu-app/ +├── src/ # código principal +├── openspec/ +│ ├── specs/ # specs arquivados (source of truth) +│ └── changes/ # specs ativos +│ └── add-oauth/ +│ ├── spec.md +│ ├── design.md +│ └── tasks.md +├── .gitignore # inclui .worktrees/ +└── ... + +../.worktrees/ +└── add-oauth/ # worktree isolado + ├── .git # branch: dev-flow/add-oauth + ├── src/ # cópia do código + ├── node_modules/ # instalado localmente + └── ... +``` + +--- + +## FAQ + +### Posso rodar múltiplos features em paralelo? + +Sim. Cada `dev-orchestrator spec` cria um worktree isolado. Rode `build` em terminais separados: + +```bash +# Terminal 1 +dev-orchestrator build add-oauth + +# Terminal 2 +dev-orchestrator build fix-payments +``` + +Worktrees em branches diferentes = zero conflito. O merge no main é o único ponto de serialização. + +### O QA falhou e eu quero corrigir manualmente + +```bash +cd ../.worktrees/fix-payments +# ... faz as correções ... +git add -A && git commit -m "manual fix" +dev-orchestrator build fix-payments # re-dispara do QA +``` + +### Como limpar uma feature abandonada? + +```bash +dev-orchestrator clean fix-abandonada +``` + +Remove o worktree e o branch. O spec em `openspec/changes/` fica — delete manualmente se quiser. + +### Preciso commitar algo no meio do build? + +O Dev Agent já commita a cada tentativa. Se quiser checkpoints extras, faça manualmente no worktree — o script não interfere. + +### O que acontece com `node_modules`? + +Cada worktree tem o seu próprio `node_modules`, instalado durante o `spec`. Sem symlinks, sem compartilhamento — isolamento total. Custa espaço em disco, mas evita qualquer heisenbug de dependência. + +--- + +## Opcional: Kanban com .hive (Swarm Tools) + +Se quiser tracking mais visual, instale o Swarm Tools (leve, sem daemon, sem binário grande): + +```bash +npm install -g opencode-swarm-plugin +swarm setup +``` + +Depois, dentro do OpenCode, use `/hive` pra ver tasks e `/swarm "tarefa"` pra decompor em paralelo. O `.hive/` é uma pasta git-tracked com markdown — nada de banco ou servidor. + +O script `dev-orchestrator` funciona com ou sem Swarm Tools. São independentes. diff --git a/tooling/dev-orchestrator b/tooling/dev-orchestrator new file mode 100755 index 0000000..86d1088 --- /dev/null +++ b/tooling/dev-orchestrator @@ -0,0 +1,277 @@ +#!/usr/bin/env bash +# dev-orchestrator — OpenSpec + OpenCode dev→QA loop with git worktrees +# Zero dependencies beyond git, opencode, openspec. No heavy binaries. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO="${DEV_FLOW_REPO:-$(pwd)}" +WORKTREE_ROOT="$REPO/../.worktrees" + +# ── helpers ────────────────────────────────────────────────────── + +_wt_path() { echo "$WORKTREE_ROOT/$1"; } +_wt_branch(){ echo "dev-flow/$1"; } + +_die() { echo "✗ $*" >&2; exit 1; } +_ok() { echo "✓ $*"; } + +# Ensure we're inside a git repo with openspec +_guard() { + cd "$REPO" + git rev-parse --show-toplevel >/dev/null 2>&1 || _die "not a git repo: $REPO" + [ -d openspec ] || _die "openspec not initialized. Run: dev-orchestrator init" +} + +# ── commands ───────────────────────────────────────────────────── + +cmd_init() { + cd "$REPO" + git rev-parse --show-toplevel >/dev/null 2>&1 || _die "not a git repo" + + mkdir -p "$WORKTREE_ROOT" + [ -d openspec ] && _ok "openspec already initialized" || { + openspec init --tools opencode --force + _ok "openspec initialized" + } + + grep -qxF '.worktrees/' .gitignore 2>/dev/null || { + echo '.worktrees/' >> .gitignore + _ok "added .worktrees/ to .gitignore" + } + + echo "" + echo "Repo ready. Next: dev-orchestrator spec " +} + +cmd_spec() { + local name="$1" + _guard + + # ── validate name (kebab-case) ── + [[ "$name" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]] || _die "name must be kebab-case: add-oauth, fix-login" + + # ── create OpenSpec change ── + echo "── Creating OpenSpec change: $name ──" + openspec new change "$name" --json 2>/dev/null || { + _die "openspec new change failed. Already exists? Run: dev-orchestrator status" + } + + # ── create worktree ── + local branch="$(_wt_branch "$name")" + local wt="$(_wt_path "$name")" + echo "── Creating worktree: $wt [$branch] ──" + git worktree add -b "$branch" "$wt" HEAD + + # ── install deps in worktree (fully isolated, no symlinks) ── + if [ -f "$wt/package.json" ]; then + echo "── Installing dependencies ──" + (cd "$wt" && npm install --silent 2>&1 | tail -1) || true + fi + if [ -f "$wt/pyproject.toml" ] || [ -f "$wt/setup.py" ]; then + (cd "$wt" && [ -d .venv ] || python3 -m venv .venv && . .venv/bin/activate && pip install -e . -q 2>&1 | tail -1) || true + fi + + # ── orchestrator fills the spec ── + echo "── Orchestrator filling spec ──" + opencode run \ + "You are filling an OpenSpec change for feature: $name. + + STEPS: + 1. Read the codebase structure first (scan src/, lib/, or equivalent). + 2. Read openspec/changes/$name/ — note the template files created. + 3. Read openspec/specs/ for existing specs to avoid conflicts. + 4. For each template file in the change directory, fill it with: + - Clear requirements and acceptance criteria + - Files that need to change + - Dependencies on other modules + - Test plan + 5. Run: openspec validate $name --strict + 6. Fix any validation errors, re-run until clean. + 7. Output a summary: spec files created, key decisions, estimated scope." \ + --workdir "$REPO" + + echo "" + _ok "Spec '$name' ready at openspec/changes/$name/" + echo " Worktree: $wt" + echo " Review the spec, then: dev-orchestrator build $name" +} + +cmd_build() { + local name="$1" + _guard + + local wt="$(_wt_path "$name")" + [ -d "$wt" ] || _die "worktree not found: $wt. Run: dev-orchestrator spec $name" + + local branch="$(_wt_branch "$name")" + local max_retries=3 + + for attempt in $(seq 1 $max_retries); do + echo "" + echo "══════════════════════════════════════════════════" + echo " $name — Dev Phase (attempt $attempt/$max_retries)" + echo "══════════════════════════════════════════════════" + + opencode run \ + "IMPLEMENT the spec at openspec/changes/$name/. + + RULES: + - Read openspec instructions --change $name first + - Implement ALL requirements from the spec + - Write tests for every new code path + - Run the test suite and ensure it passes + - If tests fail, fix them before considering work done + - Commit with message: '$name: implement feature (attempt $attempt)' + - Do NOT modify openspec/ files — only source code and tests" \ + --workdir "$wt" || { + echo "⚠ Dev phase had errors, proceeding to QA anyway..." + } + + # ── QA phase ── + echo "" + echo "──────────────────────────────────────────────────" + echo " $name — QA Review" + echo "──────────────────────────────────────────────────" + + local qa_file="/tmp/dev-orchestrator-qa-$$.txt" + opencode run \ + "QA REVIEW for $name. + + CHECKLIST (answer each with PASS or FAIL): + 1. SPEC COMPLIANCE — Does the code implement everything in openspec/changes/$name/? + 2. TESTS — Do all tests pass? Run them now. + 3. REGRESSIONS — Does any existing test break? Check git diff vs main. + 4. EDGE CASES — Are errors handled? Null/empty inputs? Timeouts? + 5. CODE QUALITY — Clear naming? No debug leftovers? No commented-out code? + + OUTPUT FORMAT (exactly these 2 lines, nothing else): + VERDICT: PASS|FAIL + REASON: " \ + --workdir "$wt" > "$qa_file" 2>&1 + + local verdict + verdict=$(grep '^VERDICT:' "$qa_file" | head -1 | awk -F': ' '{print $2}') + local reason + reason=$(grep '^REASON:' "$qa_file" | head -1 | cut -d' ' -f2-) + + if [ "$verdict" = "PASS" ]; then + echo "" + _ok "QA PASSED — $reason" + + # ── archive + merge ── + cd "$REPO" + echo "── Archiving spec ──" + openspec archive "$name" --yes 2>/dev/null || true + + echo "── Merging to main ──" + local current_branch=$(git branch --show-current) + git merge "$branch" -m "dev-flow: merge $name" 2>/dev/null || { + echo "⚠ Merge conflict. Resolve manually in $wt then run:" + echo " cd $wt && git checkout main && git merge $branch" + return 1 + } + + echo "── Cleaning up worktree ──" + git worktree remove "$wt" 2>/dev/null || true + git branch -d "$branch" 2>/dev/null || true + + echo "" + _ok "$name — BUILD COMPLETE ✓" + rm "$qa_file" + return 0 + fi + + echo "" + echo "✗ QA FAILED — ${reason:-see $qa_file}" + rm "$qa_file" + + if [ "$attempt" -eq "$max_retries" ]; then + _die "$name FAILED after $max_retries attempts. Worktree kept at $wt for manual fix." + fi + echo "↻ Sending back to dev with QA feedback..." + done +} + +cmd_status() { + _guard 2>/dev/null || true + + echo "" + printf "%-4s %-30s %-10s %-10s %-15s\n" "#" "FEATURE" "COMMITS" "SPEC" "WORKTREE" + printf "%-4s %-30s %-10s %-10s %-15s\n" "───" "──────────────────────────────" "──────────" "──────────" "──────────────" + + local n=0 + for wt in "$WORKTREE_ROOT"/*/; do + [ -d "$wt" ] || continue + local name=$(basename "$wt") + local branch="$(_wt_branch "$name")" + local commits="?" + [ -d "$wt/.git" ] && commits=$(cd "$wt" && git rev-list --count "$branch" -- 2>/dev/null || echo "?") + commits="${commits:-0}" + + # spec status + local spec="?" + [ -d "$REPO/openspec/changes/$name" ] && { + spec=$(cd "$REPO" && openspec status --change "$name" --json 2>/dev/null | \ + python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('artifacts_completed','?'),'/',d.get('artifacts_total','?'),sep='')" 2>/dev/null || echo "active") + } + + n=$((n+1)) + printf "%-4s %-30s %-10s %-10s %-15s\n" \ + "$n." "$name" "$commits" "${spec:-active}" "$wt" + done + + if [ "$n" -eq 0 ]; then + echo " (no active features)" + fi + echo "" +} + +cmd_clean() { + local name="$1" + cd "$REPO" + local wt="$(_wt_path "$name")" + local branch="$(_wt_branch "$name")" + + git worktree remove "$wt" 2>/dev/null || true + git branch -D "$branch" 2>/dev/null || true + [ ! -d "$wt" ] && _ok "cleaned $name" || _die "could not remove $wt" +} + +# ── dispatch ───────────────────────────────────────────────────── + +case "${1:-}" in + init) + cmd_init + ;; + spec) + [ $# -ge 2 ] || _die "usage: dev-orchestrator spec " + cmd_spec "$2" + ;; + build) + [ $# -ge 2 ] || _die "usage: dev-orchestrator build " + cmd_build "$2" + ;; + status) + cmd_status + ;; + clean) + [ $# -ge 2 ] || _die "usage: dev-orchestrator clean " + cmd_clean "$2" + ;; + *) + echo "dev-orchestrator — OpenSpec + OpenCode dev→QA loop" + echo "" + echo "commands:" + echo " init Set up repo (run once per project)" + echo " spec Create OpenSpec + worktree + fill spec" + echo " build Dev→QA loop in isolated worktree" + echo " status Kanban view of features in flight" + echo " clean Remove worktree + branch" + echo "" + echo "flow: init → spec → [review] → build → [loop until QA passes]" + echo "" + echo "worktrees live at: ../.worktrees//" + echo "branches named: dev-flow/" + exit 1 + ;; +esac \ No newline at end of file -- 2.54.0 From c53a7f278b10c8a584dbe728fd4ea12c270458ff Mon Sep 17 00:00:00 2001 From: hermes Date: Tue, 4 Aug 2026 18:26:08 -0300 Subject: [PATCH 2/5] docs: expand WORKFLOW.md with tool interaction guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added per-tool usage: when to use OpenCode/OpenSpec directly vs orchestrator - Direct interaction patterns for manual work - Clear gate: you review specs before build — critical step - When to step out of the orchestrator workflow - Smoother flow diagram --- tooling/WORKFLOW.md | 261 +++++++++++++++++++++++++------------------- 1 file changed, 151 insertions(+), 110 deletions(-) diff --git a/tooling/WORKFLOW.md b/tooling/WORKFLOW.md index 02bb0ec..c50a912 100644 --- a/tooling/WORKFLOW.md +++ b/tooling/WORKFLOW.md @@ -1,12 +1,63 @@ # Dev Orchestrator — AI Workflow Guide -Workflow de desenvolvimento com IA usando **OpenCode** + **OpenSpec** + **git worktrees**, com orquestração automática do loop dev→QA. +Toolchain de desenvolvimento com IA: **OpenCode** (agente) + **OpenSpec** (spec-driven dev) + **Dev Orchestrator** (loop dev→QA automático). + +--- + +## Ferramentas — Quando Usar Cada Uma + +### OpenCode — O Agente + +Executa tarefas de código. Use **diretamente** quando: + +- Explorar uma codebase nova: `opencode` (TUI interativo) +- Fazer uma mudança pontual: `opencode run "corrige typo no header"` +- Debugar um erro específico: `opencode run "por que esse teste falha?" --thinking` +- Revisar um PR manualmente: `opencode pr 42` + +Use via **orquestrador** quando: +- Implementar uma feature completa com spec (`dev-orchestrator build`) +- Precisar de QA automático depois do dev +- Quiser loop dev→QA sem babysitting + +```bash +# Modos do OpenCode +opencode # TUI interativo (exploração) +opencode run "tarefa" # one-shot (automação) +opencode run "..." --thinking # vê o raciocínio do modelo +opencode run "..." -f arquivo.ts # anexa contexto +``` + +### OpenSpec — O Spec Engine + +Gerencia specs como source of truth. Use **diretamente** quando: + +- Criar spec manualmente: `openspec new change minha-feature` +- Validar um spec existente: `openspec validate minha-feature --strict` +- Ver status de todos os changes: `openspec list --json` +- Arquivar spec concluído: `openspec archive minha-feature --yes` + +Use via **orquestrador** quando: +- Quiser que a IA preencha o spec automaticamente (`dev-orchestrator spec`) +- O archive deve acontecer automático pós-QA-pass (`dev-orchestrator build`) + +```bash +# Comandos OpenSpec que você mais usa +openspec list # o que está ativo? +openspec show minha-feature # ler um spec +openspec validate minha-feature # check pré-implementação +openspec status --change minha-feature # progresso dos artefatos +openspec instructions --change minha-feature # o que o agente deve fazer +``` + +### Dev Orchestrator — O Script + +Automatiza o loop completo. **Substitui** os comandos manuais acima no fluxo principal. ``` -Você (review specs) → Orquestrador (specs) → Dev Agent (implementa) → QA Agent (revisa) - ↑ │ - └─────────────────── FAIL ──────────────────────────┘ - PASS → merge → archive +você tem ideia → spec → review → build → PR pronto + ↑ ↑ ↑ + orquestrador você automático ``` --- @@ -14,179 +65,169 @@ Você (review specs) → Orquestrador (specs) → Dev Agent (implementa) ## Pré-requisitos ```bash -# Instalar as 2 dependências npm install -g opencode-ai@latest npm install -g @fission-ai/openspec@latest - -# Configurar provedor (OpenRouter, Anthropic, etc.) -opencode auth login +opencode auth login # configura provider (OpenRouter, Anthropic, etc.) ``` --- -## Comandos +## Comandos do Orquestrador | Comando | O que faz | |---|---| -| `dev-orchestrator init` | Configura o repo com OpenSpec (roda 1x por projeto) | -| `dev-orchestrator spec ` | Cria spec OpenSpec + worktree isolado + preenche spec via IA | -| `dev-orchestrator build ` | Roda dev→QA loop no worktree, merge automático no main se QA passar | -| `dev-orchestrator status` | Visão kanban dos features ativos | -| `dev-orchestrator clean ` | Remove worktree + branch (para features abandonadas) | +| `dev-orchestrator init` | Configura repo (OpenSpec + .gitignore) — 1x por projeto | +| `dev-orchestrator spec ` | Cria spec + worktree isolado + preenche spec via IA | +| `dev-orchestrator build ` | Loop dev→QA (3 tentativas), merge automático se passar | +| `dev-orchestrator status` | Dashboard de features em andamento | +| `dev-orchestrator clean ` | Remove worktree + branch (abortar feature) | --- ## Fluxo Completo -### 1. Inicializar o projeto +``` +┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ +│ init │───→│ spec │───→│ [review] │───→│ build │ +│ (1x/proj)│ │ (orquestrador│ │ (você aprova) │ │ (dev→QA loop)│ +└──────────┘ │ preenche) │ └──────────────┘ └──────┬──────┘ + └──────────────┘ │ + ┌────────────────────┘ + │ QA PASS → merge + archive + │ QA FAIL → retry (3x max) + └──────────────────────── +``` + +### 1. Inicializar ```bash cd ~/projetos/meu-app dev-orchestrator init ``` -Isso cria a pasta `openspec/`, configura o OpenCode, e adiciona `.worktrees/` ao `.gitignore`. - -### 2. Criar spec de uma feature +### 2. Especificar feature ```bash -dev-orchestrator spec add-oauth-login +dev-orchestrator spec add-oauth ``` -O que acontece: -1. Cria `openspec/changes/add-oauth-login/` com os templates -2. Cria um **git worktree** isolado em `../.worktrees/add-oauth-login/` no branch `dev-flow/add-oauth-login` -3. Roda `npm install` (ou `pip install`) dentro do worktree -4. Chama o **orquestrador** (OpenCode) que lê o código, preenche os specs, valida +O que acontece internamente: +1. `openspec new change add-oauth --json` → cria templates +2. `git worktree add -b dev-flow/add-oauth ../.worktrees/add-oauth/ HEAD` +3. `npm install` dentro do worktree +4. `opencode run "preenche os specs lendo a codebase"` → orquestrador preenche spec.md, design.md, tasks.md -### 3. Revisar os specs +### 3. Revisar os specs (MOMENTO CRÍTICO) ```bash -# Ver arquivos gerados -ls openspec/changes/add-oauth-login/ -cat openspec/changes/add-oauth-login/spec.md +# Ler o spec gerado +cat openspec/changes/add-oauth/spec.md +cat openspec/changes/add-oauth/design.md # Validar -openspec validate add-oauth-login --strict +openspec validate add-oauth --strict + +# Ajustar manualmente se quiser — edite os arquivos +vim openspec/changes/add-oauth/spec.md ``` -**Aqui você está no controle.** Revise os specs, ajuste o que quiser. -Só prossiga quando estiver satisfeito. +> **Você é o gatekeeper aqui.** Se o spec não está certo, o build vai sair errado. +> Gaste tempo revisando os specs — é o investimento mais rentável do fluxo. -### 4. Disparar o build +### 4. Build (dev→QA loop) ```bash -dev-orchestrator build add-oauth-login +dev-orchestrator build add-oauth ``` -O que acontece: +Loop: ``` -── Dev Phase (attempt 1/3) ── - → OpenCode implementa no worktree - → Roda testes - -── QA Review ── - → OpenCode revisa: spec compliance, testes, regressões, edge cases - -PASS → merge no main, archive spec, remove worktree -FAIL → volta pro dev (até 3 tentativas) +Dev Phase ──→ OpenCode implementa + testa + commita + │ + ▼ +QA Phase ──→ OpenCode revisa: spec compliance, testes, regressões + │ + ├── PASS → merge no main, archive spec, remove worktree ✅ + │ + └── FAIL → volta pro Dev (até 3 tentativas) + falhou 3x → worktree mantido pra correção manual ``` -Se o QA falhar 3 vezes, o worktree é mantido pra você inspecionar e corrigir manualmente. - -### 5. Ver status de tudo +### 5. Status dashboard ```bash dev-orchestrator status ``` -Exemplo de output: -``` -# FEATURE COMMITS SPEC WORKTREE -─── ───────────────────────────── ───────── ───────── ────────────── -1. add-oauth-login 3 2/4 ../.worktrees/add-oauth-login/ -2. fix-payment-timeout 1 active ../.worktrees/fix-payment-timeout/ -``` +--- + +## Quando Sair do Orquestrador + +O script cobre 90% dos casos. Saia dele quando: + +| Situação | O que fazer | +|---|---| +| Spec ficou ruim e quero reescrever do zero | `openspec new change X` manual, preenche na mão | +| QA rejeitou e quero corrigir eu mesmo | `cd ../.worktrees/feature/` → edita → commita → `dev-orchestrator build feature` | +| Feature complexa demais pra um spec só | `openspec new change feature-pt1`, `openspec new change feature-pt2` | +| Quero iterar rápido sem spec | `opencode` TUI direto (pula o orquestrador) | +| Bug fix trivial (1-2 linhas) | `opencode run "fix: ..."` direto, nem cria spec | --- -## Estrutura de diretórios +## Paralelismo + +Rode múltiplos features ao mesmo tempo: + +```bash +# Terminal 1 +dev-orchestrator build feature-a + +# Terminal 2 +dev-orchestrator build feature-b +``` + +Cada um em seu worktree isolado. O merge no main serializa no final — se houver conflito, o script para e avisa. + +--- + +## Estrutura de Diretórios ``` ~/projetos/meu-app/ -├── src/ # código principal +├── src/ ├── openspec/ -│ ├── specs/ # specs arquivados (source of truth) -│ └── changes/ # specs ativos +│ ├── specs/ # specs arquivados +│ └── changes/ # specs ativos │ └── add-oauth/ │ ├── spec.md │ ├── design.md │ └── tasks.md -├── .gitignore # inclui .worktrees/ +├── .gitignore # inclui .worktrees/ └── ... ../.worktrees/ -└── add-oauth/ # worktree isolado - ├── .git # branch: dev-flow/add-oauth - ├── src/ # cópia do código - ├── node_modules/ # instalado localmente +└── add-oauth/ # worktree isolado + ├── .git # branch: dev-flow/add-oauth + ├── src/ + ├── node_modules/ └── ... ``` --- -## FAQ +## Opcional: Swarm Tools + .hive -### Posso rodar múltiplos features em paralelo? - -Sim. Cada `dev-orchestrator spec` cria um worktree isolado. Rode `build` em terminais separados: - -```bash -# Terminal 1 -dev-orchestrator build add-oauth - -# Terminal 2 -dev-orchestrator build fix-payments -``` - -Worktrees em branches diferentes = zero conflito. O merge no main é o único ponto de serialização. - -### O QA falhou e eu quero corrigir manualmente - -```bash -cd ../.worktrees/fix-payments -# ... faz as correções ... -git add -A && git commit -m "manual fix" -dev-orchestrator build fix-payments # re-dispara do QA -``` - -### Como limpar uma feature abandonada? - -```bash -dev-orchestrator clean fix-abandonada -``` - -Remove o worktree e o branch. O spec em `openspec/changes/` fica — delete manualmente se quiser. - -### Preciso commitar algo no meio do build? - -O Dev Agent já commita a cada tentativa. Se quiser checkpoints extras, faça manualmente no worktree — o script não interfere. - -### O que acontece com `node_modules`? - -Cada worktree tem o seu próprio `node_modules`, instalado durante o `spec`. Sem symlinks, sem compartilhamento — isolamento total. Custa espaço em disco, mas evita qualquer heisenbug de dependência. - ---- - -## Opcional: Kanban com .hive (Swarm Tools) - -Se quiser tracking mais visual, instale o Swarm Tools (leve, sem daemon, sem binário grande): +Kanban mais visual, sem servidor: ```bash npm install -g opencode-swarm-plugin swarm setup ``` -Depois, dentro do OpenCode, use `/hive` pra ver tasks e `/swarm "tarefa"` pra decompor em paralelo. O `.hive/` é uma pasta git-tracked com markdown — nada de banco ou servidor. +Dentro do OpenCode: +- `/swarm "tarefa"` — decompõe e spawna workers paralelos +- `/hive` — quadro kanban das tasks +- `/inbox` — mensagens entre agentes -O script `dev-orchestrator` funciona com ou sem Swarm Tools. São independentes. +O `.hive/` é uma pasta git-tracked. Independe do `dev-orchestrator`. \ No newline at end of file -- 2.54.0 From 80556753e305d42463cf1b2b969337439f495282 Mon Sep 17 00:00:00 2001 From: hermes Date: Tue, 4 Aug 2026 18:41:40 -0300 Subject: [PATCH 3/5] feat(dev-orchestrator): add NixOS home-manager module - New module: modules/home-manager/dev-orchestrator/ - Wraps script via writeShellApplication, git as runtime dep - opencode + openspec already in PATH via existing modules - Enabled in jpporta-nixos home.nix After rebuild: dev-orchestrator available in PATH --- hosts/jpporta-nixos/home.nix | 2 ++ .../home-manager/dev-orchestrator/default.nix | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 modules/home-manager/dev-orchestrator/default.nix diff --git a/hosts/jpporta-nixos/home.nix b/hosts/jpporta-nixos/home.nix index 780682d..19746a2 100644 --- a/hosts/jpporta-nixos/home.nix +++ b/hosts/jpporta-nixos/home.nix @@ -31,6 +31,7 @@ ../../modules/home-manager/pi ../../modules/home-manager/tmux ../../modules/home-manager/openspec + ../../modules/home-manager/dev-orchestrator ../../modules/home-manager/power-profiles ../../modules/home-manager/ntfy-notify ../../modules/home-manager/pinentry @@ -94,6 +95,7 @@ enable = true; }; openspec.enable = true; + dev-orchestrator.enable = true; power-profiles.enable = true; ntfy-notify.enable = true; bitwarden.enable = true; diff --git a/modules/home-manager/dev-orchestrator/default.nix b/modules/home-manager/dev-orchestrator/default.nix new file mode 100644 index 0000000..9228b27 --- /dev/null +++ b/modules/home-manager/dev-orchestrator/default.nix @@ -0,0 +1,16 @@ +{ lib, config, pkgs, ... }: +{ + options.custom = { + dev-orchestrator.enable = lib.mkEnableOption "enable dev-orchestrator — OpenSpec + OpenCode dev→QA loop with git worktrees"; + }; + + config = lib.mkIf config.custom.dev-orchestrator.enable { + home.packages = [ + (pkgs.writeShellApplication { + name = "dev-orchestrator"; + runtimeInputs = with pkgs; [ git ]; + text = builtins.readFile ../../../tooling/dev-orchestrator; + }) + ]; + }; +} -- 2.54.0 From 32bc53bb68d235abc9739aed9b5ff6b7c82fa458 Mon Sep 17 00:00:00 2001 From: hermes-bot Date: Wed, 5 Aug 2026 10:43:35 -0300 Subject: [PATCH 4/5] dev-orchestrator: decouple spec scaffold from fill, delegate exploration to OpenSpec native /opsx commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cmd_spec now only scaffolds (OpenSpec change + worktree + deps), no auto-fill - Added cmd_fill as fallback for headless spec filling - Output guides user to /opsx:explore and /opsx:continue inside OpenCode - cmd_build (dev→QA loop) unchanged — core value proposition --- tooling/dev-orchestrator | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tooling/dev-orchestrator b/tooling/dev-orchestrator index 86d1088..d53b45c 100755 --- a/tooling/dev-orchestrator +++ b/tooling/dev-orchestrator @@ -71,8 +71,27 @@ cmd_spec() { (cd "$wt" && [ -d .venv ] || python3 -m venv .venv && . .venv/bin/activate && pip install -e . -q 2>&1 | tail -1) || true fi - # ── orchestrator fills the spec ── - echo "── Orchestrator filling spec ──" + echo "" + _ok "Spec '$name' scaffolded at openspec/changes/$name/" + echo " Worktree: $wt" + echo "" + echo " ── Next: explore in OpenCode ──" + echo " opencode" + echo " Then use OpenSpec native commands:" + echo " /opsx:explore — discuss the feature, refine requirements" + echo " /opsx:continue — fill spec artifacts one by one" + echo "" + echo " After specs are filled → dev-orchestrator build $name" +} + +cmd_fill() { + local name="$1" + _guard + + local wt="$(_wt_path "$name")" + [ -d "openspec/changes/$name" ] || _die "spec not found: openspec/changes/$name. Run: dev-orchestrator spec $name" + + echo "── AI filling spec from conversation context ──" opencode run \ "You are filling an OpenSpec change for feature: $name. @@ -91,8 +110,7 @@ cmd_spec() { --workdir "$REPO" echo "" - _ok "Spec '$name' ready at openspec/changes/$name/" - echo " Worktree: $wt" + _ok "Spec '$name' filled at openspec/changes/$name/" echo " Review the spec, then: dev-orchestrator build $name" } @@ -247,6 +265,10 @@ case "${1:-}" in [ $# -ge 2 ] || _die "usage: dev-orchestrator spec " cmd_spec "$2" ;; + fill) + [ $# -ge 2 ] || _die "usage: dev-orchestrator fill " + cmd_fill "$2" + ;; build) [ $# -ge 2 ] || _die "usage: dev-orchestrator build " cmd_build "$2" @@ -263,12 +285,13 @@ case "${1:-}" in echo "" echo "commands:" echo " init Set up repo (run once per project)" - echo " spec Create OpenSpec + worktree + fill spec" + echo " spec Scaffold OpenSpec + worktree (no fill)" + echo " fill AI fills spec after exploration" echo " build Dev→QA loop in isolated worktree" echo " status Kanban view of features in flight" echo " clean Remove worktree + branch" echo "" - echo "flow: init → spec → [review] → build → [loop until QA passes]" + echo "flow: init → spec → [explore in OpenCode] → fill → build → [QA loop]" echo "" echo "worktrees live at: ../.worktrees//" echo "branches named: dev-flow/" -- 2.54.0 From 810047a074acc0fd94fb14cd8c3f0363301e0956 Mon Sep 17 00:00:00 2001 From: hermes-bot Date: Wed, 5 Aug 2026 10:46:52 -0300 Subject: [PATCH 5/5] fix: shellcheck warnings for Nix writeShellApplication - Remove unused SCRIPT_DIR (SC2034) - Split local var= declaration from assignment (SC2155) - Replace &&/|| with if/else in cmd_clean (SC2015) - Add shellcheck disable for .venv source (SC1091) --- tooling/dev-orchestrator | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tooling/dev-orchestrator b/tooling/dev-orchestrator index d53b45c..50c65f0 100755 --- a/tooling/dev-orchestrator +++ b/tooling/dev-orchestrator @@ -3,7 +3,6 @@ # Zero dependencies beyond git, opencode, openspec. No heavy binaries. set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO="${DEV_FLOW_REPO:-$(pwd)}" WORKTREE_ROOT="$REPO/../.worktrees" @@ -57,8 +56,8 @@ cmd_spec() { } # ── create worktree ── - local branch="$(_wt_branch "$name")" - local wt="$(_wt_path "$name")" + local branch; branch="$(_wt_branch "$name")" + local wt; wt="$(_wt_path "$name")" echo "── Creating worktree: $wt [$branch] ──" git worktree add -b "$branch" "$wt" HEAD @@ -68,6 +67,7 @@ cmd_spec() { (cd "$wt" && npm install --silent 2>&1 | tail -1) || true fi if [ -f "$wt/pyproject.toml" ] || [ -f "$wt/setup.py" ]; then + # shellcheck disable=SC1091 (cd "$wt" && [ -d .venv ] || python3 -m venv .venv && . .venv/bin/activate && pip install -e . -q 2>&1 | tail -1) || true fi @@ -88,7 +88,7 @@ cmd_fill() { local name="$1" _guard - local wt="$(_wt_path "$name")" + local wt; wt="$(_wt_path "$name")" [ -d "openspec/changes/$name" ] || _die "spec not found: openspec/changes/$name. Run: dev-orchestrator spec $name" echo "── AI filling spec from conversation context ──" @@ -118,10 +118,10 @@ cmd_build() { local name="$1" _guard - local wt="$(_wt_path "$name")" + local wt; wt="$(_wt_path "$name")" [ -d "$wt" ] || _die "worktree not found: $wt. Run: dev-orchestrator spec $name" - local branch="$(_wt_branch "$name")" + local branch; branch="$(_wt_branch "$name")" local max_retries=3 for attempt in $(seq 1 $max_retries); do @@ -221,7 +221,7 @@ cmd_status() { for wt in "$WORKTREE_ROOT"/*/; do [ -d "$wt" ] || continue local name=$(basename "$wt") - local branch="$(_wt_branch "$name")" + local branch; branch="$(_wt_branch "$name")" local commits="?" [ -d "$wt/.git" ] && commits=$(cd "$wt" && git rev-list --count "$branch" -- 2>/dev/null || echo "?") commits="${commits:-0}" @@ -247,12 +247,16 @@ cmd_status() { cmd_clean() { local name="$1" cd "$REPO" - local wt="$(_wt_path "$name")" - local branch="$(_wt_branch "$name")" + local wt; wt="$(_wt_path "$name")" + local branch; branch="$(_wt_branch "$name")" git worktree remove "$wt" 2>/dev/null || true git branch -D "$branch" 2>/dev/null || true - [ ! -d "$wt" ] && _ok "cleaned $name" || _die "could not remove $wt" + if [ ! -d "$wt" ]; then + _ok "cleaned $name" + else + _die "could not remove $wt" + fi } # ── dispatch ───────────────────────────────────────────────────── -- 2.54.0