Skip to content

bug: implement-batch riporta successo su un batch vuoto per args invalidi, e la guardia anti-duplicazione della first-review dipende da prNumber passato dal chiamante #401

Description

@rucka

Problema

Due difetti in .claude/workflows/implement-batch.js, entrambi osservati guidando il batch #277/#230/#281/#236/#234/#279 (PR #386#391).

1. Un batch che non guida nulla riporta successo

args veniva normalizzato così: se stringa, JSON.parse in try/catch; al catch, _args = undefined; poi const STORIES = _args?.stories ?? [].

Chiamandolo con args: "#234 #236 #281 …" — la forma suggerita dalla riga di invocazione della skill, che interpola verbatim gli argomenti ricevuti — il parse falliva, STORIES diventava [], e il run usciva in ~30 ms con zero agent restituendo:

{ "contracts": [], "batch": [], "note": "PRs are ready-for-merge or escalated. Merge is the human gate…" }

Cioè la forma di un batch completato con successo, indistinguibile da un run reale in cui tutte le storie sono fallite. Il primo lancio del batch è andato a vuoto senza alcun segnale.

2. La guardia anti-duplicazione della first-review dipendeva dalla contabilità del chiamante

Il continuation probe (#373) era dentro if (resuming), dove resuming = Number.isInteger(story.prNumber) — quindi girava solo se il chiamante aveva passato prNumber nell'oggetto storia.

Un resume via Workflow({resumeFromRunId}) rieseguisce gli agent implement/PR dalla cache con gli stessi args: story.prNumber è assente, resuming è false, il probe non parte, firstReviewPosted resta false e il round-0 posta un'altra first-review su una PR che ne ha già una.

Osservato tre volte sulla stessa storia (#234, PR #390) attraverso tre cicli pausa/ripresa: quella storia è stata rivista da zero ogni volta invece di avanzare nei round di fix, ed è finita la meno progredita del batch — con 4 Major ancora aperti quando le altre erano a zero.

Impatto

  • (1) fa perdere un lancio senza accorgersene; un orchestratore che riceve batch: [] non ha modo di distinguere "input sbagliato" da "batch vuoto legittimo".
  • (2) spreca un round di review opus/xhigh per storia per ciclo di ripresa, e fa regredire il progresso della storia.

Fix atteso

  1. Validare l'input rumorosamente: lanciare su stringa non-JSON, args assente, oggetto senza stories, o storia priva di id/title/branch — con un messaggio che dica la forma richiesta e perché title/branch non sono derivabili (il sandbox non ha accesso a gh/filesystem). Una lista esplicitamente vuota resta un no-op legittimo.
  2. Legare il probe all'esistenza della PR, non a story.prNumber: un probe sonnet/low per storia per run costa molto meno di una review opus duplicata, e su una storia fresh entrambi i segnali tornano false lasciando il comportamento identico.
  3. Rendere il contratto degli argomenti visibile nel meta del workflow, così il chiamante lo legge prima di invocare.

Note

Il difetto (1) non è "il chiamante ha sbagliato": la riga di invocazione della skill interpola gli argomenti ricevuti dentro Workflow({args: …}) senza convertirli, quindi la forma sbagliata è raggiungibile per costruzione.

Metadata

Metadata

Assignees

Labels

tech-debtTracked technical debt (living backlog, R7.2 — never blocks a PR)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions