diff --git a/.claude/hooks/push-verify.sh b/.claude/hooks/push-verify.sh index ef4e5a4..72ef056 100755 --- a/.claude/hooks/push-verify.sh +++ b/.claude/hooks/push-verify.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash # # Hook de antes do comando do Claude Code (evento PreToolUse, ferramenta Bash). Nega ao agente cinco -# comandos: o `scripts/verify.sh full` a um subagente, porque o modo completo é de quem fecha a tarefa; +# comandos: o `scripts/frentes.sh` com `--forcar`, que abandona uma frente sem merge e é só do usuário, ou +# com as variáveis do modo de teste, que trocam o `gh` e contornariam a conferência do merge; +# o `scripts/verify.sh full` a um subagente, porque o modo completo é de quem fecha a tarefa; # o `scripts/verify.sh unlock`, que tira a trava do modo completo e é só do usuário; o -# `scripts/verify.sh` com `CI=` ou `GITHUB_ACTIONS=` no comando, que desligaria a trava; o que mexe -# na pasta de estado do harness (`.harness/`), onde ficam a trava e a aprovação; e o `git push` +# `scripts/verify.sh` com `CI=` ou `GITHUB_ACTIONS=` no comando, que desligaria a trava; e o `git push` # que o `scripts/verify.sh prepush` não aprova, porque os commits trazem segredo ou o modo completo # não aprovou o último commit. As guardas são para um agente que coopera, e não uma barreira de # segurança. @@ -17,9 +18,9 @@ cd "${CLAUDE_PROJECT_DIR:-$(dirname "$0")/../..}" || exit 0 # A instrução de destravar, a mesma das mensagens do verify.sh (FULL_LOCK_ASK). # shellcheck source=../../scripts/full-lock.sh source scripts/full-lock.sh 2>/dev/null -# A leitura do que é mexer na pasta de estado do harness e a das aspas, definidas num lugar só. -# shellcheck source=../../scripts/harness-state-guard.sh -source scripts/harness-state-guard.sh +# A leitura das aspas de um comando de shell, que é da skill proteger-harness. +# shellcheck source=../skills/proteger-harness/scripts/harness-state-guard.sh +source .claude/skills/proteger-harness/scripts/harness-state-guard.sh # Nega o comando com as linhas dadas. deny() { @@ -31,6 +32,16 @@ deny_unlock() { deny "O comando foi negado: só o usuário destrava o modo completo." "Como resolver: ${FULL_LOCK_ASK:-}" } +deny_forcar() { + deny "O comando foi negado: só o usuário abandona uma frente com o \`--forcar\`." \ + "O \`frentes.sh remover --forcar\` remove a frente sem o merge e apaga o trabalho dela; abandonar um ticket é decisão do usuário, que a toma no prompt com \`! scripts/frentes.sh remover --forcar\`." +} + +deny_frentes_test() { + deny "O comando foi negado: o \`frentes.sh\` não roda com as variáveis do modo de teste do harness." \ + "\`HARNESS_TEST\`, \`FRENTES_GH\`, \`FRENTES_DOCKER\`, \`FRENTES_PORT_OWNER\` e \`FRENTES_GIT_VERSION\` trocam o \`gh\`, o \`docker\` e as conferências do script, e com elas o \`remover\` removeria uma frente sem o merge. São dos testes do script, que o scripts/verify.sh roda. Rode o \`frentes.sh\` sem elas." +} + deny_ci() { deny "O comando foi negado: \`CI=\` e \`GITHUB_ACTIONS=\` não vão no comando do scripts/verify.sh." \ "Na máquina, o modo completo conta as reprovações repetidas e trava; essas variáveis desligariam a trava, e o veredito da CI é só da CI. Rode o \`scripts/verify.sh\` sem elas." @@ -41,11 +52,6 @@ deny_subagent_full() { "Termine com os testes ligados aos arquivos que mudou, com os comandos do AGENTS.md do projeto, e devolva o resultado dizendo o que rodou (AGENTS.md da raiz, \"Definição de pronto\")." } -deny_state() { - deny "O comando foi negado: a pasta de estado do harness (\`.harness/\`) guarda a trava (\`full-lock\`) e a aprovação (\`full-ok\`) do modo completo, e o estado é da verificação, não do agente." \ - "Não leia, não apague e não grave nada nela: quem mexe nesse estado é o scripts/verify.sh. Se o modo completo travou: ${FULL_LOCK_ASK:-}" -} - # Uma atribuição de variável de ambiente na frente de um comando. assignment='[[:alnum:]_]+=[^[:space:]]*[[:space:]]+' # A posição de um comando: o começo de uma linha ou depois de `;`, `&`, `|` ou `(`, com variáveis de @@ -56,6 +62,12 @@ at_command=$'(^|[;&|(\n])[[:space:]]*('"$assignment"')*' # pegar também o que vem embrulhado (`timeout`, `nohup`, `bash -c`, `eval`, um `if`). Uma mensagem # que cite os dois também é negada: o hook falha fechado. verify_unlock='verify\.sh.*unlock' +# O `frentes.sh` com o `--forcar` em qualquer ponto do comando, como o `unlock`: o `remover --forcar` +# abandona uma frente sem merge, e isso é do usuário. Uma mensagem que cite os dois também é negada. +frentes_forcar='frentes\.sh.*--forcar' +# O `frentes.sh` com uma variável do modo de teste, em qualquer ponto do comando: elas trocam o `gh`, e o +# `remover` passaria a ver um PR mergeado que não existe. Só os testes do script as usam. +frentes_test_mode='(HARNESS_TEST|FRENTES_(GH|DOCKER|PORT_OWNER|GIT_VERSION))' # O modo completo do `verify.sh`, com ou sem apps, em qualquer ponto do comando, como o `unlock`. verify_full="verify\\.sh[\"']?[[:space:]]+[\"']?full([^[:alnum:]_-]|\$)" # Uma atribuição da variável CI ou GITHUB_ACTIONS: no começo, depois de um espaço (o que cobre o @@ -64,7 +76,8 @@ ci_assignment='(^|[[:space:];&|(])(CI|GITHUB_ACTIONS)=' # A mesma atribuição em qualquer ponto, para a entrada que o hook não consegue ler. ci_mention='(^|[^[:alnum:]_])(CI|GITHUB_ACTIONS)=' -# O `split_quotes` é do scripts/harness-state-guard.sh. +# O `split_quotes` é da skill proteger-harness (scripts/harness-state-guard.sh). A pasta de estado do +# harness (`.harness/`) é negada pelo hook dela (hooks/state-guard.sh), configurado à parte no settings.json. # Se o comando roda o `verify.sh` com `CI=` ou `GITHUB_ACTIONS=`: a atribuição fora das aspas, com o # `verify.sh` em qualquer ponto, ou um trecho entre aspas que traga os dois, como o de um `bash -c`. @@ -93,14 +106,16 @@ input="$(cat)" # a falha do `jq` não liberá-lo. if ! command="$(jq -r '.tool_input.command // empty' <<<"$input" 2>/dev/null)"; then [[ "$input" =~ $verify_unlock ]] && deny_unlock - harness_state_in_raw "$input" && deny_state + [[ "$input" =~ $frentes_forcar ]] && deny_forcar + [[ "$input" == *frentes.sh* && "$input" =~ $frentes_test_mode ]] && deny_frentes_test [[ "$input" == *verify.sh* && "$input" =~ $ci_mention ]] && deny_ci [[ "$input" =~ git.*push ]] || exit 0 command="git push" fi [[ "$command" =~ $verify_unlock ]] && deny_unlock -harness_state_touched "$command" && deny_state +[[ "$command" =~ $frentes_forcar ]] && deny_forcar +[[ "$command" == *frentes.sh* && "$command" =~ $frentes_test_mode ]] && deny_frentes_test # O Claude Code põe o `agent_id` na entrada quando o comando vem de um subagente. [[ -n "$(jq -r '.agent_id // empty' <<<"$input" 2>/dev/null)" && "$command" =~ $verify_full ]] && deny_subagent_full diff --git a/.claude/hooks/record-touched.sh b/.claude/hooks/record-touched.sh index 9782f5a..c676fcf 100755 --- a/.claude/hooks/record-touched.sh +++ b/.claude/hooks/record-touched.sh @@ -15,8 +15,8 @@ set -uo pipefail # Sem a pasta de estado do harness (a raiz do projeto não se alcança), não há onde anotar: sai com 0, e # o hook de fim de turno, que não acha a pasta também, avisa que nada foi verificado. -# shellcheck source=../../scripts/harness-dir.sh -source "${0%/*}/../../scripts/harness-dir.sh" +# shellcheck source=../skills/proteger-harness/scripts/harness-dir.sh +source "${0%/*}/../skills/proteger-harness/scripts/harness-dir.sh" [[ -n "$HARNESS_DIR" ]] || exit 0 root="${HARNESS_DIR%/.harness}" cd "$root" 2>/dev/null || exit 0 diff --git a/.claude/hooks/stop-verify.sh b/.claude/hooks/stop-verify.sh index f44f77f..535e7d7 100755 --- a/.claude/hooks/stop-verify.sh +++ b/.claude/hooks/stop-verify.sh @@ -24,8 +24,8 @@ state_unavailable() { exit 0 } -# shellcheck source=../../scripts/harness-dir.sh -source "${0%/*}/../../scripts/harness-dir.sh" +# shellcheck source=../skills/proteger-harness/scripts/harness-dir.sh +source "${0%/*}/../skills/proteger-harness/scripts/harness-dir.sh" [[ -n "$HARNESS_DIR" ]] || state_unavailable cd "${HARNESS_DIR%/.harness}" || state_unavailable diff --git a/.claude/settings.json b/.claude/settings.json index 8f7d261..83e9a16 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -9,14 +9,6 @@ "Edit(./docs/Gerenciador de arquivos.fig)", "Edit(./.harness/**)", "Bash(gh pr merge:*)" - ], - "ask": [ - "Edit(./.github/**)", - "Edit(./.claude/settings.json)", - "Edit(./.claude/hooks/**)", - "Edit(./.claude/agents/**)", - "Edit(./scripts/**)", - "Edit(./.claude/skills/plan-ticket/scripts/**)" ] }, "hooks": { @@ -28,6 +20,11 @@ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/push-verify.sh", "timeout": 120 + }, + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/skills/proteger-harness/hooks/state-guard.sh --ajuda 'Se o modo completo travou: pare e peça ao usuário que examine a falha e rode `! scripts/verify.sh unlock` no prompt. Só ele destrava: não destrave nem contorne a trava.'", + "timeout": 10 } ] }, diff --git a/.claude/skills/abrir-frentes/SKILL.md b/.claude/skills/abrir-frentes/SKILL.md new file mode 100644 index 0000000..e78c12c --- /dev/null +++ b/.claude/skills/abrir-frentes/SKILL.md @@ -0,0 +1,46 @@ +--- +name: abrir-frentes +description: "Open the fronts for the tickets of a spec that are ready to start: read the sub-issues and their blocking relations in the issue tracker, pick the frontier (no pending blocker, no front or pull request yet), fit it to the free slots, confirm with the user, create one front per ticket with scripts/frentes.sh novo, and report the folder, the slot and the command that opens the session of each. Use when the user wants to start several tickets of one spec in parallel." +disable-model-invocation: true +--- + +How to open the parallel fronts of a spec. It prepares the places where the work will happen and stops there: each front gets its own session, and that session plans and implements its ticket. The root `AGENTS.md`, section "Frentes paralelas", owns the rules of a front; `scripts/frentes.sh` owns how one is created and its refusals. This skill reads them and never copies them. + +**Input.** The identifier of the spec (the parent issue, `LUI-182`) or of a list of tickets, and optionally how many fronts to open. Without a number, open as many as the free slots allow. + +**What it owns.** Choosing which tickets to open and the order. It does not own the slot, the ports, the branch name or the `.env` (that is `scripts/frentes.sh`), nor the planning and implementation of a ticket (that is `/plan-ticket` and `/implement`, run in the session of each front). + +**What it never does.** +- Use `--forcar`, or call `remover`. Abandoning a front is the user's. +- Edit a `.env`, a branch or a folder of a front by hand to make a refused `novo` pass. +- Open more fronts than the free slots, or open one without the user's confirmation (step 5). +- Plan or implement a ticket, or start a session in a front. It cannot open a session in another folder, and it tells the user to. +- Change the status of an issue. "In Progress" is moved by the session of the ticket: `/plan-ticket` does it when planning starts, and `/implement` checks it. + +## Steps + +1. **The tickets of the spec.** Fetch the spec and its sub-issues from the issue tracker, each one with its blocking relations ("blocked by"), its status and its type label. If the user passed tickets instead of a spec, fetch those and their blockers. The dependencies are the native relation of the tracker, not text in the description. + +2. **Sort them.** Put each ticket in one group: + - **Done:** leave out. + - **Already taken:** the ticket has a worktree whose branch ends in it (`scripts/frentes.sh listar`), a pull request (open or merged), a local or remote branch (`git fetch`, then `git branch -a --list '**'`), or the status "In Progress" or "In Review" in the tracker. Leave out and say where the work is. The `novo` only looks at worktrees: given a ticket that has a branch but no worktree, it would create a second branch for the same ticket, apart from the work already done. How to resume that work is the user's decision. Before calling the work open, check whether it is already in the base: the branch is an ancestor of the base (`git merge-base --is-ancestor `), or `git cherry ` prints no `+` line, or its pull request is merged. The `git cherry` prints one line per commit of the branch: `+` when the base has no equivalent of it, which is work still pending, and `-` when the base has one, which is work already in the base. A `-` line is not pending work, even though the commit has another hash there. If nothing is pending, the ticket goes to the next group. + - **Stale status:** the tracker says "In Progress" or "In Review" but the work is already in the base. There is nothing to open and nothing to resume. Leave out and tell the user which tickets to close in the tracker, because changing the status is not this skill's job. + - **No code to build:** a ticket that changes nothing in the repository, like a design in Figma, has no pull request and needs no front. Leave out and say so. + - **Blocked:** some blocker is not "Done". Done means merged into the `main`, so a blocker with an open pull request still blocks. Leave out and say what unblocks it. + - **Free:** no pending blocker and not taken. This is the frontier. + + If the frontier is empty, say why (everything is blocked, in progress or done) and stop. + +3. **How many fit.** Run `scripts/frentes.sh listar` and count the open fronts. The limit is 3 in total (`FRENTES_LIMITE` adjusts it), and the main checkout counts as one whenever it is not on the principal branch (the `main` of the base), a detached HEAD included: at rest it stays on the principal branch, brought up to date with `git merge --ff-only `, and if it is detached or on another branch, say that it takes a slot and how to free it. An old worktree counts too, with or without a pull request: name the ones that look abandoned and leave them to the user, because removing a front without a merge is the user's. The number to open is the least of: the free tickets, the free fronts, and what the user asked for. If it is zero, show the list and stop. + +4. **Overlap, and which ones when there are more free tickets than fronts.** Read each free ticket and its section "Decisões de outros tickets", and compare it with the tickets already taken in step 2 whose work is still pending, which keep running while the new fronts work. A ticket with a stale status does not overlap with anything: its work is already in the base the new front starts from. Prefer tickets that touch different areas, because two fronts on the same files meet in a conflict at the sync, and tickets that unblock the most others. Warn when a free ticket overlaps one already taken. Do not pick two tickets where one takes a decision the other also takes: the escalation rule of the root `AGENTS.md` ("Ao trabalhar em um ticket") sends that to the user, so say it. Propose the choice with the reason of each. + +5. **Confirm.** Show the proposal: for each ticket, its identifier, title, type (`feature`, or `bugfix` when its label is `Bug`; `hotfix` and `docs` only if the user says) and the slot it will probably take. Say that each front starts a whole Docker environment, which takes minutes. Wait for the user to confirm or change the list. Do not start before. + +6. **Create the fronts.** For each confirmed ticket, one after the other, run `scripts/frentes.sh novo [type]` in the background (`run_in_background`), because the first start of an environment takes minutes and the commands are not allowed to wait. One after the other, not together: each start builds images and loads the machine. Wait for each to end before the next. If a `novo` refuses (limit, a ticket that already has a front, a port in use on the machine), do not work around it: report the refusal as the script prints it, skip that ticket and go on with the others. If it fails halfway, run `scripts/frentes.sh listar` and say what state the front is in; do not delete anything. + +7. **Report.** When all have ended, run `scripts/frentes.sh listar` once and answer in the chat with one row per front: ticket and title, folder, slot and ports, and the command that `novo` printed to open the session. Then, for each ticket, the first thing to run in its session: + - `/plan-ticket ` when the base has no acceptance file for it (`git show :docs/tickets///aceite.md` fails). A new front starts from the base, so this is the usual case. + - `/implement ` when the base already has the acceptance file, which means the plan is merged. In both cases, the implementation of a planned ticket starts in a new session of the same front. + + Close with what was left out and why (blocked tickets and what unblocks them, tickets already in progress, refusals), and with the reminders that matter to several fronts: one browser profile per slot, and `scripts/frentes.sh listar` shows which fronts will conflict. diff --git a/.claude/skills/abrir-frentes/agents/openai.yaml b/.claude/skills/abrir-frentes/agents/openai.yaml new file mode 100644 index 0000000..a27a0b6 --- /dev/null +++ b/.claude/skills/abrir-frentes/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Abrir frentes" + short_description: "Open the fronts of the ready tickets of a spec" +policy: + allow_implicit_invocation: false diff --git a/.claude/skills/implement-spec/SKILL.md b/.claude/skills/implement-spec/SKILL.md deleted file mode 100644 index 422e089..0000000 --- a/.claude/skills/implement-spec/SKILL.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -name: implement-spec -description: "Implement the result of /to-spec and /to-tickets in code." ---- - -You have been provided a spec. This spec should have tickets associated with it, describing how to implement the spec. - -The issue tracker should have been provided to you. If not, tell the user to run `/setup-matt-pocock-skills`. - -The goal is the entire spec implemented on a single **integration branch**, with every ticket resolved the way the issue tracker closes work. - -The tickets are not a list of steps. They are a **task graph** with blocking relationships between them. This means there is always a **frontier** of tickets which are ready to be grabbed. - -Communication to and from subagents should be sparse. Communicate primarily through **context pointers**: to the spec, tickets, research notes, and previous commits. Don't duplicate information already available via pointers. - -**Implementer subagents** should be run in the background where possible for maximum concurrency. - -## Steps - -1. Read the spec and tickets to understand the task graph. For each ticket, start from its plan commit and its acceptance file (`docs/tickets///aceite.md`), as the root `AGENTS.md`, section "Plano do ticket", describes. If a ticket has no plan commit, stop and ask for `/plan-ticket` first. Every acceptance test carries its criterion ID in a tag. - -2. (optional) Use an **exploration subagent** to conduct any exploration required by the tickets - relevant codebase files or external documentation. Ensure the exploration subagent can save files - it should save its markdown notes in a directory outside the repo, accessible by all future subagents. This lets **implementer subagents** focus on implementation rather than exploration. - -3. Create the integration branch. If the issue tracker closes work through PRs, or the user asks for one, open a draft PR after the first merge in step 5 (a branch with no commits ahead of main can't open one), marked as closing the spec and tickets. - -4. Use **implementer subagents** to implement each ticket, each in its own worktree on its own branch. Each implementer subagent: - - confirms its worktree is based on the integration branch before starting, and resets onto it if not; - - calls the Skill tool with `tdd` to build the ticket; - - runs only the tests tied to the files it changed, and never `scripts/verify.sh full`, which is the main session's; - - merges the integration branch tip into its own branch before reporting done - -5. Once an **implementer subagent** completes, merge its work to the integration branch with a **merger subagent**. - -6. If this changes the **frontier** of available tickets, kick off more **implementer subagents** to work on the new tickets. This allows for maximum concurrency. - -7. Once all tickets are complete, call the Skill tool with `simplify` and then with `code-review` on the integration branch. Then call the Skill tool with `revisao-conformidade` once per ticket: each review gets the same diff of the integration branch, in that ticket's folder, with its identifier, plan message and contract drift. Triage each ticket's findings in the main session, as step 5 of that skill says, and fix the issues raised by the code review and the findings you accepted in a single **implementer subagent**. Then, in the main session, run `scripts/verify.sh full` once, before the commit that closes the work, as the root `AGENTS.md`, section "Definição de pronto", describes. - -8. If a draft PR exists, publish each ticket's review comment, as the `revisao-conformidade` skill describes in "Publish", and mark the PR ready for review. Otherwise, resolve each ticket the way the issue tracker closes work, and report the integration branch. - -9. Clean up all **implementer subagent** worktrees. diff --git a/.claude/skills/implement-spec/agents/openai.yaml b/.claude/skills/implement-spec/agents/openai.yaml deleted file mode 100644 index f5e91af..0000000 --- a/.claude/skills/implement-spec/agents/openai.yaml +++ /dev/null @@ -1,5 +0,0 @@ -interface: - display_name: "Implement Spec" - short_description: "Implement the result of /to-spec and /to-tickets in code." -policy: - allow_implicit_invocation: false diff --git a/.claude/skills/implement/SKILL.md b/.claude/skills/implement/SKILL.md index 0d879ec..db0ff85 100644 --- a/.claude/skills/implement/SKILL.md +++ b/.claude/skills/implement/SKILL.md @@ -1,19 +1,25 @@ --- name: implement -description: "Implement a piece of work based on a spec or set of tickets." +description: "Implement one ticket in the session of its front, from its plan commit and acceptance file: tdd at the agreed seams, a commit, the sync skill, the review skills, the full once in the background, and the delivery of the pull request when the user asks." disable-model-invocation: true --- -Implement the work described by the user in the spec or tickets. +Implement one ticket, in this session and in this checkout (the front of the ticket). The flow, step by step; the rules around it are in the root `AGENTS.md`. -If the user passes a ticket reference, fetch it from the issue tracker and state its title before starting. If the reference is ambiguous, ask. +1. **Which ticket.** If the user passes a ticket reference, fetch it from the issue tracker and state its title before starting. If the reference is ambiguous, ask. Take only a ticket whose blocking tickets are done. -If the ticket has a plan commit, start from it and from its acceptance file (`docs/tickets///aceite.md`), and put each criterion ID in a tag of its acceptance test, as the root `AGENTS.md`, section "Plano do ticket", describes. If it has none, stop and ask for `/plan-ticket` first. +2. **The plan.** The ticket needs a plan commit. Start from it and from its acceptance file (`docs/tickets///aceite.md`), as the root `AGENTS.md`, section "Plano do ticket", describes. If there is no plan commit, stop and ask for `/plan-ticket` first. The issue should already be "In Progress", because `/plan-ticket` moves it when planning starts; if it is not, move it now. -Call the Skill tool with "tdd" where possible, at pre-agreed seams. +3. **Build it.** Call the Skill tool with "tdd" at the seams the plan agreed, putting each criterion ID in a tag of its acceptance test. A ticket with no test criterion has no `tdd`: deliver each criterion as its scenario describes. While working, run only the tests tied to the files you changed, with the commands of the `AGENTS.md` of each project; the stop hook already runs the type and lint checks. -While working, run only the tests tied to the files you changed, with the commands in the project's `AGENTS.md`; the stop hook already runs the type and lint checks. +4. **Escalate, do not decide.** Stop and ask when the implementation needs a decision that is not in the ticket or in the plan and that another ticket in progress would also take, or needs to change something another ticket in progress uses (the escalation rule of the root `AGENTS.md`, "Ao trabalhar em um ticket"). The decisions the ticket takes from others, and who owns each, are in its section "Decisões de outros tickets". -Once done, call the Skill tool with "simplify" and then with "code-review" to review the work, then call the Skill tool with "revisao-conformidade" to run the conformance review and triage its findings, as that skill describes. Then run the full verification once, before the commit that closes the work, as the root `AGENTS.md`, section "Definição de pronto", describes. +5. **Commit.** Once the work is done, commit it to the current branch, which is never the principal branch, without pushing: the next step needs a clean folder. -Commit your work to the current branch. +6. **Bring the main.** Call the Skill tool with "sincronizar", for the end of the ticket (its second ending): it merges the current principal branch, adapts, commits the merge and gives control back, without reviewing, running the `full` or pushing. It comes before the reviews on purpose, so that they see the merged result, including what the merge adapted. It does nothing when nothing entered. + +7. **Review.** Call the Skill tool with "simplify" and then with "code-review" to review the work. If the ticket has an acceptance file and the change alters code, in `apps/` or in the harness (`scripts/`, `.claude/hooks/`, `.github/`), call the Skill tool with "revisao-conformidade" to run the conformance review and triage its findings, as that skill describes, including its stop on a high-severity finding you would leave unfixed. Fix what you accept, and commit the fixes. + +8. **Verify.** Run `scripts/verify.sh full` once, in the background, as the root `AGENTS.md`, section "Definição de pronto", describes. If the branch changes `apps/`, save the body of the pull request, with its `## Aceite` section, in a file and pass it as `ACCEPTANCE_BODY_FILE=`, here and in every run after a fix: without it the `full` records the acceptance as skipped and the push hook refuses the approval, which would need another complete run ("Antes do push" of that file). If the `full` leads to fixes, commit them and run it again. A subagent never runs it. + +9. **Deliver, when the user asks.** With the `full` approved, stop and say the work is ready: the body of the pull request, the conformance review and the report of the sync. Do not push, open the pull request or publish anything before the user asks for it (as "suba a PR"). When they do: a plain `git push`, the pull request with the saved body plus the report of the sync (what entered, the conflicts, what was adapted), and the review comment, as the "Publish" part of `revisao-conformidade` describes. The merge of the pull request is the user's, as the root `AGENTS.md`, section "Convenções de Git", says: this skill never merges. After the user merges, and only if they ask, `scripts/frentes.sh remover ` takes the front down; never with `--forcar`, which is the user's. diff --git a/.claude/skills/plan-ticket/SKILL.md b/.claude/skills/plan-ticket/SKILL.md index eaf0819..0a8ddfc 100644 --- a/.claude/skills/plan-ticket/SKILL.md +++ b/.claude/skills/plan-ticket/SKILL.md @@ -16,9 +16,9 @@ The scripts are in `scripts/`, in this skill's folder. They need `git` and `bash - **Node command:** called as `