Codex vs Claude: la questione non è tanto quella di individuare un vincitore assoluto, quanto piuttosto quella di scegliere lo stile di lavoro su cui poter contare ogni giorno. Entrambi i prodotti consentono di esaminare un repository, modificare più file, eseguire comandi, eseguire test e fornire spiegazioni su una patch. Le differenze sostanziali risiedono nel modo in cui si delegano le attività, nella frequenza con cui si guida l’agente, nella quantità di dati che è possibile esaminare e nella compatibilità di ciascuno strumento con l’ambiente di sviluppo esistente.
Nel nostro test controllato su un repository composto da quattro attività, Codex ha ottenuto un punteggio di 98/100 e Claude Code di 99/100. Entrambi hanno completato il lavoro principale. Claude Code ha mostrato una revisione più ampia e una copertura più estesa dei casi limite, mentre Codex ha spesso raggiunto il risultato richiesto con un ambito più ristretto e ha prodotto prove a livello di esecuzione più solide nella nostra configurazione. Una differenza di un punto su un piccolo fixture Python non è un motivo sufficiente per dichiarare un vincitore assoluto.
Gli sviluppatori che non desiderano che il resto del proprio flusso di lavoro sia vincolato a un unico agente di codifica possono aggiungere GlobalGPT come livello multimodello e multimodale separato. GlobalGPT integra oltre 100 modelli di punta, quali GPT 5.6, Claude Opus 5 e GPT Image 2, in un'unica dashboard. Inoltre, il GlobalGPT CLI, I percorsi MCP e Skill possono essere utilizzati tramite Codex o Claude Code per ottenere un secondo parere, per la pianificazione, la documentazione o altri modelli supportati, mentre l'host di codifica nativo mantiene il controllo sulle modifiche al repository e sui test.

Il confronto integra informazioni ufficiali sui piani, attività pratiche sul repository, output completi ed espandibili ed esperienze della comunità chiaramente descritte. L'obiettivo è aiutare uno sviluppatore indipendente a scegliere un linguaggio di programmazione principale senza confondersi tra abbonamenti, crediti aggiuntivi e fatturazione delle API.
Codex vs Claude: il codice in sintesi
| Fattore determinante | Codice | Codice Claude |
|---|---|---|
| Attività relative al repository principale | Legge, modifica, esegue comandi e verifica le modifiche su tutte le superfici Codex supportate | Agente terminale interattivo per la lettura, la modifica, l'esecuzione di comandi e la verifica delle modifiche |
| Stile osservato nel nostro test | Più compatto in alcune parti relative all'implementazione e alla correzione dei bug | Maggiore completezza nell'analisi dei repository, nei test e nell'ampiezza della revisione |
| Comprensione del repository | Collegamento funzionale all'attività congelata | |
| Revisione del codice | Sono stati individuati e risolti due difetti validi di gravità maggiore | Ha segnalato ulteriori problemi riproducibili e ha portato il punteggio da 19/20 a 18/20 |
| Velocità rilevata | Risultato misto; le condizioni non erano sufficientemente omogenee per poter designare un vincitore assoluto | |
| Fascia di ingresso per i consumatori | $20/mese tramite il relativo piano ChatGPT | Claude Pro: $20 al mese negli Stati Uniti |
| Livelli con maggiore utilizzo | Livelli $100 e $200 | Massimo 5x a $100 e massimo 20x a $200 |
La tabella illustra una decisione di acquisto, non una classifica dei modelli. Impostazioni del modello, repository, configurazioni dei permessi o specifiche delle attività diverse possono modificare il risultato. Se si utilizza già un prodotto, il confronto più appropriato è un’attività circoscritta tratta dal proprio codice sorgente, con lo stesso comando di successo e senza ripetizioni per motivi di qualità.
Profilo di prova controllato
Primo risultato valido, stessa griglia di valutazione fissa. Le barre sono normalizzate in base al punteggio massimo di ciascuna attività.
Il grafico mostra da dove deriva quella differenza di un punto; non trasforma però una piccola partita in una classifica generale.
Cosa sono in realtà il Codex e il codice Claude
Codex e Claude Code sono prodotti di agenti, non semplici nomi di modelli. Il concetto alla base Modello di intelligenza artificiale per la programmazione è importante, ma anche l’infrastruttura circostante determina quali file l’agente può visualizzare, quali comandi può eseguire, come funzionano le approvazioni, come viene conservato il contesto e quali dati rimangono dopo il completamento dell’attività. Limitare il confronto alla sola reputazione del modello significa ignorare gran parte dell’esperienza che uno sviluppatore sta acquistando.
Codex copre flussi di lavoro basati su riga di comando, IDE, desktop e orientati al cloud. Questa versatilità lo rende adatto sia alla collaborazione locale diretta che a forme di delega più circoscritte. Claude Code è incentrato su un flusso di lavoro terminale di tipo conversazionale, con integrazioni supportate e ampie possibilità di personalizzazione; questo Guida all'uso di Claude per la codifica fornisce un'introduzione più approfondita a tale flusso di lavoro. Per alcuni sviluppatori, osservare il funzionamento di un agente nel terminale è rassicurante. Per altri, invece, ciò che conta sono il diff finale, i test e la traccia di audit, piuttosto che una conversazione continua.
Questa distinzione spiega anche perché due test che utilizzano modelli nominalmente robusti possano dare risultati diversi. È l’host a decidere come vengono presentate le istruzioni, come vengono richiamati gli strumenti e quando è necessaria l’approvazione umana per un’azione. I confronti tra comunità che ignorano l’harness possono scambiare un comportamento a livello di prodotto per una verità a livello di modello.
- Il modello fornisce capacità di ragionamento e di generazione.
- Il cablaggio dell'agente gestisce i file, i comandi, il contesto, le approvazioni e il ripristino.
- Il contratto di incarico dell'utente determina l'ambito di applicazione, i controlli di successo e il momento in cui l'agente deve interrompere l'azione.

Flusso di lavoro e controllo: delega o guida continua?
La domanda più utile riguardo al confronto tra Codex e Claude spesso non è “Quale dei due scrive codice migliore?”, ma “Come voglio utilizzarlo?”. Un compito chiaro e ben definito può essere delegato con un obiettivo preciso, un ambito consentito e un comando di verifica. Una rifattorizzazione ambigua trae vantaggio dalla discussione, dall’ispezione intermedia e dalla possibilità di reindirizzare l’agente prima che apporti modifiche eccessive.
La guida continua è utile quando i requisiti sono in evoluzione o le scelte architetturali sono ancora in fase di definizione. Diventa invece un costo quando l’agente richiede ripetutamente decisioni che avrebbero potuto essere risolte sulla base delle istruzioni contenute nel repository. L’esecuzione autonoma è utile quando il contratto di attività è stabile. Diventa rischiosa quando l’agente formula ipotesi non verificate o amplia l’ambito di applicazione senza un chiaro percorso di rollback.
Un rapporto dettagliato pubblicato su Reddit il 13 aprile 2026 descriveva circa 100 ore di utilizzo di Claude Code e 20 ore di Codex su un progetto in Python e TypeScript di circa 80.000 righe con circa 2.800 test. L'autore ha descritto Claude come più veloce e interattivo, ma che richiede maggiore supervisione, mentre Codex è risultato più lento e ponderato. Tale rapporto è particolarmente utile perché include il contesto del progetto e dell'esperienza, ma rappresenta comunque il flusso di lavoro di un singolo sviluppatore.

I nostri tempi di esecuzione non hanno individuato un chiaro vincitore. Claude ha completato più rapidamente i primi due compiti, mentre Codex ha completato più rapidamente gli ultimi due. Inoltre, Claude ha fatto ricorso a un subagente di riserva quando il suo percorso di autenticazione CLI non era disponibile, pertanto i percorsi di esecuzione non erano equivalenti a quelli di laboratorio. La conclusione più ragionevole è che la velocità dipenda dall’attività, dal modello selezionato, dall’impostazione dello sforzo, dal contesto e dall’host, e non che uno dei due prodotti sia sempre più veloce.
Comprensione del repository e gestione del contesto
Comprendere il repository va ben oltre la semplice denominazione delle cartelle. Un agente utile deve tracciare il percorso dei dati tra i file, identificare i contratti che limitano una modifica, individuare i test, distinguere un sintomo dalla sua probabile causa e spiegare il rischio derivante dalla modifica del livello sbagliato. Una mappa esaustiva può rivelare incongruenze nascoste; una mappa concisa può aiutare uno sviluppatore a giungere più rapidamente a una decisione di implementazione sicura.
Nel nostro compito T1 in sola lettura, entrambi gli agenti hanno ottenuto un punteggio di 20/20 e hanno basato le loro risposte sul repository. Claude Code è risultato più esaustivo e ha evidenziato ulteriori incongruenze nei contratti. Codex è risultato più conciso, pur identificando i file rilevanti, i rischi e il piano di implementazione. Nessuno dei due stili è automaticamente superiore. L’esaustività è utile durante migrazioni e audit in contesti poco familiari; la concisione è utile quando lo sviluppatore conosce già l’architettura e desidera un piano di modifica mirato.
T1 · Test del repository controllato
Comprendere un repository che non si conosce prima di apportarvi modifiche
Mappare l'architettura, tracciare il flusso dei dati, identificare i rischi relativi alle funzionalità prioritarie e non apportare modifiche ai file.
Architettura: modello, repository, servizio e un’utilità temporale non cablata. Rischi principali: semantica delle priorità non definita, compatibilità, ordinamento, convalida e discrepanza di ambito.
Il parere del recensore: Conciso, basato sui fatti e adeguato alla decisione in sospeso.
Tre livelli più un modulo isolato. Nessun ciclo; iniezione di dipendenze minima. Sono emersi inoltre problemi relativi all'assegnazione degli identificatori, ai contratti di errore asimmetrici e alla scarsa copertura dei test.
Il parere del recensore: Più esaustivo, pur rispettando lo stesso contratto di sola lettura.
Visualizza l'output completo di Codex
Risultato completo, sanificato e valido
Architettura ##
Si tratta di un piccolo pacchetto Python che utilizza esclusivamente le librerie standard e presenta quattro livelli funzionali:
- **Modello di dati:** [`Job`]() è una classe di dati immutabile contenente `identifier`, `name` e `owner`. `Job.to_dict()` la serializza tramite `dataclasses.asdict()`.
- **Repository:** [`JobRepository`]() memorizza i lavori in un dizionario in memoria con chiave `identifier`. Non è previsto alcun database né alcuna persistenza duratura.
- **Servizio:** [`SchedulerService`]() si occupa dell’assegnazione degli identificatori, della normalizzazione degli input, della creazione, dell’elenco e dell’eliminazione.
- **Utilità temporale:** [`next_daily_run()`]() calcola l’ora della successiva esecuzione, ma non viene importata né collegata a `Job`, `SchedulerService` o `JobRepository`.
- **API pubblica:** [`scheduler.__init__`]() esporta solo `SchedulerService`.
Nonostante il nome del repository, attualmente i job non contengono informazioni di pianificazione e non esiste una coda di esecuzione. La priorità può quindi influire sui metadati memorizzati e sull’ordine di visualizzazione, ma non può influire sull’effettiva esecuzione dei job senza ampliare notevolmente il sistema.
## Flusso dei dati di creazione e visualizzazione
Creazione tramite `SchedulerService.create_job(name, owner)`:
1. [`create_job()`]() rifiuta un nome composto esclusivamente da spazi.
2. Elimina gli spazi in eccesso da `name` e `owner`, quindi costruisce un oggetto `Job` immutabile utilizzando il `_next_identifier` del servizio.
3. [`JobRepository.save()`]() salva l’oggetto in `_jobs[job.identifier]`.
4. Il servizio incrementa `_next_identifier` e restituisce lo stesso oggetto `Job`.
Elenco tramite `SchedulerService.list_jobs()`:
1. [`list_jobs()`]() delega direttamente a `repository.all()`.
2. [`JobRepository.all()`]() ordina le chiavi del dizionario in ordine numerico.
3. I lavori vengono quindi restituiti in ordine crescente di identificatore/data di creazione, non in ordine di pianificazione o priorità.
## File probabilmente interessati dalle priorità dei lavori
Obbligatorio:
- [`scheduler/models.py`](): aggiungere il campo "priority" e un eventuale valore predefinito. `to_dict()` lo includerà automaticamente poiché utilizza `asdict()`.
- [`scheduler/service.py`](): accetta, convalida e passa la priorità a `Job`.
- [`tests/test_scheduler.py`](): verificare il comportamento in caso di valore predefinito, esplicito, non valido, serializzato e relativo all’ordinamento.
Condizionale:
- [`scheduler/repository.py`](): modificare `all()` solo se le priorità sono destinate a controllare l'ordine di elenco. Una chiave secondaria deterministica come `identifier` dovrebbe gestire i casi di parità.
- [`scheduler/__init__.py`](): aggiornare solo se la priorità diventa un enum pubblico o un oggetto valore.
- [`README.md`](): documentare i valori accettati, il valore predefinito e la semantica di ordinamento.
Probabilmente non interessato:
- `scheduler/time_rules.py`, poiché il suo unico simbolo opera su una data e ora fornite e non ha alcuna relazione con i lavori o l’elenco.
## Rischi principali
- **Semantica indefinita:** il codice non fornisce alcun precedente per stabilire se valori più grandi o più piccoli indichino una priorità più alta, quali valori siano validi o se la priorità influisca in qualche modo sull’ordine di visualizzazione.
- **Compatibilità:** L’aggiunta di un argomento obbligatorio a `Job` o a `create_job()` comprometterebbe il funzionamento delle chiamate esistenti, come `create_job("Daily report", "Alex")` nel test attuale. Un valore predefinito preserverebbe tale chiamata.
- **Problemi legati al costruttore posizionale:** `Job` viene attualmente costruito in modo posizionale in `SchedulerService.create_job()`. La posizione dei campi e future chiamate posizionali potrebbero assegnare silenziosamente valori errati; l’uso di un costruttore basato su parole chiave sarebbe più sicuro.
- **Modifica dell’ordinamento:** la sostituzione dell’ordinamento degli identificatori in `JobRepository.all()` modifica il comportamento consolidato. In caso di priorità uguali è necessario un criterio di spareggio stabile.
- **Ambiguità nella convalida:** un valore Python senza restrizioni potrebbe consentire stringhe, valori booleani o interi arbitrari difficili da confrontare in modo coerente.
- **Incoerenza nell’ambito di esecuzione:** Non esiste un dispatcher né una coda di esecuzione. Affermare che la priorità determini quale lavoro venga eseguito per primo non sarebbe supportato da alcun simbolo attuale.
- **Limiti in memoria:** la priorità, come ogni altro campo del job, scompare al termine del processo poiché `_jobs` è solo un dizionario di istanza.
## Piano di implementazione e convalida
1. Definire innanzitutto il contratto: rappresentazione, valori consentiti, valore predefinito, direzione della priorità, criterio di spareggio e se modifica l’ordine di elenco.
2. Aggiungere `priority` a `Job`, preferibilmente con un valore predefinito retrocompatibile.
3. Estendere `SchedulerService.create_job()` con un parametro di priorità predefinito, convalidarlo e costruire `Job` con argomenti chiave.
4. Se l’elenco tiene conto della priorità, modificare `JobRepository.all()` per ordinare prima in base alla priorità e poi all’identificatore. Altrimenti lasciare invariato l’ordinamento del repository.
5. Aggiungere test per:
- Creazione esistente a due argomenti.
- Mantenimento esplicito della priorità.
- Priorità predefinita.
- Tipo non valido e valori fuori intervallo.
- Output di `Job.to_dict()`.
- Ordine di visualizzazione in presenza di priorità multiple.
- Ordinamento stabile per priorità uguali.
- Comportamento esistente in caso di nome vuoto.
6. Aggiornare il README con il contratto pubblico esatto.
7. Eseguire la suite completa offline con `python3 -m unittest discover -s tests -v`.
## Verifica eseguita
- Suite di test di base: **2 test superati**.
- La ricerca dei simboli a livello di repository ha confermato che `next_daily_run()` è scollegato e che non esistono simboli di priorità.
- File modificati: **nessuno**.
- Implementazione della funzionalità: **non eseguita**, come richiesto.
> **Conclusione + decisione**
>
> La modifica è minima se la priorità è solo un metadato o riguarda l’ordine di elenco: principalmente `models.py`, `service.py`, `repository.py` e i test. Prima dell’implementazione, occorre decidere se la priorità descriva semplicemente un lavoro o modifichi l’ordinamento di `list_jobs()`, oltre alla scala dei valori, al valore predefinito, alla direzione e alla regola di spareggio.Visualizza l'output completo del codice Claude
Registro completo del passaggio di consegne, compreso il testo integrale del primo output valido
# T1 Registro di esecuzione — Comprensione di un repository sconosciuto
## Parametri di esecuzione
| Campo | Valore |
| --- | --- |
| Attività | `T1` |
| Prompt congelato | `01-prompts/T1.md` |
| SHA-256 del prompt congelato | `a571ff15c2502ec29b172ae2e77dd9ab0caca2869b91f9468d47571434d16c17` |
| Unità di esecuzione | subagente Claude isolato, `general-purpose`, contesto nuovo |
| Metodo di isolamento | **fallback del subagente** (downgrade documentato — vedi `results/isolation-decision.md`) |
| Copia pulita assegnata | `runtime/workspaces/T1` |
| Versione del codice Claude | `2.1.220` |
| Impostazione del modello | `claude-opus-5` |
| start_utc | `2026-07-28T10:27:31Z` |
| end_utc | `2026-07-28T10:28:32Z` |
| Durata | 61 s (in concomitanza con T2–T4; misurazione della latenza non precisa) |
| Numero di tentativi | 1 |
| Stato | `valido` |
| Intervento umano | nessuno |
## Riepilogo degli strumenti sicuri
`date`, `find`, `ls`, `wc`, `stat`, `grep`, `Read` su 7 file dell’area di lavoro, `python3 -V`,
`python3 -m unittest discover -s tests -v`. Tutte le operazioni di lettura limitate all’area di lavoro assegnata.
Nessuna rete, nessuna installazione, nessuna scrittura.
## Risultato del controllo offline
`python3 -m unittest discover -s tests -v` → 2 test, OK (uscita 0). Riverificato dal
coordinatore dall’esterno dell’area di lavoro: vedi `results/checks/T1-public.txt`.
## Patch
Nessuna. `results/T1/patch.diff` è vuoto e `diff -ru 02-fixture runtime/workspaces/T1`
non restituisce alcuna differenza. L’attività richiedeva un’ispezione senza modificare i file; ciò è
stato confermato piuttosto che asserito.
## Errori corretti
Un errore recuperabile della shell: un `grep` iniziale utilizzava pattern `--include=*.py` senza virgolette che
la shell ha tentato di espandere con glob; l'esecuzione è stata ripetuta con pattern tra virgolette e ha avuto esito positivo. Nessun effetto sui risultati.
## Output visibile (testuale)
### 1. Che cos’è questo repository
Un fixture autonomo della libreria standard di Python denominato `local-scheduler-1.0.0` (`fixture-manifest.json`), con licenza MIT, senza dipendenze di rete o di produzione (`README.md`, `"network_required": false`). È molto piccolo: 8 file sorgente/documentazione più il manifesto, per un totale di 103 righe. L’interprete utilizzato è **Python 3.9.6**. Non sono presenti `pyproject.toml`, `setup.py`, configurazioni CI, linter o configurazioni del type-checker: l’unico flusso di lavoro dichiarato è `python3 -m unittest discover -s tests -v` (`README.md`).
### 2. Architettura
Tre livelli più un modulo orfano, tutti all’interno di `scheduler/`:
| Livello | File | Simbolo | Responsabilità |
|---|---|---|---|
| Facciata del pacchetto | `scheduler/__init__.py` | `__all__ = ["SchedulerService"]` | Riesporta solo `SchedulerService`; `Job`, `JobRepository` e `time_rules` non fanno parte dell’interfaccia pubblica |
| Modello di dominio | `scheduler/models.py` | `Job` (`@dataclass(frozen=True)`) | Oggetto valore immutabile con i campi `identifier: int`, `name: str`, `owner: str`, oltre a `to_dict()` implementato come `asdict(self)` |
| Persistenza | `scheduler/repository.py` | `JobRepository` | `dict` in memoria con chiave `identifier`; `save`, `get`, `all`, `delete` |
| Servizio applicativo | `scheduler/service.py` | `SchedulerService` | Convalida, assegnazione dell’identificatore, orchestrazione: `create_job`, `list_jobs`, `delete_job` |
| Orfano | `scheduler/time_rules.py` | `next_daily_run` | Calcolo della ricorrenza — **non importato da nessun altro** |
La direzione delle dipendenze è chiara e unidirezionale: `service.py` importa da `.models` e `.repository`; `repository.py` importa da `.models`; `models.py` importa solo `dataclasses`. Nessun ciclo. L’iniezione di dipendenze è presente ma minima — `SchedulerService.__init__(self, repository=None)` esegue `self.repository = repository or JobRepository()`, quindi nei test è possibile sostituirlo con un repository fittizio.
Si noti che `scheduler/time_rules.py` è attualmente codice morto. Ho cercato con grep in tutto l’albero `time_rules` e `next_daily_run`; gli unici risultati sono la sua stessa definizione e la sua presenza in `expected_files` di `fixture-manifest.json`. È incluso nel rilascio ma non è collegato.
### 3. Flusso dei dati
**Creazione di un lavoro** — `SchedulerService.create_job(name, owner)`:
1. Controllo: `if not name.strip(): raise ValueError('name is required")`. Questa è l"*unica* validazione nel sistema — `owner` non viene mai verificato, quindi viene accettato anche un proprietario vuoto.
2. Costruzione: `Job(self._next_identifier, name.strip(), owner.strip())` — costruzione posizionale, ed entrambe le stringhe vengono normalizzate tramite stripping.
3. Persistenza: `self.repository.save(job)`, che esegue `self._jobs[job.identifier] = job` e restituisce il job.
4. Incremento del contatore: `self._next_identifier += 1` — *dopo* il salvataggio, quindi un’eccezione generata lascia il contatore non utilizzato.
5. Restituzione dell’istanza `Job` (il servizio restituisce il proprio `job` locale, non il valore restituito dal repository).
L’assegnazione degli identificatori avviene nel **servizio**, non nel repository (`self._next_identifier = 1` in `SchedulerService.__init__`). Questo è un punto di giunzione importante: l’iniezione di un repository che contiene già dei lavori li sovrascriverà silenziosamente, poiché il nuovo servizio ricomincia la numerazione da 1.
**Elenco dei lavori** — `SchedulerService.list_jobs()` è un semplice pass-through a `JobRepository.all()`, che restituisce `[self._jobs[key] for key in sorted(self._jobs)]`. L’ordinamento è quindi **ascendente in base all’identificatore intero**, che attualmente coincide con l’ordine di inserimento. Ad ogni chiamata viene creato un nuovo elenco, ma gli oggetti `Job` sono riferimenti condivisi — sicuri solo perché `Job` è congelato.
**Eliminazione** — `SchedulerService.delete_job(identifier)` delega a `JobRepository.delete`, che è `self._jobs.pop(identifier)` senza valore predefinito, quindi genera un `KeyError` in caso di ID mancante. Ciò è incoerente con `JobRepository.get`, che restituisce `None` nella stessa condizione.
**Copertura di test di questi percorsi** — `tests/test_scheduler.py` presenta esattamente due casi: `test_create_and_list_jobs` (verifica che `job.identifier == 1` e `[job] == service.list_jobs()`) e `test_blank_name_is_rejected`. Entrambi superano il test sull’albero attuale.
### 4. File che potrebbero essere interessati dall’aggiunta delle priorità dei lavori
In ordine decrescente di certezza:
1. **`scheduler/models.py`** — certo. `Job` necessita di un campo `priority`. Poiché la classe di dati è `frozen=True` e i campi sono posizionali, un nuovo campo deve avere un valore predefinito (ad es. `priority: int = 0`) oppure deve essere posizionato dopo i tre esistenti; in caso contrario, ogni costruzione posizionale esistente verrebbe compromessa. `to_dict()` non necessita di modifiche — `asdict(self)` rileva automaticamente il campo, il che costituisce una modifica silenziosa del contratto di serializzazione piuttosto che una modifica del codice.
2. **`scheduler/service.py`** — certo. `create_job` richiede un parametro `priority` e deve passarlo al costruttore posizionale `Job(...)` alla riga 13. Se la priorità viene convalidata (intervallo, appartenenza a un'enumerazione), la condizione di controllo va inserita accanto al controllo esistente `name.strip()`. Se l’elenco deve essere ordinato in base alla priorità, `list_jobs` è il punto in cui andrebbe inserita una politica di ordinamento se si desidera che il repository rimanga un semplice archivio.
3. **`scheduler/repository.py`** — probabile. Il metodo `sorted(self._jobs)` di `JobRepository.all()` ordina le *chiavi* del dizionario, ovvero gli identificatori. L'elenco ordinato per priorità richiede di modificare questo codice per ordinare i valori in base a una chiave come `(-job.priority, job.identifier)`, oppure di aggiungere un accessore ordinato separato. Non lasciare implicito il criterio di spareggio: l’ordine di inserimento nel dizionario non è un contratto stabile su cui fare affidamento.
4. **`tests/test_scheduler.py`** — certo. Nuovi casi per la priorità predefinita, la priorità esplicita, l’ordinamento e il rifiuto delle priorità non valide. Si noti che l’attuale `assertEqual([job], service.list_jobs())` confronta lo *stesso* oggetto, quindi sopravvive all’aggiunta di un campo; non sopravvivrebbe se confrontasse un letterale `Job` appena costruito.
5. **`README.md`** — probabilmente, se la semantica della priorità (quale estremità dell’intervallo prevale, valore predefinito) deve essere specificata da qualche parte.
6. **`scheduler/__init__.py`** — solo se è necessario esportare un enum di priorità o delle costanti insieme a `SchedulerService`.
7. **`fixture-manifest.json`** — solo se si aggiunge un nuovo file di modulo; il suo array `expected_files` è un inventario esplicito e potrebbe subire variazioni.
8. **`scheduler/time_rules.py`** — *non* dovrebbe essere modificato. La priorità è ortogonale alla ricorrenza e questo modulo non è collegato.
### 5. Rischi principali
- **La semantica di ordinamento rappresenta un cambiamento di comportamento silenzioso.** `JobRepository.all()` attualmente garantisce l’ordinamento per identificatore crescente e `list_jobs` lo eredita. Qualsiasi consumatore che faccia affidamento su tale garanzia viene compromesso dal riordinamento. Decidere esplicitamente: `list_jobs()` cambia significato, oppure viene introdotto un nuovo `list_jobs_by_priority()` accanto ad esso? La prima opzione è quella a rischio maggiore e il test esistente `test_create_and_list_jobs` è troppo debole per rilevare una regressione (lista con un solo elemento).
- **La direzione di ordinamento è davvero ambigua.** 'Priorità 1" convenzionalmente significa *la più alta* in alcuni sistemi e *la più bassa* in altri. In questo repository non c’è nulla — né commenti, né stringhe di documentazione, né righe nel README — che chiarisca la questione. Scegliete una convenzione, documentatela in `models.py` e codificatela in un test con almeno tre priorità distinte, in modo che la direzione sia fissata.
- **I casi di parità nell’ordinamento sono instabili.** Se due job condividono la stessa priorità, il risultato deve comunque essere deterministico. La funzione `sorted` di Python è stabile, ma la stabilità è utile solo se l’ordine di input è a sua volta definito. Includete sempre `identifier` come chiave secondaria esplicita.
- **Ordine dei campi in una dataclass congelata.** `Job` è `@dataclass(frozen=True)` con tre campi posizionali, e `service.py:13` lo costruisce in modo posizionale. Inserire `priority` in qualsiasi posizione diversa dall’ultima, o senza un valore predefinito, costituisce una modifica che compromette la compatibilità (breaking change) che i due test esistenti potrebbero non evidenziare in modo evidente.
- **Ampliamento del contratto `to_dict()` che amplia il contratto.** `asdict(self)` riflette tutti i campi. L’aggiunta di `priority` modifica ogni payload serializzato senza alcuna modifica visibile nel corpo del metodo in `models.py`. Qualsiasi asserzione sulla forma esatta del dizionario non funzionerà più.
- **Vincoli di Python 3.9.6.** L’assenza di `@dataclass(slots=True)` (3.10+), di `kw_only=True` (3.10+) e delle annotazioni PEP 604 `int | None` causa errori in fase di esecuzione senza `from __future__ import annotations`. Se la priorità è modellata come un enum, `enum.StrEnum` è disponibile solo a partire dalla versione 3.11 e non è presente. Qualsiasi di queste condizioni causerebbe il malfunzionamento del fixture su questo interprete.
- **L’assegnazione degli identificatori risiede nel livello sbagliato.** `SchedulerService._next_identifier` implica che il servizio gestisca la generazione degli ID mentre il repository ne gestisce l’archiviazione. Se il lavoro sulle priorità dovesse portare a un’implementazione di un secondo repository o a fixture precaricate, questa separazione causerebbe collisioni tra gli ID e la sovrascrittura dei lavori.
- **Contratti di errore asimmetrici.** `JobRepository.get` restituisce `None` in caso di mancata corrispondenza, mentre `JobRepository.delete` genera un `KeyError`. Qualsiasi nuova ricerca relativa alla priorità dovrebbe adottare deliberatamente una convenzione, anziché ereditare accidentalmente questa incoerenza.
- **Precedente relativo a lacune nella convalida.** `create_job` convalida `name` ma non `owner`. Non replicare tale lassismo per `priority`: una priorità non convalidata si propaga nella chiave di ordinamento e può generare un `TypeError` in profondità all’interno di `sorted` (ad es. confrontando `int` con `None`) anziché nel punto di chiamata.
- **Trappola del codice morto.** `scheduler/time_rules.py` sembra contenere logica di pianificazione e attirerà modifiche. Non viene importato da nessun altro file e la sua stessa stringa di documentazione ammette il bug: aggiunge 24 ore trascorse in UTC e "sposta l’ora locale dell’orologio da parete in occasione dei passaggi all’ora legale'. Modificarlo non produce alcun effetto osservabile sul sistema testato, quindi lo sforzo profuso in questo ambito è sprecato e qualsiasi test scritto su di esso non convalida nulla di ciò che viene distribuito.
- **Rete di sicurezza esile.** Due test, nessuna CI, nessun linter, nessun controllo dei tipi. Non c’è nulla che possa rilevare una regressione se non ciò che si scrive personalmente. Considerare la suite esistente come una copertura di base insufficiente, non come un filtro.
### 6. Piano di implementazione (non eseguito)
1. **Definire prima la semantica, per iscritto.** Tipo di priorità (`int` vs enum), intervallo valido, valore predefinito per i lavori esistenti/non specificati e direzione di ordinamento. Registratelo come stringa di documentazione su `Job` in `scheduler/models.py` — è l’unico punto da cui tutti i livelli dipendono già.
2. **Estendere il modello.** Aggiungere `priority: int = 0` come *ultimo* campo di `Job` in `scheduler/models.py`, preservando la compatibilità posizionale con `service.py:13` e lasciando inalterato `to_dict()`.
3. **Integralo nel servizio.** Aggiungi un parametro `priority` predefinito a `SchedulerService.create_job`, convalidalo accanto al controllo esistente `name.strip()` (genera un `ValueError`, in linea con il tipo di errore stabilito) e passalo al costruttore di `Job`.
4. **Definire esplicitamente il contratto di elenco.** Opzione preferita a basso rischio: lasciare `JobRepository.all()` così com’è come primitiva ordinata per identificatore e aggiungere un accessore separato ordinato per priorità. Se invece `list_jobs()` deve cambiare significato, modificare la comprensione di `JobRepository.all()` per ordinare i valori in base a una chiave composta esplicita che includa `identifier` come criterio di spareggio, e annotare la modifica in `README.md`.
5. **Mantenere `scheduler/__init__.py` sincronizzato** solo se è stato introdotto un enum o una costante pubblica.
6. **Non modificare `scheduler/time_rules.py`** e non aggiungere file a meno che `expected_files` in `fixture-manifest.json` non venga aggiornato nella stessa modifica.
### 7. Piano di convalida
- **Prima la baseline.** Eseguire `python3 -m unittest discover -s tests -v` prima di qualsiasi modifica e confermare che i 2 test siano superati. L’ho già fatto: i test superano senza errori.
- **Controllo di regressione.** Entrambi i test esistenti devono continuare a superare il controllo senza modifiche. Se `test_create_and_list_jobs` necessita di modifiche, ciò indica che la modifica introduce un bug, non è un motivo per modificare il test.
- **Nuovi casi in `tests/test_scheduler.py`:**
- Priorità predefinita quando `create_job` viene chiamato con la vecchia firma a due argomenti (dimostra la retrocompatibilità).
- Ciclo completo di priorità esplicita attraverso `create_job` → `list_jobs`.
- Ordinamento con **tre o più** priorità distinte, verificando l’intero elenco — è questo che determina la direzione di ordinamento.
- Spareggio: due lavori con priorità uguale vengono restituiti in ordine crescente di identificatore.
- Una priorità non valida genera un `ValueError`, analogamente al caso del nome vuoto.
- `to_dict()` include `priority` con il valore previsto.
- Percorso del repository iniettato: `SchedulerService(repository=fake)` assegna comunque correttamente la priorità, verificando l’integrazione `repository or JobRepository()`.
- **Verifica di compatibilità.** Confermare che tutto funzioni specificatamente su Python 3.9.6 — nessun `slots=`, nessun `kw_only=`, nessuna unione PEP 604 nuda, nessun `StrEnum`.
- **Controllo dell’inventario.** Rileggere `fixture-manifest.json` e confermare che l’insieme di file su disco corrisponda ancora a `expected_files`.
- **Determinismo.** Eseguire la suite due o tre volte; i bug di ordinamento che coinvolgono l’ordine di iterazione dei dizionari possono presentarsi in modo intermittente.
- **Pulizia.** Eseguire con `PYTHONDONTWRITEBYTECODE=1` in modo che le directory `__pycache__` non compaiano come variazioni non tracciate rispetto al manifesto.
Limitazione del test: si trattava di un piccolo repository Python offline. Claude ricorreva a un subagente di riserva dopo la scadenza dell'OAuth via CLI, pertanto l'isolamento e la visibilità dei token non erano identici.
Questo risultato non è indicativo delle prestazioni su un monorepo di grandi dimensioni o in una sessione autonoma della durata di una settimana. Il test è stato volutamente limitato e controllato. Per una valutazione reale, si consiglia di iniziare con una richiesta in sola lettura: chiedere a ciascuno strumento di mappare il percorso delle chiamate, indicare i file che verrebbero modificati, identificare i test ed elencare le ipotesi non risolte prima di consentire le modifiche.
Stile di implementazione, ambito delle patch e correzione dei bug
Lavoro su più file
Lo stesso comportamento di superamento dei test può derivare da scelte ingegneristiche diverse. Nel T2, entrambi i prodotti hanno ottenuto un punteggio di 30/30 e hanno superato il validatore nascosto congelato. Il codice Claude ha posizionato la validazione in più di un punto di confine e ha aggiunto test più ampi sul modello diretto e sulle soglie. Codex ha utilizzato un’implementazione più snella, incentrata sui servizi, che ha comunque soddisfatto il contratto.
Per uno sviluppatore indipendente, si tratta di un vero e proprio compromesso. Una validazione più ampia può proteggere gli invarianti quando gli oggetti vengono creati attraverso percorsi multipli. Una patch più piccola può ridurre la superficie di regressione e i tempi di revisione quando un unico servizio costituisce il punto di ingresso previsto. La risposta giusta dipende dalle regole di proprietà del repository, non dal conteggio isolato delle righe modificate o dei test.
T2 · Test del repository controllato
Implementare una funzionalità prioritaria su più file
Aggiungere il comportamento "congelato", garantire la compatibilità e superare i controlli sia pubblici che nascosti.
Ho aggiunto la priorità al modello immutabile, l'ho convalidato ai confini del servizio e ho mantenuto l'ordinamento nel repository. Tutti e sette i test pubblici e il validatore nascosto congelato sono stati superati.
Il parere del recensore: Un'implementazione più snella e incentrata sui servizi, in grado di gestire ogni comportamento "congelato".
Priorità convalidata sia a livello di confine del servizio che a livello di modello immutabile; filtro del repository mantenuto e copertura della soglia aggiunta. Quattordici test pubblici e il validatore nascosto hanno superato i test.
Il parere del recensore: Una copertura più ampia del modello diretto e della soglia, senza alcun vantaggio in termini di punteggio funzionale.
Visualizza l'output completo di Codex
Risultato completo, sanificato e valido
È stata implementata la funzionalità di priorità dei lavori pianificati. File modificati: - [scheduler/models.py](./scheduler/models.py:5) — aggiunto il campo serializzato `priority`, con valore predefinito `0`. - [scheduler/service.py](./scheduler/service.py:11) — aggiunti la convalida, l'archiviazione e il filtro `list_jobs(min_priority=0)`, mantenendo l'ordine degli identificatori. - [tests/test_scheduler.py](./tests/test_scheduler.py:16) — aggiunta la copertura per i valori predefiniti, la serializzazione, l’archiviazione, i limiti, i valori non validi e il filtraggio. Test eseguiti: ```text python3 -m unittest discover -s tests -v Eseguiti 7 test — OK ``` **Conclusione:** Il task congelato è completo e verificato. **Decisione richiesta:** Nessuna.
Visualizza l'output completo del codice Claude
Registro completo del passaggio di consegne, compreso il testo integrale del primo output valido
Registro di esecuzione # T2 — Funzionalità di priorità multi-file Parametri di esecuzione ## | Campo | Valore | | --- | --- | | Attività | `T2` | | Prompt congelato | `01-prompts/T2.md` | | SHA-256 del prompt congelato | `8476a56034c4e719b97ee4081b32b4c73efd45feafe1bda9d477c83cb8fdb698` | | Unità di esecuzione | subagente Claude isolato, `general-purpose`, contesto nuovo | | Metodo di isolamento | **fallback del subagente** (downgrade documentato — vedi `results/isolation-decision.md`) | | Copia pulita assegnata | `runtime/workspaces/T2` | | Versione del codice Claude | `2.1.220` | | Impostazione del modello | `claude-opus-5` | | start_utc | `2026-07-28T10:27:52Z` | | end_utc | `2026-07-28T10:29:33Z` | | Durata | 101 s (in concomitanza con T1, T3, T4; misurazione della latenza non precisa) | | Numero di tentativi | 1 | | Stato | `valido` | | Intervento umano | nessuno | ## Riepilogo degli strumenti sicuri `date`, `Lettura`/`Modifica`/`Scrittura` solo all’interno dell’area di lavoro assegnata, `grep`, `python3 -m unittest discover`, `python3 -m compileall`, controlli di funzionalità inline con `python3 -c`. Nessuna connessione di rete, nessuna installazione, solo libreria standard. ## File modificati `scheduler/models.py`, `scheduler/repository.py`, `scheduler/service.py`, `tests/test_scheduler.py`. Nessun file aggiunto o rimosso, quindi `fixture-manifest.json` rimane corretto. Patch completa: `results/T2/patch.diff`. ## Risultati dei controlli offline Segnalati dal task runner: | Controllo | Risultato | | --- | --- | | `python3 -m unittest discover -s tests -v` (linea di base, prima della modifica) | 2 superati, 0 falliti | | `python3 -m compileall -q scheduler tests` | pulito | | controlli di funzionalità inline (costruzione legacy a 3 argomenti, soglia per parola chiave/posizionale, `to_dict`) | superato | | `python3 -m unittest discover -s tests -v` (finale) | **14 superati, 0 falliti** | Riverificato in modo indipendente dal coordinatore dall’esterno dell’area di lavoro: | Controllo | Uscita | Risultato | | --- | --- | --- | | suite pubblica (`results/checks/T2-public.txt`) | 0 | 14 test, OK | | validatore nascosto `03-checks/test_t2_hidden.py` (`results/checks/T2-hidden.txt`) | 0 | 2 test, OK | Il validatore nascosto fallisce (uscita 1) su una copia incontaminata del fixture, confermando che il superamento del test è significativo. Vedi `results/checks/validator-controls.md`. ## Copertura del comportamento della mappa di riferimento Tutti e cinque i comportamenti richiesti in `03-checks/gold-map.json` sono soddisfatti: | Comportamento richiesto | Prova | | --- | --- | | priorità predefinita 0 | `Job.priority: int = MIN_PRIORITY`; `create_job(..., priority=MIN_PRIORITY)`; `test_priority_defaults_to_zero` | | intervallo di numeri interi da 0 a 9 | `validate_priority` rifiuta valori non interi e fuori intervallo; `test_out_of_range_priority_is_rejected`, `test_non_integer_priority_is_rejected` | | priorità serializzata | `to_dict()` tramite `asdict`; `test_priority_appears_in_serialized_output` verifica la presenza esatta del dizionario | | filtraggio per priorità minima | `list_jobs(min_priority=0)` → `JobRepository.all(min_priority)`; `test_filter_is_inclusive_of_the_threshold` | | ordinamento degli identificatori | filtro applicato all'interno della comprensione esistente `sorted(self._jobs)`; `test_filter_preserves_ascending_identifier_order` | ## Errori corretti Nessuno. Gli artefatti `__pycache__` derivanti dall’esecuzione dei test sono stati rimossi dal task runner; una scansione del coordinatore ha confermato che l’area di lavoro è pulita. ## Output visibile (testuale) Aggiunto un campo intero `priority` ai lavori pianificati nei livelli modello, repository e servizio del fixture dello scheduler locale, oltre all’elenco filtrato. **`scheduler/models.py`** — Aggiunte le costanti del modulo `MIN_PRIORITY = 0` / `MAX_PRIORITY = 9` e una funzione riutilizzabile `validate_priority(priority)` che genera un `ValueError` per i valori non interi e per quelli al di fuori dell’intervallo compreso tra 0 e 9 inclusi. `bool` viene esplicitamente rifiutato nonostante sia una sottoclasse di `int`, quindi `True` non può passare inosservato come priorità 1. La classe di dati congelata `Job` acquisisce `priority: int = MIN_PRIORITY` come campo finale con un valore predefinito, il che mantiene funzionante la costruzione esistente a 3 argomenti, e un `__post_init__` che chiama il validatore in modo che non sia possibile costruire priorità non valide in alcun modo. `to_dict()` è stato lasciato come `asdict(self)`, quindi la priorità appare automaticamente nell’output serializzato e nell’ordine dei campi. **`scheduler/repository.py`** — `JobRepository.all()` accetta un `min_priority` opzionale e filtra all’interno della comprensione esistente `sorted(self._jobs)`, in modo che l’ordine ascendente degli identificatori sia garantito dallo stesso unico percorso di codice che già lo forniva, anziché essere ristabilito dopo il filtraggio. L’argomento predefinito mantiene il precedente comportamento senza argomenti per i chiamanti esistenti. L’archiviazione in sé non ha richiesto alcuna modifica: il repository memorizza intere istanze `Job`, quindi la priorità persiste e viene trasferita attraverso `save`/`get`/`all`. **`scheduler/service.py`** — `create_job` accetta un argomento `priority` opzionale in coda (valore predefinito 0) e lo convalida prima di costruire l’oggetto `Job`, in modo che l’errore venga generato al confine del servizio con lo stesso contratto `ValueError` del controllo esistente sul nome vuoto. `list_jobs(min_priority=0)` delega al repository. L’ordinamento e il filtraggio risiedono in un unico punto anziché essere duplicati. **Nota di progettazione sulla convalida di `min_priority`:** viene verificato come tipo intero ma *non* è deliberatamente limitato all’intervallo 0–9. La regola 0–9 limita ciò che un job può memorizzare; una soglia è un parametro di query e rifiutare, ad esempio, `min_priority=10` trasformerebbe una query legittima "senza corrispondenze" in un errore. Il fatto che `list_jobs(min_priority=9)` restituisca `[]` quando nessun lavoro ha priorità 9 è coperto da un test. `scheduler/time_rules.py` è stato letto ma lasciato invariato: il cambiamento relativo all’ora legale documentato è un comportamento predefinito preesistente, fuori dall’ambito di questo compito, e modificarlo avrebbe comportato un cambiamento di comportamento non pertinente. Non sono stati aggiunti né rimossi file, quindi `fixture-manifest.json` rimane accurato (verificato a livello di codice). ### Copertura di test aggiunta Valore predefinito 0; round-trip di archiviazione tramite `JobRepository`; priorità nell’output di `to_dict()`; valori limite 0 e 9 accettati; valori fuori intervallo −1/10/100 rifiutati; valori non interi `"3"`/`3.5`/`None`/`True` rifiutati; convalida diretta a livello di modello; ordine di elenco non filtrato; elenco filtrato che preserva l’ordine ascendente degli identificatori; soglia inclusiva; risultato vuoto; `min_priority` non intero rifiutato.
Limitazione del test: si trattava di un piccolo repository Python offline. Claude ricorreva a un subagente di riserva dopo la scadenza dell'OAuth via CLI, pertanto l'isolamento e la visibilità dei token non erano identici.
Correzione di bug in casi limite
T3 ha testato un difetto nella programmazione dell'ora legale. Entrambi gli agenti hanno ottenuto un punteggio di 30/30 e hanno superato gli stessi controlli nascosti primaverili e autunnali. Il codice Claude ha aggiunto una copertura esplicita per gli orari locali ambigui e saltati, gli input ingenui e i rollover di più giorni. Codex ha apportato una modifica più circoscritta al giorno di calendario e ha superato il contratto congelato.
Test più ampi sui casi limite infondono fiducia quando la libreria viene ampiamente riutilizzata o quando il costo di un errore di pianificazione è elevato. Una modifica circoscritta è preferibile quando il difetto è ben isolato e il team vuole ridurre al minimo i cambiamenti nel comportamento. La domanda pratica da porsi durante la revisione non è “Chi ha scritto di più?”, bensì se la patch risolva la causa principale indicata, preservi i contratti circostanti e verifichi i limiti a rischio.
T3 · Test del repository controllato
Correggere la programmazione giornaliera in occasione dei passaggi all’ora legale
Mantenere l'ora di New York richiesta durante i cambi di stagione tra primavera e autunno.
Causa principale: l'implementazione ha aggiunto 24 ore UTC trascorse. Soluzione: avanzare di un giorno di calendario locale. Entrambi i controlli "frozen spring" e "fall" sono stati superati.
Il parere del recensore: La minoranza ha approvato il contratto congelato nella sua interezza.
Sono stati trattati: spring, fall, orari locali omessi e ambigui, input ingenui e roll su più giorni. Entrambi i controlli nascosti "frozen" sono stati superati dopo aver ampliato la copertura dei test di regressione.
Il parere del recensore: Copertura più ampia dei casi limite; stesso punteggio funzionale secondo i criteri prestabiliti.
Visualizza l'output completo di Codex
Risultato completo, sanificato e valido
È stata implementata la correzione relativa all'ora legale. File modificati: - [scheduler/time_rules.py](./scheduler/time_rules.py) - [tests/test_time_rules.py](./tests/test_time_rules.py) Modifiche: - Avanzamento di un giorno di calendario locale anziché di 24 ore UTC. - Aggiunti test di regressione per l’avanzamento e il ritorno all’ora solare a New York. - Verificato che gli intervalli UTC trascorsi siano rispettivamente di 23 e 25 ore. Controlli: - Test unitari: 4 superati. - Controllo sintattico in memoria: 7 file Python superati. - La compilazione del bytecode è stata bloccata perché Python reindirizza la propria cache al di fuori dell’area di lavoro assegnata; non sono stati scritti file esterni. **Conclusione:** `next_daily_run` ora mantiene l’ora di orologio richiesta durante i passaggi all’ora legale. Non è richiesta alcuna decisione.
Visualizza l'output completo del codice Claude
Registro completo del passaggio di consegne, compreso il testo integrale del primo output valido
Registro di esecuzione # T3 — Correzione bug DST
Parametri di esecuzione ##
| Campo | Valore |
| --- | --- |
| Attività | `T3` |
| Prompt congelato | `01-prompts/T3.md` |
| SHA-256 del prompt congelato | `3fee50d0230f27f8d6dd7f12e050fa3f0b7f5fb77d9559361fee96e5f1a47307` |
| Unità di esecuzione | subagente Claude isolato, `general-purpose`, contesto nuovo |
| Metodo di isolamento | **fallback del subagente** (downgrade documentato — vedi `results/isolation-decision.md`) |
| Copia pulita assegnata | `runtime/workspaces/T3` |
| Versione del codice Claude | `2.1.220` |
| Impostazione del modello | `claude-opus-5` |
| start_utc | `2026-07-28T10:28:05Z` |
| end_utc | `2026-07-28T10:30:03Z` |
| Durata | 118 s (in concomitanza con T1, T2, T4; non si tratta di una misurazione della latenza pura) |
| Numero di tentativi | 1 |
| Stato | `valido` |
| Intervento umano | nessuno |
## Riepilogo dello strumento di sicurezza
`date`, `Lettura`/`Modifica` solo all’interno dell’area di lavoro assegnata, `python3 -m unittest discover`,
`python3 -m compileall`, un’esecuzione di controllo negativo in memoria, un controllo di integrità del manifesto.
Solo libreria standard (`datetime`, `zoneinfo`, `unittest`). Nessuna connessione di rete, nessuna installazione.
## File modificati
`scheduler/time_rules.py` (la correzione — solo il corpo e la stringa di documentazione di `next_daily_run`),
`tests/test_scheduler.py` (aggiunto `NextDailyRunTests`, 8 test, più un helper `_elapsed`;
i test esistenti non sono stati modificati). Nessun altro modulo è stato modificato, nessun file è stato aggiunto. Patch completa:
`results/T3/patch.diff`.
## Risultati del controllo offline
Segnalati dal task runner:
| Controllo | Risultato |
| --- | --- |
| `python3 -m unittest discover -s tests -v` | **10 superati, 0 falliti** (2 preesistenti + 8 nuovi) |
| `python3 -m compileall -q scheduler tests` | pulito |
| integrità del manifesto rispetto a `fixture-manifest.json` | 0 mancanti, 0 inattesi |
| controllo negativo: implementazione seed patchata in memoria, solo `NextDailyRunTests` | 8 eseguiti, **5 falliti come previsto**, inclusi entrambi i test DST |
Riverificato in modo indipendente dal coordinatore dall’esterno dell’area di lavoro:
| Controllo | Uscita | Risultato |
| --- | --- | --- |
| suite pubblica (`results/checks/T3-public.txt`) | 0 | 10 test, OK |
| validatore nascosto `03-checks/test_t3_hidden.py` (`results/checks/T3-hidden.txt`) | 0 | 2 test, OK |
Il validatore nascosto fallisce (uscita 1) su una copia incontaminata del fixture. Vedi
`results/checks/validator-controls.md`.
## Copertura del comportamento della mappa di riferimento
Tutti e quattro i comportamenti richiesti in `03-checks/gold-map.json` sono soddisfatti:
| Comportamento richiesto | Prova |
| --- | --- |
| ora dell’orologio da parete preservata | incremento applicato all’orologio da parete locale ingenuo, zona riassociata; verificato in ogni test DST |
| Transizione primaverile coperta | `test_spring_forward_keeps_requested_hour` — ora 09:30 mantenuta, offset `-04:00`, tempo trascorso 23 h |
| Transizione autunnale coperta | `test_fall_back_keeps_requested_hour` — ora 09:30 mantenuta, offset `-05:00`, tempo trascorso 25 h |
| Fuso orario IANA utilizzato | `ZoneInfo("America/New_York")` dalla libreria standard |
Oltre all’insieme richiesto, il runner ha coperto anche i due casi limite della PEP 495 — un tempo reale
saltato dall’avanzamento primaverile e un tempo reale ambiguo durante il ritorno all’ora solare — oltre ai rollover di sette giorni
a cavallo di ciascuna transizione e al comportamento con input ingenuo.
## Errori corretti
Due fallimenti di asserzione nei test causati dall’autore stesso: `following - previous` su due date-ora che condividono un
`tzinfo` sottrae gli orologi reali ingenui, quindi le asserzioni sul tempo trascorso indicavano 1 giorno e fallivano.
L’implementazione era corretta e le asserzioni erano errate; corretto con un helper `_elapsed`
che converte prima entrambi gli operandi in UTC. Nessun errore di strumenti, importazioni o ambiente.
Gli artefatti `__pycache__` sono stati rimossi dopo l’esecuzione.
## Output visibile (testuale)
**Riproduzione**
`scheduler/time_rules.py::next_daily_run` è stato chiamato con una data e ora `America/New_York` su entrambi i lati di una transizione all’ora legale del 2024:
```
2024-03-09T09:30:00-05:00 -> 2024-03-10T10:30:00-04:00 # l'ora ha subito uno scostamento di +1
2024-11-02T09:30:00-04:00 -> 2024-11-03T08:30:00-05:00 #: lo scostamento orario è stato di -1
```
Un lavoro richiesto per le 09:30 ora locale è stato avviato alle 10:30 dopo l'ora legale e alle 08:30 dopo il ritorno all'ora solare.
**Causa principale**
L'implementazione iniziale considerava "daily" come una durata assoluta fissa:
```python
elapsed = previous_run.astimezone(timezone.utc) + timedelta(hours=24)
return elapsed.astimezone(previous_run.tzinfo)
```
La conversione iniziale in UTC fa sì che `timedelta(hours=24)` corrisponda esattamente a 24 ore trascorse. Tuttavia, un giorno di calendario locale in un fuso orario IANA dura 23 ore nel giorno dell’ora legale e 25 ore nel giorno del ritorno all’ora solare, quindi un offset costante di 24 ore porta inevitabilmente a un’ora di scarto rispetto all’ora dell’orologio locale richiesta.
**La correzione** (`scheduler/time_rules.py`)
La ricorrenza giornaliera è una regola di calendario, quindi l’incremento viene ora applicato all’orologio locale «naïve», con il fuso orario riassociato in seguito:
```python
tzinfo = previous_run.tzinfo
naive_next = previous_run.replace(tzinfo=None) + timedelta(days=1)
if tzinfo is None:
return naive_next
candidate = naive_next.replace(tzinfo=tzinfo, fold=0)
return candidate.astimezone(timezone.utc).astimezone(tzinfo)
```
Perché è corretto:
- L'aritmetica dell'orologio locale sul valore "naive" è indipendente dall'offset, quindi l'ora e i minuti richiesti vengono preservati per definizione; `zoneinfo` fornisce quindi l’offset UTC in vigore alla nuova data (verificato: `-04:00` dopo l’avanzamento dell’ora in primavera, `-05:00` dopo il ritorno all’ora solare, con tempo reale trascorso rispettivamente di 23 h e 25 h).
- `fold=0` più il round-trip UTC gestisce i due casi limite che l’aritmetica pura dell’orologio da parete lascia indefiniti. Secondo la PEP 495, un’ora da parete *saltata* (02:30 del 10/03/2024) presenta l’offset pre-transizione a `fold=0`, quindi il round-trip lo normalizza all’istante reale 03:30 EDT anziché restituire una data e ora che non indica alcun istante. Un tempo reale *ambiguo* (01:30 del 3 novembre 2024) viene risolto in modo deterministico alla sua prima occorrenza (EDT) invece di risultare arbitrario.
- L’input «naïve» mantiene il suo significato precedente (semplicemente +1 giorno di calendario) — non viene imposto alcun nuovo requisito `tzinfo` ai chiamanti.
L’ambito è stato mantenuto ristretto: sono stati modificati solo il corpo e la stringa di documentazione di `next_daily_run`. `service.py`, `models.py`, `repository.py` e `__init__.py` sono rimasti invariati, non sono stati aggiunti nuovi file e il manifesto dei fixture corrisponde ancora esattamente (nessun file mancante o inaspettato). Solo libreria standard (`datetime`, `zoneinfo`, `unittest`).
**Test di regressione** (`tests/test_scheduler.py`, nuovo `NextDailyRunTests`, 8 test) coprono: stabilità nei giorni normali, ora di passaggio all’ora legale + offset + 23 ore trascorse, ora di ritorno all’ora solare + offset + 25 ore trascorse, cicli di sette giorni a cavallo di ciascuna transizione, tempo reale saltato, tempo reale ambiguo e input ingenuo.
Due note degne di nota. Innanzitutto, le mie asserzioni iniziali sul tempo trascorso utilizzavano `following - previous`; Python ignora un `tzinfo` condiviso e sottrae gli orologi da parete ingenui, quindi entrambe restituivano 1 giorno e fallivano. L’implementazione era corretta e le asserzioni errate — risolto con un helper `_elapsed` che converte entrambi gli operandi in UTC. In secondo luogo, ho verificato che i test individuassero effettivamente il difetto originale rieseguendo `NextDailyRunTests` su una copia in memoria dell’implementazione con i valori iniziali: 5 su 8 hanno dato esito negativo, inclusi entrambi i test relativi all’ora legale. I tre che superano il test nella versione difettosa (giorno normale, saltato, ambiguo) documentano il comportamento piuttosto che rilevare una regressione: i casi saltati/ambigui coincidono per caso perché uno spostamento assoluto di +24 ore capita proprio di cadere sullo stesso istante normalizzato.
Limitazione del test: si trattava di un piccolo repository Python offline. Claude ricorreva a un subagente di riserva dopo la scadenza dell'OAuth via CLI, pertanto l'isolamento e la visibilità dei token non erano identici.
Qualità della revisione del codice e verifica umana
Le attività di revisione del codice richiedono competenze diverse rispetto all'implementazione delle funzionalità. Un revisore efficace deve individuare problemi riproducibili, valutarne l'impatto, indicare il percorso esatto del codice e distinguere un vero difetto da un avviso puramente ipotetico. La correzione di un problema comporta un ulteriore test: la patch non deve introdurre una nuova regressione.
Il codice Claude ha mostrato il vantaggio più evidente nel T4. Ha segnalato cinque risultati riproducibili in modo indipendente, inclusi entrambi gli obiettivi di revisione prestabiliti, ottenendo un punteggio di 19/20. Codex ha segnalato e risolto due difetti validi di gravità maggiore, ma non ha menzionato la coppia prestabilita, ottenendo un punteggio di 18/20. I risultati di Codex non erano falsi positivi; la differenza osservata riguardava l’ampiezza piuttosto che la correttezza di base.
T4 · Test del repository controllato
Individua i difetti riproducibili e risolvi i problemi con il più alto grado di affidabilità
Esaminare il codice, riprodurre i difetti reali, applicare le correzioni consentite e dimostrare che i test di regressione verificano il comportamento.
1. Elevato — I lavori esistenti potrebbero essere sovrascritti senza preavviso. 2. Medio — Le esecuzioni giornaliere hanno subito scostamenti in occasione dei passaggi all’ora legale. Verifica: quattro test superati, zero errori.
Il parere del recensore: Risultati utili relativi a problemi di maggiore gravità e correzioni mirate, ma non sono stati raggiunti i due obiettivi di revisione prefissati.
D1 Deriva DST · Alta D2 Acquisizione ingenua del fuso orario · Media D3 Collisione di identificatori · Alta D4 L'assenza di cancellazione genera un KeyError · Media D5 Proprietario non convalidato · Bassa
Il parere del recensore: Copertura di revisione più ampia senza falsi positivi riprodotti; due risultati dipendenti dal contratto non sono stati corretti.
Visualizza l'output completo di Codex
Risultato completo, sanificato e valido
## Risultati che richiedono un intervento 1. **Alto — I lavori esistenti potrebbero essere sovrascritti in modo silenzioso** - Prova: inizializzazione dell'identificatore in [service.py](./scheduler/service.py:8), combinata con la sostituzione del dizionario in [repository.py](./scheduler/repository.py:9). - Impatto: la creazione di un servizio con un repository esistente potrebbe riutilizzare l’identificatore `1`, sostituendo il lavoro memorizzato e causando la perdita di dati. - Riproduzione minima: salvare `Job(1, ...)`, costruire `SchedulerService(repository)`, quindi creare un altro lavoro. Prima della correzione, rimaneva solo il nuovo lavoro. - Correzione: inizializzare l’identificatore successivo a partire dall’identificatore esistente più alto del repository. - Test di regressione: [test_scheduler.py](./tests/test_scheduler.py:22). 2. **Medio — Le esecuzioni giornaliere subivano scostamenti in occasione dei passaggi all’ora legale** - Prova: calcolo corretto in [time_rules.py](./scheduler/time_rules.py:4). - Impatto: un processo giornaliero pianificato per le 09:00 veniva eseguito alle 10:00 dopo il passaggio all’ora legale in primavera. - Riproduzione minima: calcolare l’esecuzione successiva dopo `2026-03-07 09:00 America/New_York`. Prima della correzione, il risultato era `2026-03-08 10:00`. - Correzione: aggiungere un giorno di calendario locale invece di 24 ore UTC trascorse. - Test di regressione: [test_scheduler.py](./tests/test_scheduler.py:33). ## File modificati - [scheduler/service.py](./scheduler/service.py) - [scheduler/time_rules.py](./scheduler/time_rules.py) - [tests/test_scheduler.py](./tests/test_scheduler.py) ## Verifica - Entrambi i test di regressione sono risultati falliti prima delle rispettive correzioni. - Ciascuno è stato superato dopo la correzione corrispondente. - `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -v` - Risultato: **4 test superati, 0 falliti**. - Non sono rimasti artefatti della cache Python generati. ## Conclusione e decisione - **Conclusione:** Entrambi i difetti confermati sono stati corretti e sono coperti da test di regressione mirati. - **Decisione richiesta:** Nessuna.
Visualizza l'output completo del codice Claude
Registro completo del passaggio di consegne, compreso il testo integrale del primo output valido
# T4 Registro di esecuzione — Test e revisione del codice
## Parametri di esecuzione
| Campo | Valore |
| --- | --- |
| Attività | `T4` |
| Prompt congelato | `01-prompts/T4.md` |
| SHA-256 del prompt congelato | `5e69546007ea776f40b3d334ddb75671ff684c151c77551bad27de3b0fdce640` |
| Unità di esecuzione | subagente Claude isolato, `general-purpose`, contesto nuovo |
| Metodo di isolamento | **fallback del subagente** (downgrade documentato — vedi `results/isolation-decision.md`) |
| Copia pulita assegnata | `runtime/workspaces/T4` |
| Versione del codice Claude | `2.1.220` |
| Impostazione del modello | `claude-opus-5` |
| start_utc | `2026-07-28T10:28:22Z` |
| end_utc | `2026-07-28T10:32:17Z` |
| Durata | 235 s (in concomitanza con T1–T3; non è una misurazione di latenza pulita) |
| Numero di tentativi | 1 |
| Stato | `valido` |
| Intervento umano | nessuno |
La condizione presente nel prompt congelato — "correggili se la configurazione di esecuzione congelata consente
le correzioni" — è stata risolta dal coordinatore tramite `00-control/run-config.json` e
`00-control/safety-policy.json`, che consentono la scrittura di copie isolate dei fixture. Al runner è stato
comunicato che le correzioni sono consentite. Non gli è stato mostrato alcun file di controllo.
## Riepilogo degli strumenti sicuri
`date`, `Lettura`/`Modifica`/`Scrittura` solo all’interno dell’area di lavoro assegnata, `grep`,
`python3 -m unittest discover`, `python3 -m compileall`, un’esecuzione di vacuity con copia temporanea, un
controllo di presenza del manifesto. Nessuna rete, nessuna installazione, solo libreria standard.
## File modificati
`scheduler/time_rules.py` (modificato), `scheduler/service.py` (modificato),
`tests/test_scheduler.py` (modificato, +2 test), `tests/test_time_rules.py` (aggiunto, 5 test).
Patch completa: `results/T4/patch.diff`.
## Risultati del controllo offline
Segnalato dal task runner:
| Controllo | Risultato |
| --- | --- |
| `python3 -m unittest discover -s tests -v` | **9 superati, 0 falliti, 0 saltati** (baseline 2) |
| `python3 -m compileall -q scheduler tests` | superato |
| Controllo della presenza del manifesto rispetto a `expected_files` | tutti e 8 presenti |
| Esecuzione di vacuity sulle implementazioni originali ripristinate | 5 fallimenti, 4 superati, come previsto |
Riverificato in modo indipendente dal coordinatore dall’esterno dell’area di lavoro:
| Controllo | Uscita | Risultato |
| --- | --- | --- |
| suite pubblica (`results/checks/T4-public.txt`) | 0 | 9 test, OK |
Controllo incrociato informativo, non valutato: anche il validatore nascosto T3 supera il test su questo
spazio di lavoro (uscita 0), poiché T4 ha risolto in modo indipendente lo stesso difetto `next_daily_run`. Vedi
`results/checks/validator-controls.md`.
## Copertura dei difetti nella mappa di riferimento
`03-checks/gold-map.json` inserisce due difetti per la valutazione di T4. Entrambi sono stati rilevati:
| Difetto inserito | Rilevato | Segnalato come |
| --- | --- | --- |
| proprietario vuoto accettato | sì | **D5**, `scheduler/service.py:11,13`, gravità Bassa, segnalato e deliberatamente non risolto |
| L’eliminazione di un identificatore mancante genera un `KeyError` | sì | **D4**, `scheduler/repository.py:19` → `service.py:22`, gravità Media, segnalato e deliberatamente non risolto |
Sono stati segnalati altri tre difetti oltre a quelli inseriti. Nessuno di essi è un falso positivo:
- **D1** — Scostamento dell’ora legale in `next_daily_run`. Si tratta del terzo difetto elencato in
`03-checks/seeded-defects.md` (è classificato sotto T3, non T4, ma è un vero e proprio bug prestabilito).
- **D2** — Un input ingenuo in `next_daily_run` acquisisce silenziosamente il fuso orario dell’host e restituisce una
data e ora consapevoli. Reale e dipendente dall’host; verificato dal coordinatore rispetto al codice sorgente del fixture.
- **D3** — Collisione di identificatori tra un servizio e un repository iniettato o condiviso, che causa una
sovrascrittura silenziosa. Reale: `SchedulerService._next_identifier` parte sempre da 1 mentre
`JobRepository.save` è un'assegnazione a un dizionario non protetta. T1 ha identificato in modo indipendente la stessa
discrepanza dal fixture originale.
Numero di falsi positivi: **0**. Il runner ha inoltre correttamente segnalato l’assenza di problemi di sicurezza, osservando che
il fixture non presenta vulnerabilità relative a rete, I/O, deserializzazione, sottoprocessi o credenziali.
## Scostamento degno di nota
Il prompt congelato richiedeva test e correzioni sui "due difetti con il più alto livello di affidabilità". Il
runner ha selezionato D1/D2 (una correzione, stessa funzione) e D3, anziché i due difetti inseriti nella mappa di riferimento
D4 e D5. La motivazione addotta è difendibile: sia D4 che D5 dipendono da un contratto API non specificato
, quindi correggerli sarebbe un tentativo alla cieca. Il punteggio relativo al rilevamento non è influenzato: entrambi i difetti prestabiliti
sono stati individuati, con indicazione di file, riga, gravità, impatto e riproducibilità. Le correzioni applicate riguardavano difetti reali
e sono supportate da un controllo di vacuità.
## Errori sanificati
Due fallimenti di test autoindotti dovuti alla sottrazione tra tempo reale e tempo assoluto su date e ore
che condividono un `tzinfo`; corretti e verificati nuovamente. Nessun errore di strumenti o ambiente. Gli artefatti `__pycache__`
sono stati rimossi dopo l’esecuzione.
## Output visibile (testuale)
### Segnalazione di difetto
**D1 — `scheduler/time_rules.py:10-11` — La pianificazione giornaliera subisce uno scostamento di un'ora durante l'ora legale — Gravità: Alta**
`next_daily_run` aggiunge 24 ore *trascorse* tramite un round-trip UTC invece di far avanzare il giorno di calendario. Un processo giornaliero è definito dall’ora reale, quindi ogni processo in un fuso orario che osserva l’ora legale viene eseguito silenziosamente con un’ora di anticipo o di ritardo a partire dal giorno di transizione, e l’errore persiste (ogni esecuzione riparte dall’ora spostata). La stessa stringa di documentazione ammetteva tale comportamento.
```
prev = datetime(2024, 3, 9, 9, 0, tzinfo=ZoneInfo("America/New_York"))
next_daily_run(prev) # -> 2024-03-10 10:00:00-04:00, previsto 09:00-04:00
prev = datetime(2024, 11, 2, 9, 0, tzinfo=ZoneInfo("America/New_York"))
next_daily_run(prev) # -> 3 novembre 2024 08:00:00-05:00, previsto 09:00-05:00
```
**D2 — `scheduler/time_rules.py:10-11` — Un input ingenuo acquisisce silenziosamente il fuso orario locale del computer — Gravità: Media**
Le stesse due righe. `.astimezone(timezone.utc)` su un oggetto datetime 'naive' presuppone l'ora locale del sistema, mentre `.astimezone(None)` restituisce un oggetto datetime "aware". Una chiamata con input ingenuo restituisce un output consapevole, quindi il risultato non è comparabile con gli altri valori ingenui del chiamante (`TypeError` al confronto) e la risposta dipende dal `TZ` dell’host.
```
next_daily_run(datetime(2024, 1, 1, 9, 0))
# -> datetime(2024, 1, 2, 9, 0, tzinfo=timezone(timedelta(hours=8), "CST")) # dipendente dall'host
```
**D3 — `scheduler/service.py:8,13,15` (prefisso) — La collisione degli identificatori distrugge silenziosamente i lavori memorizzati — Gravità: Alta**
Il contatore degli ID era specifico per ogni `SchedulerService` e partiva sempre da 1, ignorando il contenuto del repository inserito. Qualsiasi secondo servizio su un repository condiviso, o qualsiasi servizio su un repository precompilato, riassegnava l’ID 1; `JobRepository.save` è un’assegnazione a un dizionario, quindi il lavoro esistente veniva sovrascritto senza generare alcun errore. Perdita di dati.
```
repo = JobRepository()
SchedulerService(repo).create_job("Backup notturno", "Alex") # id 1
SchedulerService(repo).create_job('Esportazione buste paga', 'Blake') # di nuovo id 1
repo.all() # -> [Job(1, "Esportazione buste paga", "Blake")] — Il lavoro di Alex è sparito
```
**D4 — `scheduler/repository.py:19` → `scheduler/service.py:22` — `delete_job` genera un `KeyError` per un id sconosciuto — Gravità: Media**
`delete` utilizza `dict.pop` senza un valore predefinito, mentre il metodo correlato `get` (riga 13) restituisce `None` in caso di mancata corrispondenza. L'incoerenza genera un `KeyError` non gestita tramite `SchedulerService.delete_job`, che difficilmente verrà intercettato da chi chiama la funzione. Riproduzione: `SchedulerService().delete_job(999)` → `KeyError: 999`. La correzione potrebbe essere `pop(identifier, None)` o un'eccezione di dominio esplicita — lasciata deliberatamente non corretta, poiché il contratto corretto (operazione silenziosa vs. errore tipizzato) è una decisione relativa all’API che spetta al proprietario.
**D5 — `scheduler/service.py:11,13` — Il campo `owner` non viene convalidato — Gravità: Bassa**
`name` viene controllato per verificare che non sia vuoto, ma `owner` no: `create_job('ok', ' ')` memorizza `owner=''`. Entrambi i parametri chiamano inoltre `.strip()` senza protezione, quindi `None` viene segnalato come `AttributeError: l'oggetto 'NoneType' non ha l'attributo 'strip'` anziché come `ValueError`, che l'API utilizza altrimenti per input non validi. Lasciato non risolto — il contratto previsto per `owner` non è specificato in nessuna parte del fixture.
**Sicurezza:** nessun risultato. Il fixture non presenta vulnerabilità relative a rete, I/O, deserializzazione, sottoprocessi o credenziali; l’archiviazione avviene tramite un dizionario interno al processo.
**Lacuna di copertura:** `scheduler/time_rules.py` e `scheduler/repository.py` presentavano una copertura di test pari a zero prima di questa esecuzione; i due test iniziali hanno verificato solo il percorso normale del servizio.
### Test e correzioni applicate
I due difetti con il più alto livello di confidenza erano **D1/D2** (stessa funzione, un'unica correzione) e **D3**.
**Correzione 1 — `scheduler/time_rules.py`:** sostituito il round-trip UTC con `previous_run + timedelta(days=1)`. Python esegue operazioni aritmetiche basate sul tempo reale su date e ore consapevoli, e `zoneinfo` ricalcola l’offset UTC in modo pigro a partire dal nuovo tempo reale — quindi le 09:00 rimangono le 09:00 mentre l’offset si sposta correttamente da `-05:00` a `-04:00`. Questo risolve contemporaneamente D1 e D2: gli input "naïve" ora rimangono tali e il fuso orario locale non viene mai dedotto. Il caso di transizione tra ora irraggiungibile e ora ambigua è documentato come soggetto alle regole di raggruppamento di `tzinfo`.
**Correzione 2 — `scheduler/service.py`:** rimosso il contatore `_next_identifier` per istanza; gli identificatori vengono ora assegnati dallo stato del repository come `max(ID esistenti, default=0) + 1` al momento della creazione. Ciò è corretto sia per i repository condivisi che per quelli precompilati. Compromesso: O(n) per ogni creazione invece di O(1), accettabile per un archivio in memoria basato su dizionario, e correttezza rispetto a un contatore che non può vedere l’archivio in cui scrive.
**Test — `tests/test_time_rules.py` (nuovo, 5 test):** conservazione dell’ora reale durante il passaggio all’ora legale e al ritorno all’ora solare, tempo trascorso assoluto di 23h/25h durante tali transizioni, ricalcolo dell’offset UTC, “naive-stays-naive” e un semplice avanzamento di un giorno in UTC. Salta correttamente se non è presente il database IANA.
**Test — `tests/test_scheduler.py` (ampliati, +2 test):** due servizi che condividono un unico repository devono emettere ID distinti e conservare entrambi i lavori; un servizio su un repository precompilato con gli ID 1 e 7 deve emettere l’ID 8 e lasciare intatti i lavori esistenti.
**Verifica di vacuità:** ho ripristinato entrambe le implementazioni originali in una copia temporanea e ho rieseguito la suite di test — tutti e 5 i nuovi test hanno dato esito negativo (`FAILED (failures=5)`), mentre tutti superano il codice corretto. I test individuano effettivamente i difetti.
Una correzione durante l’esecuzione: la mia prima bozza verificava il tempo DST trascorso come `result - previous`, che Python valuta come aritmetica dell’orologio reale quando entrambi gli operandi condividono un tzinfo, quindi leggeva `24h` e i test fallivano. Le verifiche ora convertono in UTC prima di sottrarre. L’errore era nel mio test, non nella correzione.
### Note per il responsabile
`fixture-manifest.json` è rimasto invariato, quindi `tests/test_time_rules.py` è un nuovo file legittimo non elencato in `expected_files` — aggiornare il manifesto se un controllo impone un insieme esatto di file. Inoltre, D4 e D5 sono stati segnalati ma non corretti di proposito: entrambi dipendono da una decisione relativa al contratto API (semantica «miss-on-delete», regole di convalida del proprietario) che non è specificata in nessuna parte del fixture, quindi sceglierne uno sarebbe stata una supposizione piuttosto che una correzione.
Limitazione del test: si trattava di un piccolo repository Python offline. Claude ricorreva a un subagente di riserva dopo la scadenza dell'OAuth via CLI, pertanto l'isolamento e la visibilità dei token non erano identici.
Nessuno dei due risultati elimina la necessità di una verifica manuale. Una volta che uno dei due agenti ha completato una riparazione, è necessario ispezionare le interfacce modificate, l’ambito dei file inatteso, l’eventuale mancanza di test negativi, i permessi o la cronologia dei comandi e il percorso di rollback. Una spiegazione convincente non può sostituire un test riproducibile.
Autorizzazioni, sandboxing e sicurezza operativa
Un agente di codifica è in grado di leggere codice privato, eseguire comandi della shell, modificare numerosi file e richiamare strumenti esterni. Ciò rende la progettazione dei permessi un elemento fondamentale della qualità del prodotto. Le domande rilevanti sono: quali operazioni richiedono l’approvazione, a cosa può accedere l’agente per impostazione predefinita, con quale chiarezza segnala in anticipo le azioni rischiose e se uno sviluppatore può verificare le modifiche risultanti.
Non considerare automaticamente come un vantaggio un numero inferiore di richieste di approvazione. Un basso livello di attrito è utile in un ambiente isolato, privo di credenziali o collegamenti alla produzione. Lo stesso comportamento può rivelarsi pericoloso in un repository collegato a script di distribuzione, dati reali dei clienti o autorizzazioni cloud di ampia portata. Al contrario, un numero eccessivo di approvazioni può rendere impraticabile un’automazione sicura e indurre gli utenti ad approvare le richieste senza leggerle.
Il nostro test ha utilizzato copie locali fresche, senza sistemi di produzione, senza implementazione e senza alcun intervento umano durante l’esecuzione. Valuta quindi il completamento delle attività in condizioni di sicurezza, non la sicurezza relativa dei due prodotti. Prima di utilizzare uno dei due strumenti per attività importanti, iniziate con un accesso in sola lettura, definite le directory e i comandi consentiti, esaminate le differenze e eseguite controlli oggettivi in un ambiente ripristinabile.
- Inizia con un'architettura in sola lettura oppure opta per un approccio prudente.
- Approva solo i comandi di cui comprendi l'ambito e le conseguenze.
- Conservare le credenziali, i dati di produzione e gli accessi per l'implementazione al di fuori dell'ambiente di prova.
- Prima di accettare il risultato, richiedere un diff, dei test e un percorso di rollback ben definito.
MCP, competenze, istruzioni di progetto e personalizzazione
Entrambi gli ecosistemi possono essere estesi, ma i termini relativi all’estensione non devono essere considerati sinonimi. Le istruzioni di progetto indicano a un agente come comportarsi all’interno di un repository. Le Skills riutilizzabili racchiudono un flusso di lavoro ripetibile o una competenza specifica. MCP collega un host a strumenti o dati esterni. Gli hook e i comandi possono automatizzare momenti specifici all’interno di un ciclo di sviluppo. Un prodotto può eccellere in un livello senza necessariamente eguagliare una per una le funzionalità di un altro.
La questione fondamentale non è se esista o meno un logo di integrazione, bensì se la connessione possa essere configurata, autenticata, approvata e utilizzata nell’host che si utilizza effettivamente. È inoltre necessario che la modalità di errore sia comprensibile. Un server MCP che funziona in modo interattivo ma attende l’approvazione in una sessione non presidiata è comunque utile, ma non dovrebbe essere descritto come un’automazione senza attrito.
Le istruzioni riutilizzabili presentano una limitazione simile. I file di istruzioni troppo lunghi non garantiscono il rispetto delle regole, mentre un insieme di regole eccessivamente complicato può distogliere l’attenzione dal contesto o creare contraddizioni. Le linee guida del repository devono essere concise, verificabili e strettamente legate al codice. È necessario specificare i comandi di verifica obbligatori, le aree protette, le regole di stile e i casi in cui l’agente deve interrompersi per chiedere conferma.
- Istruzioni per il progetto: regole specifiche del repository e comandi di verifica.
- Competenze: procedure riutilizzabili o pacchetti di competenze.
- MCP: collegamenti a strumenti e dati esterni.
- Ganci e comandi: automazione basata su eventi definiti del flusso di lavoro.
Codex vs Claude: prezzi e limiti di utilizzo
Il confronto tra le tariffe "Clean" parte da $20 al mese. L'accesso a Codex è incluso nel piano $20 ChatGPT corrispondente, mentre il piano Claude Pro costa $20 al mese negli Stati Uniti e include Claude Code. Entrambe le offerte prevedono livelli di consumo più elevati a $100 e $200. Prezzi di listino simili non significano capacità identiche.
Il piano Max 5x da Claude costa $100 al mese, mentre il piano Max 20x da Claude costa $200 al mese. I nomi “5x” e “20x” descrivono l’utilizzo per sessione rispetto alla versione Pro, piuttosto che un numero garantito di attività di codifica. Claude e Claude Code condividono i limiti di sessione e settimanali. La lunghezza del contesto, i file allegati, la scelta del modello e l’uso delle funzionalità possono influire sulla velocità con cui viene esaurita la quota a disposizione.

I crediti di utilizzo opzionali di Claude consentono, una volta attivati, di proseguire le attività idonee al superamento del limite di utilizzo incluso, e tali crediti vengono fatturati separatamente alle tariffe standard dell’API. L’autenticazione tramite chiave API costituisce un’altra modalità di fatturazione distinta. Definire una qualsiasi di queste modalità come “illimitata” nasconderebbe il costo marginale effettivo.

Codex distingue inoltre tra l'utilizzo incluso nel piano consumer, i crediti acquistati idonei e la fatturazione API. I messaggi locali e le chat su cloud condividono una finestra temporale di cinque ore e potrebbero essere applicati anche limiti settimanali. Un campo token in un log CLI non può essere convertito direttamente in una percentuale relativa alle cinque ore, in un importo di credito dell'abbonamento o in una fattura API.
Per attività di programmazione in solitaria occasionali, il livello $20 su entrambi i fronti rappresenta un punto di partenza ragionevole. Il lavoro quotidiano sui repository con contesti estesi può giustificare un livello di utilizzo più elevato, ma solo dopo aver osservato i reset effettivi e il consumo delle attività. Il lavoro parallelo intensivo richiede ancora maggiore attenzione: pagare per un livello più ampio non elimina la necessità di controllare il contesto, suddividere le attività e riservare il ragionamento più dispendioso per il lavoro che richiede un elevato livello di giudizio.
Cosa è emerso dal nostro test comparativo tra Codex e Claude
Prima che entrambi gli agenti iniziassero a funzionare, abbiamo bloccato quattro prompt in inglese, un fixture Python pubblico, i controlli oggettivi, una griglia di valutazione e la regola del “primo risultato valido”. Le attività riguardavano la comprensione di un repository sconosciuto, una funzionalità multi-file, la correzione di un bug nel DST e la revisione del codice con correzioni. I risultati validi non hanno richiesto alcun intervento umano, mentre gli output deboli ma validi non potevano essere rieseguiti per ottenere un punteggio migliore.
Codex ha eseguito processi CLI isolati con JSONL grezzo, mantenendo i campi dei token generati dalla CLI. La sessione OAuth della CLI Claude del collega era scaduta, quindi Claude Code ha utilizzato un coordinatore con contesti di subagente aggiornati. Abbiamo ricostruito le patch di Claude in copie di audit pulite e abbiamo rieseguito i controlli pubblici e nascosti. Ciò ha prodotto prove pratiche credibili, ma non ha garantito un isolamento identico né superfici di controllo del modello identiche.
| Compito | Codice | Codice Claude | Interpretazione limitata |
|---|---|---|---|
| T1: comprensione del repository | 20/20 | 20/20 | Pareggio: approccio compatto contro approccio esaustivo |
| T2: funzione multi-file | 30/30 | 30/30 | Collegamento funzionale; validazione e ambito di test diversi |
| T3: Riparazione del DST | 30/30 | 30/30 | Entrambe hanno superato il test: copertura più ristretta rispetto a quella più ampia dei bordi |
| T4: revisione e riparazione | 18/20 | 19/20 | Il codice Claude ha mostrato una maggiore ampiezza di revisione |
Test controllato · Griglia di valutazione "Frozen"
Codex 98/100 contro Claude Code 99/100
Il divario di un punto non è un segnale universale di successo. Le differenze significative dipendono dal compito specifico.
| Area decisionale | Risultato osservato | Lettura pratica |
|---|---|---|
| Comprensione del repository | Pareggio · 20/20 ciascuno | Claude era più esaustivo; Codex era più conciso. |
| Funzionalità multi-file | Pareggio · 30/30 ciascuno | Entrambi hanno superato i controlli nascosti; Claude ha aggiunto test più approfonditi. |
| Correzione del bug relativo all'ora legale | Pareggio · 30/30 ciascuno | Claude copriva più bordi; Codex ha utilizzato la patch più stretta. |
| Verifica e riparazione | Claude 19/20; Codex 18/20 | Claude ha individuato difetti più riproducibili. |
| Velocità rilevata | Misto | Claude ha guidato T1/T2; Codex ha guidato T3/T4. |
Informativa: stessi prompt e stessa configurazione, ma percorsi di isolamento diversi. Non generalizzare questo piccolo test a ogni repository, livello di modello o sessione autonoma.
Il test è troppo limitato per valutare le prestazioni su repository di grandi dimensioni, su ogni linguaggio di programmazione, su ogni livello di modello o su sessioni autonome di lunga durata. Il divario totale di un punto va interpretato come “entrambi hanno avuto esito positivo, con una differenza nell’ampiezza della revisione”, non come una classifica universale.
Cosa dicono gli utenti reali — e quanto ci si può fidare
Il feedback della comunità è prezioso quando include un progetto, un’attività, un modello, il contesto in cui si svolge l’iniziativa e l’orizzonte temporale. Risulta invece poco significativo quando un post si limita a segnalare che un determinato prodotto “sembra più intelligente” o “è molto più veloce”. Utenti diversi mettono a confronto repository, livelli di abbonamento, prompt, estensioni e livelli di supervisione diversi.
L'esempio contestuale tratto da Reddit riportato sopra suggerisce un compromesso in termini di interazione: un approccio veloce e colloquiale può richiedere maggiore attenzione, mentre un'esecuzione ponderata può sembrare più lenta ma richiedere meno correzioni. Il nostro test controllato si sovrappone solo in parte a quell’account. Ha rilevato velocità variabili e nessun intervento umano nelle esecuzioni valide, quindi non può confermare l’affermazione relativa al «babysitting». Questo è esattamente il motivo per cui le prove provenienti dalla comunità e quelle ottenute tramite test controllati dovrebbero essere presentate insieme senza fonderle.
Il commento sull’imbracatura X solleva un secondo punto utile: il risultato di una codifica appartiene all’intero sistema, non solo all’etichetta del modello. Nessuno dei due post dovrebbe essere considerato come dato di indagine. Usali per individuare le domande da porre nella tua sperimentazione: numero di interventi, entità della differenza, qualità del test e capacità di recupero da un presupposto errato.
Estensione del Codex e del codice Claude con GlobalGPT
GlobalGPT è un spazio di lavoro multimodello e multimodale, non sostituisce gli agenti nativi del repository. Il suo ruolo pratico è quello di ampliare le funzionalità di un host esistente: utilizzare un altro modello di agente disponibile per ottenere un secondo parere, una revisione del progetto, una verifica della documentazione o un output specializzato, mentre Codex o Claude Code continuano a occuparsi dell’accesso al repository, dei comandi shell, dei test e delle approvazioni.
GlobalGPT pubblica guide ufficiali sulla CLI per Codice e Codice Claude, oltre a Cursor. Nel nostro test di integrazione T5 in ambiente sicuro, l'interfaccia CLI ha completato la stessa attività "congelata" in entrambi gli ambienti confrontati. In Codex, abbiamo inoltre verificato una chiamata in sola lettura all'elenco dei modelli MCP e abbiamo installato, caricato e utilizzato la Skill GlobalGPT.
Integrazione GlobalGPT · Escluso dal punteggio di codifica
CLI verificato in entrambi i flussi di lavoro; MCP e Skill verificati in Codex
Questo parametro misura i percorsi di integrazione, non se GlobalGPT sostituisca uno dei due agenti di codifica nativi.
| Percorso | Ambiente Codex | Corsa dei colleghi Claude |
|---|---|---|
| GlobalGPT CLI | Verificato con gpt-5.6-sol e gpt-5.6-luna | Verificato con le stesse attività congelate |
| MCP | Elenco interattivo dei modelli in sola lettura verificato | Non connesso durante l'esecuzione |
| Abilità | Installato, caricato e testato | Installato ma non utilizzato per le chiamate congelate |
| MCP senza supervisione | Rispettata la limitazione di approvazione | Non testato |
Visualizza la documentazione completa relativa all'integrazione
# GlobalGPT Riepilogo del test di integrazione ## Ambito di applicazione Il test T5 valuta l’integrazione del GlobalGPT ed è escluso dal punteggio di codifica nativo del Codex. Yukie non è stato utilizzato. ## Blocco e prontezza dei modelli - Modello A: `gpt-5.6-sol` - Modello B: `gpt-5.6-luna` - Entrambi i modelli figuravano nell’elenco dei modelli attivi. - Entrambe le prove di prontezza leggere hanno restituito testo valido e analizzabile. - I modelli sono stati bloccati prima delle chiamate formali di output T5A e T5B. ## Risultati formali della CLI | Attività | Modello | Stato | Durata | Token del prompt | Token di completamento | Intestazioni richieste | |---|---|---|---:|---:|---:|---:| | T5A | gpt-5.6-sol | Valido | 27 s | 2.116 | 1.207 | 6/6 | | T5B | gpt-5.6-luna | Valido | 14 s | 2.116 | 1.441 | 6/6 | Entrambe le chiamate formali hanno utilizzato lo stesso compito di pianificazione del prodotto in inglese congelato tramite `glbgpt exec`, hanno restituito un output visibile solo in inglese e non hanno esposto alcuna credenziale. Non si è verificata alcuna riesecuzione di qualità. ## Risultato MCP - `codex mcp list` ha mostrato che `globalgpt` era abilitato. - Una sessione Codex non interattiva ha individuato e tentato di eseguire `mcp__globalgpt__glbgpt_list_models`, ma la chiamata è stata annullata poiché non era disponibile l’approvazione MCP automatica. Nessuna impostazione di sicurezza è stata allentata. - La sessione Codex interattiva attiva ha richiamato con successo lo stesso strumento MCP GlobalGPT in sola lettura e ha ricevuto nove modelli di chat. - Risultato: accesso MCP interattivo verificato; l’esecuzione MCP non interattiva e non presidiata mantiene una limitazione di approvazione. Risultato della skill ## - Le skill GlobalGPT e GlobalGPT Coding sono installate nella directory delle skill di Codex tramite collegamenti al pacchetto di skill CLI in bundle. - La skill GlobalGPT è stata caricata e seguita per la verifica della sessione configurata, la selezione del modello in tempo reale, la prontezza operativa, le opzioni di sicurezza dei crediti e la gestione degli errori. - Risultato: installata e testata nel flusso di lavoro attivo di Codex. ## Conclusione limitata Questa esecuzione verifica il funzionamento delle chiamate CLI GlobalGPT, una chiamata interattiva GlobalGPT MCP in sola lettura da Codex e un percorso della skill GlobalGPT installato/utilizzato. Non dimostra che ogni modello, strumento multimediale, host, account o configurazione MCP automatizzata funzioni. Non testa Yukie né supporta l’affermazione che GlobalGPT sostituisca Codex o Claude Code.
Ambito verificato: chiamate CLI specifiche, una lettura interattiva dell’MCP e un percorso di installazione/utilizzo di una Skill. Ciò non garantisce la verifica di ogni modello, strumento multimediale, host o configurazione automatizzata.
Il confine è importante. L'esecuzione Claude del collega ha verificato il percorso CLI, non l'MCP lato Claude. La Skill era installata lì, ma non è stata utilizzata per le chiamate in sospeso. Un tentativo automatizzato tramite Codex MCP richiedeva comunque un'approvazione manuale. La disponibilità dei modelli e i crediti dipendono anche dal piano GlobalGPT attuale, pertanto gli sviluppatori dovrebbero controllare l'elenco in tempo reale anziché dare per scontato che tutti i modelli siano inclusi.
GlobalGPT copre anche immagini, video, audio e flussi di lavoro guidati degli agenti. Le voci "Slides", "Document" e "Image" di Yukie appartengono a una categoria diversa: offrono modelli predefiniti e una guida passo passo nel browser per attività che non richiedono la scrittura di codice. Questo può risultare più semplice rispetto all’apertura di una CLI di programmazione per creare una presentazione o un documento strutturato, ma non sostituisce la lettura del repository, l’esecuzione dei test o la revisione del codice.
Categoria di flusso di lavoro diversa
Test guidati da Yukie sull'agente del browser
Utile per flussi di lavoro web specifici per determinate attività; non è stato testato come sostituto di un agente di codifica del repository.
| Flusso di lavoro | Criteri soddisfatti | Primo risultato valido |
|---|---|---|
| Diapositive | 5/6 | È stata generata una presentazione di cinque diapositive; non è stato possibile verificare le note del relatore. |
| Documento | 6/6 | Documento di sintesi della ricerca strutturato, con cronologia delle esportazioni e delle versioni. |
| Immagine + didascalia | 5/6 | Immagine ben definita e squadrata; mancava la didascalia richiesta. |
Conclusione fondata: punti di accesso chiari e flussi di lavoro multimodali guidati. Conclusioni non fondate: utilizzo illimitato, prezzo esatto o sostituzione completa del codice Codex/Claude.
Quale linguaggio di programmazione dovrebbe scegliere uno sviluppatore indipendente?
- Scegli Codex quando l'esecuzione compatta e limitata, la combinazione delle superfici disponibili o le tracce di esecuzione disponibili nella tua configurazione si adattano al tuo modo di lavorare.
- Scegli il codice Claude quando assumono maggiore importanza il ciclo di terminale conversazionale, le funzionalità di personalizzazione che avete verificato o comportamenti di revisione più ampi, come quelli osservati nel nostro fixture.
- Utilizzarne uno dei due per un repository che non conosci solo dopo aver superato i test relativi all'architettura in sola lettura e alla valutazione dei rischi. Entrambi gli strumenti hanno svolto bene tale compito.
- Usali entrambi in modo selettivo quando una revisione da parte di un secondo agente giustifica il costo aggiuntivo dell'abbonamento e del coordinamento. Chiedi al secondo strumento di mettere in discussione una differenza o un piano, anziché ripetere ciecamente l'attività.
- Aggiungi GlobalGPT quando il routing multimodello o il lavoro multimodale rappresentano il livello mancante. Mantenere le operazioni native sul repository nell'host di sviluppo.
Una prova di sette giorni è più istruttiva di una classifica. Scegliete una funzionalità reale ma non ancora in produzione, un bug e un'analisi. Bloccate il prompt e il comando di conferma. Registrate il primo diff valido, i test superati, il tempo trascorso, gli interventi umani, l'ambito inatteso e in che modo il lavoro ha influito sul vostro utilizzo disponibile. Il prodotto migliore è quello di cui riuscite a individuare gli errori e di cui riuscite a sostenere il flusso di lavoro.
Domande frequenti sul codice Codex vs Claude
Il Codex è migliore del codice Claude?
Non in tutti i casi. Entrambi hanno portato a termine i quattro compiti previsti dal nostro programma. Claude Code si è distinto per l'ampiezza della revisione, mentre Codex si è dimostrato più conciso in alcune parti relative all'implementazione e alla correzione dei bug.
Qual è la soluzione migliore per i repository di grandi dimensioni?
Il nostro piccolo strumento non è in grado di rispondere a questa domanda. Valuta entrambi nell’ambito di un’attività in architettura di sola lettura dal tuo repository prima di autorizzare eventuali modifiche.
Quale agente di codifica richiede meno supervisione?
Dipende dalla chiarezza del compito, dalle impostazioni del modello, dalle istruzioni del repository e dallo stile di interazione desiderato. Un utente di Reddit ha segnalato diversi modelli di supervisione, ma quell’esperienza individuale non costituisce una regola valida per l’intero prodotto.
Qual è il più economico?
I principali livelli di consumo corrispondono a $20, $100 e $200 al mese, ma la capacità inclusa e le modalità di limitazione variano. I crediti opzionali e la fatturazione tramite API sono gestiti separatamente.
I piani Claude e Claude condividono gli stessi limiti di utilizzo?
Sì. I piani Claude e Claude Code prevedono limiti di sessione condivisa e limiti settimanali per i piani Pro o Max associati.
Le attività locali e quelle su cloud di Codex condividono gli stessi limiti?
I messaggi locali e le chat su cloud condividono una finestra temporale di cinque ore; potrebbero inoltre essere applicati limiti settimanali.
Il modello GlobalGPT può sostituire il modello Codex o il modello Claude Code?
No. È in grado di estendere entrambi i flussi di lavoro con modelli aggiuntivi, CLI, MCP, Skills e strumenti multimodali, ma l'accesso al repository e il comportamento degli agenti di codifica rimangono nell'host.
Posso utilizzare il codice GlobalGPT per entrambi i prodotti?
GlobalGPT offre tutorial ufficiali sulla CLI per entrambe le soluzioni. Abbiamo verificato l'utilizzo della CLI in entrambi gli ambienti e l'uso di MCP e Skill in Codex, con una limitazione relativa all'approvazione per l'MCP in modalità automatica.
I prezzi, le condizioni dei piani, le integrazioni e le fonti di riferimento sono stati verificati nel luglio 2026. I dettagli del prodotto sono soggetti a modifiche.
Apri GlobalGPT se desideri aggiungere un livello multimodello e multimodale al tuo flusso di lavoro di codifica esistente.


