You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(output): activate tool JSON output for codeclimate/sarif via reports config or CLI flag
Pre-3.3.2 setStructuredFormat(true) only fired when --format=codeclimate|sarif.
Reports requested via flows.options.reports.<X> or --report-X=PATH left tools
emitting human text, and every parser (phpstan, phpcs, phpmd, psalm,
parallel-lint — all do json_decode over stdout) returned []. The codeclimate
or sarif payload came out empty.
Fix detects whether a codeclimate/sarif payload will be produced via any
path (primary --format, config reports, CLI report flag) and propagates the
flag accordingly. Reuses collectReportTargets() so CLI > config precedence
and --no-reports semantics stay consistent.
Adds 16-row decision-table unit matrix and 3 release tests against the .phar:
phpstan via reports config, phpstan via --report-sarif CLI, and a multi-tool
flow (phpcs+phpmd) confirming the bypass affected every tool, not just
phpstan.
Also includes FEAT-13 (--fast-dirty execution mode) in v3.4 ROADMAP.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: ROADMAP.md
+63Lines changed: 63 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -398,6 +398,69 @@ Output JSON:
398
398
399
399
**Score**: 6.5/10. Coste muy bajo (reusa lógica de filterJobForMode, sin ejecución), valor real en monorepos y CI orquestado. Encaja con la línea de "data-driven" de v3.3.
400
400
401
+
### FEAT-13 · `--fast-dirty` — modo de ejecución sobre el working tree completo
402
+
403
+
**Casos de uso reales**:
404
+
405
+
1.**Hooks de IA agentic** (Claude Code, Cursor, Cline, Copilot agent…). El agente toca ficheros y queremos aplicar el **mismo** flow que en precommit, con `--format=json` para ahorrar tokens. Hoy los ficheros no están en stage → `--fast` los pierde, `--fast-branch` analiza demasiado, y la única salida es un script bash de ~10 líneas en cada hook que computa la lista y la pasa por `--files`. El QA debería ser uno: el flow del hook humano es el flow del hook IA.
406
+
407
+
2.**Dev en revisión intermedia sin commitear**. Patrón estándar de desarrollo iterativo: "voy a revisar lo que llevo antes de commitear". Hoy o haces `git add -A && githooks flow qa --fast` (ensucia el stage) o te escribes el `--files` a mano. Ambas son fricción.
408
+
409
+
**Hueco que rellena**:
410
+
411
+
| Modo | Set | Para |
412
+
|---|---|---|
413
+
|`--fast`| staged | precommit |
414
+
|`--fast-branch`| branch diff vs main + staged | CI feature branch |
Tracked modificados vs HEAD (staged o no) ∪ untracked no ignorados.
427
+
428
+
**Decisiones del diseño**:
429
+
430
+
| Decisión | Valor |
431
+
|---|---|
432
+
| Nombre del flag |`--fast-dirty` (idiomático git: "dirty working tree" es término oficial; corto; sin ambigüedad con `--fast` que cubre solo staged) |
433
+
| Implementación |`ExecutionContext::getWorktreeDiffFilesLazy()` análogo a `getBranchDiffFilesLazy()`; nuevo variant `ExecutionMode::FAST_DIRTY`; reconocer `fast-dirty` en `EffectiveOptionsResolver`|
434
+
| Fallback | Tree limpio → todos los jobs accelerable skip, exit 0. NO cae a full (sería sorprendente y rompería el caso "git status limpio tras commit") |
435
+
| Mutuamente excluyente con |`--fast`, `--fast-branch`, `--files`, `--files-from` (todos definen el set) |
| Untracked |**Incluidos**. Documentar en docs que si hay scratch files en paths cubiertos, usar `.gitignore` o `--exclude-pattern`. Sin código nuevo (`--no-untracked` solo si aparece reporte real) |
438
+
| Coexistencia con `--files-from=-` (stdin) | El stdin sigue funcionando, tiene su caso de uso (input arbitrario externo). FEAT-13 cubre el caso "set canónico del working tree" con semántica nombrada y testeada, sin pipa |
439
+
440
+
**Composición con FEAT-1** (`only-files` / `exclude-files`):
441
+
442
+
Dos niveles ortogonales — admisión (FEAT-1) y filtrado de input (modo + `paths` del job). FEAT-1 debe leer del set unificado vía `ExecutionContext::getFilteredFiles()`, no hardcodear por modo: si lo hace, FEAT-13 compone gratis.
443
+
444
+
-**Skip por only-files**: dirty `src/AppB/User.php`, job con `only-files: ['src/AppA/**']` → `skipped: true, skipReason: "no files match only-files"`.
445
+
-**Admisión + filtrado**: dirty `src/AppA/Foo.php` + `src/AppB/Bar.php`, job accelerable con `only-files: ['src/AppA/**']` y `paths: ['src/AppA']` → admite; al binario solo `src/AppA/Foo.php` (intersección con `paths`).
446
+
-**Non-accelerable admitido**: dirty `composer.lock`, job non-accelerable con `only-files: ['composer.lock']` → corre la suite entera (FEAT-1 solo admite, no recorta input).
447
+
448
+
Test matrix de FEAT-1 debe incluir un caso por modo accelerable, no solo `--fast`.
449
+
450
+
**Tests obligatorios**:
451
+
- Unit: cómputo del set (tree limpio, solo unstaged, solo untracked, mezcla, dentro de un git worktree real, repo con submodules).
452
+
- Integration: flow run con working tree dirty, jobs accelerable y non-accelerable.
453
+
- Mutua exclusión con `--fast`/`--fast-branch`/`--files`/`--files-from`.
454
+
455
+
**Out of scope**:
456
+
- Distinguir tracked dirty vs untracked vía flag (esperar reporte real de "scratch indeseado analizado").
457
+
- Modo "fast-vs-upstream" (commits locales no en remote) para pre-push hooks; es un caso distinto, no encaja en este modo.
458
+
- Aplicar `--fast-dirty` por defecto a hooks específicos (decisión del usuario en config).
459
+
460
+
**Score**: 7/10. Coste bajo (~1 día código + tests, patrón ya existe en `getBranchDiffFilesLazy`); dos casos confirmados (uno con viento de cola fuerte: agentic IA en 2026); self-contained; aditivo. No bloquea ni depende de FEAT-1/2/3.
461
+
462
+
**Por qué v3.4 y no "Pendiente de análisis"**: coste tan bajo que no compite con el resto del bloque en planning, y el caso agentic-IA tiene timing — retrasarlo a v3.5 cede el espacio a otra herramienta.
463
+
401
464
### Validación de commit messages como tipo nativo (`commit-msg`)
402
465
403
466
Tipo de job nativo que valida el subject del commit con reglas declarativas (`min-length`, `max-length`, `pattern`, `forbid-trailing-period`, `subject-case`, `forbid-empty`, `merge-allowed`) y preset `conventional-commits`. Se cablea al hook git `commit-msg`. Movido el 2026-04-28: a nivel funcional v3.3 ya cumple el objetivo del usuario (multi-flow + multi-reporte + budgets); commit-msg pasa a "nice-to-have" sin urgencia. **Spec de diseño ya redactada** en `spec/spec-design-commit-message-validation.md` (~620 líneas, 17 AC, 34 REQ): cuando se reabra, la implementación arranca directa de ahí.
Copy file name to clipboardExpand all lines: docs/changelog.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,12 @@
2
2
3
3
All notable changes to this project are documented here.
4
4
5
+
## [3.3.2]
6
+
7
+
### Fixed
8
+
9
+
- Code Climate and SARIF reports requested via `flows.options.reports.codeclimate` / `reports.sarif` in config or via `--report-codeclimate=PATH` / `--report-sarif=PATH` CLI flags came out empty (`[]` / no findings) when the primary `--format` was anything other than `codeclimate` / `sarif`. The flag that asks each tool for JSON output only activated on `--format=codeclimate|sarif`, so every tool ran with its default human-text format and the report parsers (which all do `json_decode()` over stdout) found nothing to extract. Affects every tool with a JSON-dependent parser: PHPStan (`--error-format=json`), PHPCS (`--report=json`), PHPMD (positional `json` format), Psalm (`--output-format=json`) and parallel-lint (`--json`). Fixed: tool-level JSON output is now requested whenever a codeclimate or sarif payload will be produced, regardless of how it was requested.
0 commit comments