@tacuchi/agent-workflow-cli 6.2.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +65 -12
  2. package/dist/application/profile/profile-service.d.ts +53 -0
  3. package/dist/application/profile/profile-service.d.ts.map +1 -0
  4. package/dist/application/profile/profile-service.js +210 -0
  5. package/dist/application/profile/profile-service.js.map +1 -0
  6. package/dist/application/self/bootstrap.js +2 -1
  7. package/dist/application/self/bootstrap.js.map +1 -1
  8. package/dist/application/self/detect-hosts.d.ts +18 -0
  9. package/dist/application/self/detect-hosts.d.ts.map +1 -0
  10. package/dist/application/self/detect-hosts.js +37 -0
  11. package/dist/application/self/detect-hosts.js.map +1 -0
  12. package/dist/application/self/install-hooks.d.ts +30 -0
  13. package/dist/application/self/install-hooks.d.ts.map +1 -0
  14. package/dist/application/self/install-hooks.js +253 -0
  15. package/dist/application/self/install-hooks.js.map +1 -0
  16. package/dist/application/self/install-skill.d.ts +2 -0
  17. package/dist/application/self/install-skill.d.ts.map +1 -1
  18. package/dist/application/self/install-skill.js +69 -3
  19. package/dist/application/self/install-skill.js.map +1 -1
  20. package/dist/cli/commands/self.d.ts.map +1 -1
  21. package/dist/cli/commands/self.js +9 -1
  22. package/dist/cli/commands/self.js.map +1 -1
  23. package/dist/cli/tui/tabs/skills-tab.d.ts.map +1 -1
  24. package/dist/cli/tui/tabs/skills-tab.js +100 -24
  25. package/dist/cli/tui/tabs/skills-tab.js.map +1 -1
  26. package/package.json +2 -2
  27. package/skills/agent-workflow/commands/README.md +26 -0
  28. package/skills/agent-workflow/commands/compact.md +24 -0
  29. package/skills/agent-workflow/commands/doctor.md +100 -0
  30. package/skills/agent-workflow/commands/export-arq.md +77 -0
  31. package/skills/agent-workflow/commands/export-conclusions.md +78 -0
  32. package/skills/agent-workflow/commands/export-plan.md +74 -0
  33. package/skills/agent-workflow/commands/export-qa-note.md +30 -0
  34. package/skills/agent-workflow/commands/export-report.md +78 -0
  35. package/skills/agent-workflow/commands/export-requirement.md +30 -0
  36. package/skills/agent-workflow/commands/export-scripts.md +92 -0
  37. package/skills/agent-workflow/commands/export-tech-manuals.md +75 -0
  38. package/skills/agent-workflow/commands/export-tech-note.md +30 -0
  39. package/skills/agent-workflow/commands/hub-init.md +82 -0
  40. package/skills/agent-workflow/commands/migrate.md +56 -0
  41. package/skills/agent-workflow/commands/project-init.md +60 -0
  42. package/skills/agent-workflow/commands/resume.md +22 -0
  43. package/skills/agent-workflow/commands/rules.md +40 -0
  44. package/skills/agent-workflow/commands/session.md +35 -0
  45. package/skills/agent-workflow/doctrine/README.md +15 -0
  46. package/skills/agent-workflow/doctrine/compact/SKILL.md +145 -0
  47. package/skills/agent-workflow/doctrine/doctor/SKILL.md +86 -0
  48. package/skills/agent-workflow/doctrine/doctor/SKILL.md.tmp +0 -0
  49. package/skills/agent-workflow/doctrine/hub-init/SKILL.md +157 -0
  50. package/skills/agent-workflow/doctrine/hub-init/SKILL.md.tmp +0 -0
  51. package/skills/agent-workflow/doctrine/hub-init/references/multiroot-manual.md +51 -0
  52. package/skills/agent-workflow/doctrine/implement/SKILL.md +290 -0
  53. package/skills/agent-workflow/doctrine/implement/references/branch-verification.md +16 -0
  54. package/skills/agent-workflow/doctrine/implement/references/design-md-template.md +108 -0
  55. package/skills/agent-workflow/doctrine/implement/references/rollback-guide.md +81 -0
  56. package/skills/agent-workflow/doctrine/migrate/SKILL.md +281 -0
  57. package/skills/agent-workflow/doctrine/migrate/SKILL.md.tmp +0 -0
  58. package/skills/agent-workflow/doctrine/project-init/SKILL.md +100 -0
  59. package/skills/agent-workflow/doctrine/project-init/SKILL.md.tmp +0 -0
  60. package/skills/agent-workflow/doctrine/refactor/SKILL.md +208 -0
  61. package/skills/agent-workflow/doctrine/refactor/references/refactor-md-template.md +108 -0
  62. package/skills/agent-workflow/doctrine/refactor/references/strangler-checklist.md +116 -0
  63. package/skills/agent-workflow/doctrine/resume/SKILL.md +199 -0
  64. package/skills/agent-workflow/doctrine/rules/SKILL.md +224 -0
  65. package/skills/agent-workflow/doctrine/rules/SKILL.md.tmp +0 -0
  66. package/skills/agent-workflow/doctrine/session/SKILL.md +383 -0
  67. package/skills/agent-workflow/doctrine/session/references/auto-plan-rules.md +63 -0
  68. package/skills/agent-workflow/doctrine/session/references/backlog-template.md +95 -0
  69. package/skills/agent-workflow/doctrine/session/references/branch-verification.md +198 -0
  70. package/skills/agent-workflow/doctrine/session/references/commits-policy.md +111 -0
  71. package/skills/agent-workflow/doctrine/session/references/communication-style.md +50 -0
  72. package/skills/agent-workflow/doctrine/session/references/graduacion-routing.md +88 -0
  73. package/skills/agent-workflow/doctrine/session/references/lifecycle-deep.md +160 -0
  74. package/skills/agent-workflow/doctrine/session/references/prompts/C1-specialty-selection.md +11 -0
  75. package/skills/agent-workflow/doctrine/session/references/prompts/C2-cost-guard.md +14 -0
  76. package/skills/agent-workflow/doctrine/session/references/prompts/M1-closure-commit-prompt.md +104 -0
  77. package/skills/agent-workflow/doctrine/session/references/prompts/M10-next-step.md +17 -0
  78. package/skills/agent-workflow/doctrine/session/references/prompts/M11-context.md +16 -0
  79. package/skills/agent-workflow/doctrine/session/references/prompts/M2-branch-caso-A.md +14 -0
  80. package/skills/agent-workflow/doctrine/session/references/prompts/M3-branch-caso-C.md +33 -0
  81. package/skills/agent-workflow/doctrine/session/references/prompts/M4-cross-source-hard-gate.md +33 -0
  82. package/skills/agent-workflow/doctrine/session/references/prompts/M5-modality-analyze.md +15 -0
  83. package/skills/agent-workflow/doctrine/session/references/prompts/M6-phase-gate.md +31 -0
  84. package/skills/agent-workflow/doctrine/session/references/prompts/M7-refactor-legacy-detected.md +28 -0
  85. package/skills/agent-workflow/doctrine/session/references/prompts/M8-refactor-cleanup.md +16 -0
  86. package/skills/agent-workflow/doctrine/session/references/prompts/M9-contract-review.md +39 -0
  87. package/skills/agent-workflow/doctrine/session/references/prompts/S1-type-design.md +15 -0
  88. package/skills/agent-workflow/doctrine/session/references/prompts/S2-topic-change-detection.md +14 -0
  89. package/skills/agent-workflow/doctrine/session/references/prompts/S3-flow-detection.md +28 -0
  90. package/skills/agent-workflow/doctrine/session/references/prompts/S4-resume.md +27 -0
  91. package/skills/agent-workflow/doctrine/session/references/prompts/S5-post-compact.md +17 -0
  92. package/skills/agent-workflow/doctrine/session/references/prompts/S6-scope.md +16 -0
  93. package/skills/agent-workflow/doctrine/session/references/prompts/S7-design-review.md +37 -0
  94. package/skills/agent-workflow/doctrine/session/references/prompts-catalog.md +210 -0
  95. package/skills/agent-workflow/doctrine/session/references/sandbox-readonly-rules.md +82 -0
  96. package/skills/agent-workflow/doctrine/session/references/specialty-decision-tree.md +56 -0
  97. package/skills/agent-workflow/doctrine/session/references/topic-change-rules.md +67 -0
  98. package/skills/agent-workflow/exports/README.md +15 -0
  99. package/skills/agent-workflow/exports/export-arq/SKILL.md +229 -0
  100. package/skills/agent-workflow/exports/export-arq/SKILL.md.tmp +0 -0
  101. package/skills/agent-workflow/exports/export-arq/references/lexico-tecnico.md +94 -0
  102. package/skills/agent-workflow/exports/export-arq/references/template-c4.md +293 -0
  103. package/skills/agent-workflow/exports/export-arq/references/template-plantuml.puml +77 -0
  104. package/skills/agent-workflow/exports/export-arq/references/template-structurizr.dsl +72 -0
  105. package/skills/agent-workflow/exports/export-arq/references/validations.md +231 -0
  106. package/skills/agent-workflow/exports/export-conclusions/SKILL.md +169 -0
  107. package/skills/agent-workflow/exports/export-conclusions/references/dedup-rules.md +154 -0
  108. package/skills/agent-workflow/exports/export-conclusions/references/template-conclusions.md +158 -0
  109. package/skills/agent-workflow/exports/export-plan/SKILL.md +225 -0
  110. package/skills/agent-workflow/exports/export-plan/references/state-transitions.md +141 -0
  111. package/skills/agent-workflow/exports/export-plan/references/template-plan.md +132 -0
  112. package/skills/agent-workflow/exports/export-qa-note/SKILL.md +31 -0
  113. package/skills/agent-workflow/exports/export-report/SKILL.md +262 -0
  114. package/skills/agent-workflow/exports/export-report/SKILL.md.tmp +0 -0
  115. package/skills/agent-workflow/exports/export-report/references/lexico.md +174 -0
  116. package/skills/agent-workflow/exports/export-report/references/template-a.md +95 -0
  117. package/skills/agent-workflow/exports/export-report/references/template-b.md +221 -0
  118. package/skills/agent-workflow/exports/export-report/references/template-c.md +180 -0
  119. package/skills/agent-workflow/exports/export-report/references/validations.md +255 -0
  120. package/skills/agent-workflow/exports/export-requirement/SKILL.md +31 -0
  121. package/skills/agent-workflow/exports/export-scripts/SKILL.md +324 -0
  122. package/skills/agent-workflow/exports/export-scripts/references/code-scan-recommendations.md +83 -0
  123. package/skills/agent-workflow/exports/export-scripts/references/deprecation-plan.md +80 -0
  124. package/skills/agent-workflow/exports/export-scripts/references/lexico-tecnico.md +80 -0
  125. package/skills/agent-workflow/exports/export-scripts/references/manifest-template.md +253 -0
  126. package/skills/agent-workflow/exports/export-scripts/references/readme-template.md +79 -0
  127. package/skills/agent-workflow/exports/export-scripts/references/theme-handling.md +168 -0
  128. package/skills/agent-workflow/exports/export-scripts/references/validations.md +242 -0
  129. package/skills/agent-workflow/exports/export-tech-manuals/SKILL.md +214 -0
  130. package/skills/agent-workflow/exports/export-tech-manuals/references/lexico-tecnico.md +97 -0
  131. package/skills/agent-workflow/exports/export-tech-manuals/references/template-index.md +123 -0
  132. package/skills/agent-workflow/exports/export-tech-manuals/references/template-manual.md +143 -0
  133. package/skills/agent-workflow/exports/export-tech-manuals/references/validations.md +211 -0
  134. package/skills/agent-workflow/exports/export-tech-note/SKILL.md +31 -0
  135. package/skills/agent-workflow/hooks/README.md +15 -0
  136. package/skills/agent-workflow/hooks/hooks.template.json +90 -0
  137. package/skills/agent-workflow/references/README.md +12 -0
  138. package/skills/agent-workflow/references/legacy-anchors.md +50 -0
  139. package/skills/agent-workflow/references/profile-parametrization.md +88 -0
  140. package/skills/agent-workflow/specialties/README.md +14 -0
  141. package/skills/agent-workflow/specialties/analyze-conclude/SKILL.md +175 -0
  142. package/skills/agent-workflow/specialties/analyze-conclude/references/incident-classification.md +61 -0
  143. package/skills/agent-workflow/specialties/analyze-investigate/SKILL.md +148 -0
  144. package/skills/agent-workflow/specialties/analyze-investigate/SKILL.md.tmp +0 -0
  145. package/skills/agent-workflow/specialties/analyze-investigate/references/cost-guard.md +85 -0
  146. package/skills/agent-workflow/specialties/analyze-synthesize/SKILL.md +127 -0
  147. package/skills/agent-workflow/specialties/design-brief/SKILL.md +90 -0
  148. package/skills/agent-workflow/specialties/design-deliver/SKILL.md +121 -0
  149. package/skills/agent-workflow/specialties/design-develop/SKILL.md +115 -0
  150. package/skills/agent-workflow/specialties/design-discover/SKILL.md +103 -0
  151. package/skills/agent-workflow/standards/README.md +12 -0
  152. package/skills/agent-workflow/standards/coding-standards/SKILL.md +102 -0
  153. package/skills/agent-workflow/standards/coding-standards/SKILL.md.tmp +0 -0
  154. package/skills/agent-workflow/standards/coding-standards/references/angular-typescript.md +266 -0
  155. package/skills/agent-workflow/standards/coding-standards/references/database-conventions.md +170 -0
  156. package/skills/agent-workflow/standards/coding-standards/references/fe-be-integration.md +300 -0
  157. package/skills/agent-workflow/standards/coding-standards/references/frontend-structure.md +182 -0
  158. package/skills/agent-workflow/standards/coding-standards/references/java-spring.md +244 -0
  159. package/skills/agent-workflow/standards/coding-standards/references/project-structure.md +197 -0
  160. package/skills/agent-workflow/standards/frontend-design/SKILL.md +62 -0
  161. package/skills/agent-workflow/standards/frontend-design/references/feedback-toasts-patterns.md +249 -0
  162. package/skills/agent-workflow/standards/frontend-design/references/form-patterns.md +278 -0
  163. package/skills/agent-workflow/standards/frontend-design/references/list-patterns.md +256 -0
  164. package/skills/agent-workflow/standards/frontend-design/references/modal-patterns.md +220 -0
  165. package/skills/agent-workflow/standards/frontend-design/references/navigation-patterns.md +224 -0
  166. package/skills/agent-workflow/standards/redaccion-simple/SKILL.md +128 -0
  167. package/skills/agent-workflow/standards/sql-rollback-generator/SKILL.md +197 -0
  168. package/skills/agent-workflow/standards/sql-rollback-generator/references/irreversible-checklist.md +161 -0
  169. package/skills/agent-workflow/standards/sql-rollback-generator/references/release-rollback.md +131 -0
  170. package/skills/agent-workflow/standards/sql-rollback-generator/references/rollback-patterns.md +255 -0
  171. package/skills/agent-workflow/standards/sql-script-organizer/SKILL.md +244 -0
  172. package/skills/agent-workflow/standards/sql-script-organizer/references/bundle-readme-template.md +82 -0
  173. package/skills/agent-workflow/standards/sql-script-organizer/references/categorization-rules.md +122 -0
  174. package/skills/agent-workflow/standards/sql-script-organizer/references/consolidation-cross-session.md +125 -0
  175. package/skills/agent-workflow/standards/sql-script-organizer/references/scripts-sql-format.md +140 -0
  176. package/skills/agent-workflow/standards/testing-strategy/SKILL.md +113 -0
  177. package/skills/agent-workflow/standards/testing-strategy/references/test-levels.md +255 -0
  178. package/skills/agent-workflow/workflows/README.md +12 -0
  179. package/skills/agent-workflow/workflows/analyze-workflow/SKILL.md +107 -0
  180. package/skills/agent-workflow/workflows/design-workflow/SKILL.md +100 -0
  181. package/skills/agent-workflow/workflows/dev-workflow/SKILL.md +195 -0
@@ -0,0 +1,300 @@
1
+ # FE-BE Integration — reglas transversales
2
+
3
+ > Anchor: `agent-workflow:fe-be-integration`. Reglas canónicas para la integración Frontend ↔ Backend en proyectos qtc-* a partir de qtc-dev v2.6 (session013) — actualizado en v2.7 (session015) para reflejar el modelo phased extendido Phase 0-5. Aplica a sesiones `flow=dev` con `## Type: feature|refactor` y a refactors guiados por el skill `agent-workflow:refactor`.
4
+ >
5
+ > Origen: session013-dev-flujo-feature-refactor-phased + session015-dev-aplicar-flujo-fases-extendido. Prior art: [JSON Merge Patch RFC 7396](https://datatracker.ietf.org/doc/html/rfc7396), [Walking Skeleton — Cockburn](https://codeclimate.com/blog/kickstart-your-next-project-with-a-walking-skeleton), [CQRS — Microsoft Learn](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs).
6
+
7
+ ## Resumen ejecutivo
8
+
9
+ | Regla | Qué aplicar | Por qué |
10
+ |---|---|---|
11
+ | **R1 — Sparse DTO unificado** | Mismo DTO para create + edit, todos los campos nullable. `null` = "no tocar". | Reduce duplicación, hace explícita la intención del FE, simplifica el BE. |
12
+ | **R2 — PATCH para edit** | `@PatchMapping` en BE, `http.patch()` en FE. POST queda solo para create. | Semántica HTTP correcta. PATCH = mutación parcial; PUT = reemplazo total. |
13
+ | **R3 — FE envía solo cambios** | El FE construye el payload con campos modificados; el resto se omite o queda `null`. | Reduce payload, evita race conditions con campos no editados. |
14
+ | **R4 — Sin fallbacks que oculten errores** | Prohibido `catchError(() => of([]))` en FE. Prohibido `try/catch` que retorne mock en BE durante migraciones. | Los errores deben fallar ruidosamente para detectarse en cert antes de prod. |
15
+ | **R5 — Validación en BE con Bean Validation** | DTOs con `@NotNull`/`@Size`/etc. Errores → 400 estructurado con `field` y `message`. | El FE muestra el error sin lógica adicional. |
16
+ | **R6 — DB stub-first** | Funciones/SP nuevas arrancan en Phase 0 devolviendo mock. Implementación real en Phase 1/2. | Separación de cableado vs lógica; permite testear el contrato antes de comprometer SQL. |
17
+
18
+ ## R1 — Sparse DTO unificado
19
+
20
+ ### Patrón
21
+
22
+ Un único DTO `<Feature>SaveRequest` que sirve para POST (create) y PATCH (edit). Todos los campos son nullable. Convención:
23
+
24
+ - En **POST** (create): el FE envía todos los campos requeridos; los opcionales pueden venir `null`.
25
+ - En **PATCH** (edit): el FE envía solo los campos que cambian; el resto omitido o `null` significa "no tocar".
26
+
27
+ ### Tradeoff aceptado
28
+
29
+ **No se puede setear un campo a `null` intencionalmente.** Si el dominio requiere "limpiar a null" un campo (ej. fecha de baja → null), modelarlo como:
30
+ - Endpoint dedicado (`POST /api/<feature>/{id}/limpiar-fecha-baja`) para semántica clara.
31
+ - O bien, campo separado `clearFechaBaja: boolean` en el DTO.
32
+
33
+ Esto es deliberado: optar por simplicidad sobre completitud (vs. JSON Patch RFC 6902 que sí permite operaciones explícitas pero añade complejidad).
34
+
35
+ ### Ejemplo Java/Spring
36
+
37
+ ```java
38
+ public record CategoriaSaveRequest(
39
+ @Size(max = 100) String nombre,
40
+ @Size(max = 500) String descripcion,
41
+ Boolean activo,
42
+ Integer ordenVisual
43
+ ) {}
44
+
45
+ @RestController
46
+ @RequestMapping("/api/categorias")
47
+ @RequiredArgsConstructor
48
+ public class CategoriasController {
49
+
50
+ private final CategoriasService service;
51
+
52
+ @PostMapping
53
+ public ResponseEntity<CategoriaResponse> create(
54
+ @Valid @RequestBody CategoriaSaveRequest req
55
+ ) {
56
+ return ResponseEntity.ok(service.create(req));
57
+ }
58
+
59
+ @PatchMapping("/{id}")
60
+ public ResponseEntity<CategoriaResponse> edit(
61
+ @PathVariable Long id,
62
+ @Valid @RequestBody CategoriaSaveRequest req
63
+ ) {
64
+ return ResponseEntity.ok(service.patch(id, req));
65
+ }
66
+ }
67
+ ```
68
+
69
+ En el service, el método `patch(id, req)` ignora campos `null` del request:
70
+
71
+ ```java
72
+ @Transactional
73
+ public CategoriaResponse patch(Long id, CategoriaSaveRequest req) {
74
+ Categoria entity = repo.findById(id).orElseThrow(NotFoundException::new);
75
+ if (req.nombre() != null) entity.setNombre(req.nombre());
76
+ if (req.descripcion() != null) entity.setDescripcion(req.descripcion());
77
+ if (req.activo() != null) entity.setActivo(req.activo());
78
+ if (req.ordenVisual() != null) entity.setOrdenVisual(req.ordenVisual());
79
+ return mapper.toResponse(repo.save(entity));
80
+ }
81
+ ```
82
+
83
+ ### Ejemplo Angular/TypeScript
84
+
85
+ ```typescript
86
+ export interface CategoriaSaveRequest {
87
+ nombre?: string | null;
88
+ descripcion?: string | null;
89
+ activo?: boolean | null;
90
+ ordenVisual?: number | null;
91
+ }
92
+
93
+ @Injectable({ providedIn: 'root' })
94
+ export class CategoriasApiService {
95
+ private readonly base = `${environment.apiUrl}/api/categorias`;
96
+
97
+ constructor(private http: HttpClient) {}
98
+
99
+ create(req: CategoriaSaveRequest): Observable<CategoriaResponse> {
100
+ return this.http.post<CategoriaResponse>(this.base, req);
101
+ }
102
+
103
+ edit(id: number, cambios: CategoriaSaveRequest): Observable<CategoriaResponse> {
104
+ return this.http.patch<CategoriaResponse>(`${this.base}/${id}`, cambios);
105
+ }
106
+ }
107
+ ```
108
+
109
+ En el componente de edit, el FE construye el payload solo con cambios:
110
+
111
+ ```typescript
112
+ guardar(): void {
113
+ const original = this.categoriaOriginal;
114
+ const form = this.form.value;
115
+ const cambios: CategoriaSaveRequest = {};
116
+ if (form.nombre !== original.nombre) cambios.nombre = form.nombre;
117
+ if (form.descripcion !== original.descripcion) cambios.descripcion = form.descripcion;
118
+ if (form.activo !== original.activo) cambios.activo = form.activo;
119
+ if (form.ordenVisual !== original.ordenVisual) cambios.ordenVisual = form.ordenVisual;
120
+
121
+ if (Object.keys(cambios).length === 0) return; // nada cambió
122
+
123
+ this.api.edit(original.id, cambios).subscribe({
124
+ next: (res) => this.toast.success('Guardado'),
125
+ error: (err) => this.errorHandler.handle(err) // R4: no silenciar
126
+ });
127
+ }
128
+ ```
129
+
130
+ ## R2 — PATCH para edit
131
+
132
+ | Verbo | Cuándo | DTO | Idempotente |
133
+ |---|---|---|---|
134
+ | `POST /api/<feature>` | Crear nueva entidad | `<Feature>SaveRequest` (todos los required cargados) | No |
135
+ | `GET /api/<feature>` y `GET /api/<feature>/{id}` | Listar / obtener | — | Sí |
136
+ | `PATCH /api/<feature>/{id}` | Editar parcial | `<Feature>SaveRequest` (solo campos cambiados) | No (orden importa si dos PATCHes pisan el mismo campo) |
137
+ | `DELETE /api/<feature>/{id}` | Eliminar | — | Sí |
138
+
139
+ **No usar `PUT`** salvo casos excepcionales (replace total con todos los campos). El default es PATCH.
140
+
141
+ ## R3 — FE envía solo cambios
142
+
143
+ Reduce payload y evita pisar campos no editados. Implementación: FE compara `formValue` con `entidadOriginal` y arma diff. Ver ejemplo en R1.
144
+
145
+ **Anti-pattern**: enviar todo el formulario incluyendo campos no editados — equivale a PUT y rompe la semántica de PATCH sparse.
146
+
147
+ ## R4 — Sin fallbacks que oculten errores
148
+
149
+ ### Prohibido en FE
150
+
151
+ ```typescript
152
+ // ❌ NO HACER: silencia errores HTTP
153
+ this.api.list().pipe(
154
+ catchError(() => of([])) // <-- usuario nunca ve el error
155
+ ).subscribe(items => this.items = items);
156
+ ```
157
+
158
+ ```typescript
159
+ // ✅ HACER: propagar al usuario via toast/handler
160
+ this.api.list().subscribe({
161
+ next: (items) => this.items = items,
162
+ error: (err) => this.errorHandler.handle(err)
163
+ });
164
+ ```
165
+
166
+ ### Prohibido en BE durante migraciones
167
+
168
+ ```java
169
+ // ❌ NO HACER: fallback al método legacy oculta bugs
170
+ public List<Categoria> listar() {
171
+ try {
172
+ return nuevoListarConSparse();
173
+ } catch (Exception e) {
174
+ log.warn("Nuevo método falló, usando legacy", e);
175
+ return legacyListar(); // <-- usuario nunca se entera
176
+ }
177
+ }
178
+ ```
179
+
180
+ ```java
181
+ // ✅ HACER: dejar que el nuevo método falle ruidosamente
182
+ public List<Categoria> listar() {
183
+ return nuevoListarConSparse();
184
+ }
185
+ ```
186
+
187
+ Si necesitás rollout gradual, usá feature flag explícita:
188
+
189
+ ```java
190
+ public List<Categoria> listar() {
191
+ if (featureFlags.isEnabled("categorias-sparse-dto")) {
192
+ return nuevoListarConSparse();
193
+ }
194
+ return legacyListar();
195
+ }
196
+ ```
197
+
198
+ La feature flag es **explícita y observable** (vs. fallback silencioso).
199
+
200
+ ## R5 — Validación en BE con Bean Validation
201
+
202
+ > **Phase 3 marker (v2.7+)**: Bean Validation se materializa en **Phase 3 — Validaciones / Correcciones**, no en Phase 2 — Escritura. Phase 2 produce endpoints funcionales que mutan estado pero pueden devolver 500 ante input malformado. Phase 3 agrega `@NotNull`/`@Size`/etc. + handler global 400 estructurado. Trade-off aceptado: temporalmente el código de Phase 2 no es robusto contra input malformado; el usuario debe ser consciente de no testear edge cases hasta cerrar Phase 3.
203
+
204
+ ```java
205
+ public record CategoriaSaveRequest(
206
+ @NotNull(message = "El nombre es obligatorio")
207
+ @Size(min = 1, max = 100, message = "Entre 1 y 100 caracteres")
208
+ String nombre,
209
+
210
+ @Size(max = 500)
211
+ String descripcion,
212
+
213
+ @NotNull
214
+ Boolean activo,
215
+
216
+ @PositiveOrZero(message = "Debe ser ≥0")
217
+ Integer ordenVisual
218
+ ) {}
219
+ ```
220
+
221
+ Handler global devuelve estructura uniforme:
222
+
223
+ ```java
224
+ @RestControllerAdvice
225
+ public class GlobalExceptionHandler {
226
+
227
+ @ExceptionHandler(MethodArgumentNotValidException.class)
228
+ public ResponseEntity<ValidationErrorResponse> onValidation(MethodArgumentNotValidException ex) {
229
+ var fields = ex.getBindingResult().getFieldErrors().stream()
230
+ .map(fe -> new FieldError(fe.getField(), fe.getDefaultMessage()))
231
+ .toList();
232
+ return ResponseEntity.badRequest().body(new ValidationErrorResponse(fields));
233
+ }
234
+ }
235
+
236
+ public record ValidationErrorResponse(List<FieldError> errors) {}
237
+ public record FieldError(String field, String message) {}
238
+ ```
239
+
240
+ El FE recibe 400 con estructura predecible y muestra los errores junto a cada campo.
241
+
242
+ **Limitación con Sparse DTO**: `@NotNull` en el DTO unificado **NO se valida en PATCH**, porque PATCH permite enviar campos `null`. Soluciones:
243
+
244
+ - **Validation groups**: `@NotNull(groups = OnCreate.class)` y aplicar grupo distinto en POST vs PATCH.
245
+ - **DTO separado solo para POST**: `<Feature>CreateRequest extends <Feature>SaveRequest` con campos requeridos no-null. Aceptable cuando el escenario lo justifica.
246
+
247
+ Documentar la decisión en DECISIONS.md de la sesión.
248
+
249
+ ## R6 — DB stub-first
250
+
251
+ > **Flujo phased v2.7+**: Phase 0 mock → Phase 1 query real → Phase 3 validaciones de input/integridad referencial. El stub en Phase 0 permite probar el cableado e2e + routing sin comprometer SQL real.
252
+
253
+ En Phase 0 (contrato), funciones/SP nuevas devuelven mock:
254
+
255
+ ```sql
256
+ -- Phase 0: stub
257
+ CREATE OR REPLACE FUNCTION fn_categorias_listar(
258
+ p_filtro TEXT DEFAULT NULL,
259
+ p_pagina INT DEFAULT 1,
260
+ p_tamanio INT DEFAULT 20
261
+ ) RETURNS JSONB AS $$
262
+ BEGIN
263
+ -- TODO Phase 1: implementar query real con filtro y paginación
264
+ RETURN '[]'::jsonb;
265
+ END;
266
+ $$ LANGUAGE plpgsql STABLE;
267
+ ```
268
+
269
+ ```sql
270
+ -- Phase 1: implementación real
271
+ CREATE OR REPLACE FUNCTION fn_categorias_listar(
272
+ p_filtro TEXT DEFAULT NULL,
273
+ p_pagina INT DEFAULT 1,
274
+ p_tamanio INT DEFAULT 20
275
+ ) RETURNS JSONB AS $$
276
+ WITH base AS (
277
+ SELECT id, nombre, descripcion, activo, orden_visual
278
+ FROM esq_admin.tb_categorias
279
+ WHERE p_filtro IS NULL OR nombre ILIKE '%' || p_filtro || '%'
280
+ )
281
+ SELECT COALESCE(jsonb_agg(row_to_json(base)), '[]'::jsonb)
282
+ FROM base
283
+ ORDER BY orden_visual
284
+ OFFSET (p_pagina - 1) * p_tamanio
285
+ LIMIT p_tamanio;
286
+ $$ LANGUAGE sql STABLE;
287
+ ```
288
+
289
+ Reglas qtc-dev/coding-standards/database-conventions.md siguen aplicando (header de 4 líneas, idempotencia, schema explícito, BEGIN/COMMIT en scripts).
290
+
291
+ ## Refs
292
+
293
+ - `agent-workflow:coding-standards/references/java-spring.md` — convenciones Spring Boot (Constructor Injection, @Transactional, records).
294
+ - `agent-workflow:coding-standards/references/angular-typescript.md` — convenciones Angular (HttpClient, ApiService, environments).
295
+ - `agent-workflow:coding-standards/references/database-conventions.md` — convenciones BD qtc-* (schemas, naming, scripts).
296
+ - `agent-workflow:implement/SKILL.md` — phased mode (Phase 0/1/2 + gate M6 entre phases; S7 design-review antes de Phase 0 desde planning closure).
297
+ - `agent-workflow:refactor/SKILL.md` — Strangler Fig para refactors completos.
298
+ - `agent-workflow:prompts-catalog#M6,S7` — gates phased (S7 design-review antes de Phase 0; M6 entre phases). M9 retirado v2.8+.
299
+ - [JSON Merge Patch RFC 7396](https://datatracker.ietf.org/doc/html/rfc7396) — spec del comportamiento PATCH sparse (qtc-dev usa **convención simple sparse** en lugar del Content-Type RFC 7396, pero la semántica conceptual es idéntica salvo el caso "set to null intencional").
300
+ - [JSON Patch RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902) — alternativa con array de operaciones; descartada por complejidad.
@@ -0,0 +1,182 @@
1
+ # Estructura de Proyecto Frontend
2
+
3
+ Convenciones de estructura para aplicaciones Angular del tu ecosistema.
4
+
5
+ ## Versiones en uso
6
+
7
+ - Angular 15 (pefectivo-front-angular)
8
+ - Angular 16 (core-frontend-miscuotas-externo)
9
+ - TypeScript 4.9 - 5.1
10
+
11
+ ## Arquitectura `@data` / `@presentation`
12
+
13
+ ```
14
+ src/app/
15
+ ├── @data/ ← Capa de datos
16
+ │ ├── interfaces/ ← Interfaces TypeScript (espejean el backend)
17
+ │ ├── services/ ← ApiService central + services de datos
18
+ │ ├── guards/ ← Route guards
19
+ │ ├── interceptors/ ← HTTP interceptors
20
+ │ └── directive/ ← Directivas custom
21
+ ├── @presentation/ ← Capa de presentación
22
+ │ ├── components/ ← Componentes de UI organizados por feature
23
+ │ ├── services/ ← Services de negocio/UI que consumen ApiService
24
+ │ ├── shared/ ← Componentes y módulos compartidos
25
+ │ ├── auth/ ← Módulo de autenticación (si aplica)
26
+ │ ├── home/ ← Página principal
27
+ │ └── pages/ ← Páginas de la aplicación
28
+ ├── Utils/ ← Utilidades (armarPayload, requestFilter, etc.)
29
+ ├── app.module.ts
30
+ ├── app-routing.module.ts
31
+ └── app.component.ts
32
+ ```
33
+
34
+ ## ApiService — Wrapper HTTP central
35
+
36
+ Todas las llamadas HTTP pasan por `@data/services/api.service.ts`. No usar `HttpClient` directamente en otros services.
37
+
38
+ ```typescript
39
+ @Injectable({ providedIn: 'root' })
40
+ export class ApiService {
41
+ constructor(
42
+ private toast: ToastService,
43
+ private http: HttpClient,
44
+ private storageService: StorageService
45
+ ) {}
46
+
47
+ get(path: string, params?: any): Observable<any> {
48
+ return this.http.get(path, { params }).pipe(
49
+ catchError((error: HttpErrorResponse) => {
50
+ if (error.status === 401) {
51
+ window.location.href = this.storage.url; // Redirección en 401
52
+ }
53
+ const errorMessage = error?.error?.status?.error?.messages?.[0] ?? 'Error inesperado';
54
+ this.toast.showToast(errorMessage, 'danger');
55
+ return this.formatErrors(error);
56
+ })
57
+ );
58
+ }
59
+
60
+ post(path: string, body: any): Observable<any> { /* mismo patrón */ }
61
+ put(path: string, body: object = {}): Observable<any> { /* mismo patrón */ }
62
+ patch(path: string, body: object = {}): Observable<any> { /* mismo patrón */ }
63
+ delete(path: string): Observable<any> { /* mismo patrón */ }
64
+ }
65
+ ```
66
+
67
+ ## Interfaces — Espejeo del backend
68
+
69
+ En `@data/interfaces/` se definen interfaces que reflejan las estructuras del backend:
70
+
71
+ ```typescript
72
+ // generics.ts — Equivale a RespBase<T> del backend
73
+ export interface IResponsePayload<T> {
74
+ trace: Trace;
75
+ status: Status;
76
+ payload: T;
77
+ }
78
+
79
+ export interface IPayloadListG<T> {
80
+ count: number;
81
+ total: number;
82
+ items: T[];
83
+ }
84
+
85
+ export interface ResponseDTO {
86
+ identificador: number;
87
+ cuerpo: string;
88
+ mensaje: string;
89
+ }
90
+ ```
91
+
92
+ Cada entidad de negocio tiene su propia interface: `solicitud.ts`, `credito.ts`, `cliente.ts`, `oferta.ts`, etc.
93
+
94
+ ## Services de presentación
95
+
96
+ En `@presentation/services/` se crean services que consumen `ApiService`:
97
+
98
+ ```typescript
99
+ @Injectable({ providedIn: 'root' })
100
+ export class SolicitudService {
101
+ constructor(private apiService: ApiService) {}
102
+
103
+ generaSolicitud(solicitud: Solicitud): Observable<IResponsePayload<ResponseDTO>> {
104
+ const request = armarPayload<any>(solicitud);
105
+ const url = `${env.API_PRESTAMO}v1/solicitud`;
106
+ return this.apiService.post(url, request);
107
+ }
108
+ }
109
+ ```
110
+
111
+ Patrón: URL desde environment + payload armado con `armarPayload()` de `Utils/`.
112
+
113
+ ## Utilidades
114
+
115
+ `Utils/utils.ts` provee funciones compartidas:
116
+ - `armarPayload<T>(data)` — Envuelve datos en la estructura `ReqBase` con trace
117
+ - `requestFilter(params)` — Convierte un objeto a query string
118
+
119
+ ## Environments
120
+
121
+ Tres archivos de configuración con URLs de API:
122
+
123
+ - `environment.ts` — Base (vacío)
124
+ - `environment.dev.ts` — Desarrollo/certificación
125
+ - `environment.prod.ts` — Producción
126
+
127
+ ```typescript
128
+ export const environment = {
129
+ production: false,
130
+ API_PRESTAMO: 'https://api-cert.example.com/',
131
+ API_SOLICITUD: 'https://api-solicitud-cert.example.com/',
132
+ API_IDENTIDAD: '',
133
+ API_MOTOR: '',
134
+ };
135
+ ```
136
+
137
+ ## Dependencias comunes
138
+
139
+ - **Angular Material** — Componentes UI (`@angular/material`, `@angular/cdk`)
140
+ - **Bootstrap** — Grid y utilidades CSS
141
+ - **ngx-toastr** — Notificaciones toast
142
+ - **RxJS** — Programación reactiva
143
+ - **moment** — Manejo de fechas
144
+ - **STOMP/SockJS** — WebSockets para notificaciones en tiempo real
145
+
146
+ ## Componentes compartidos (`shared/`)
147
+
148
+ Convención: todo patrón que aparezca en **2+ vistas** vive en `@presentation/shared/` (o `@shared/` según convención del proyecto).
149
+
150
+ **Heurística de extracción:** al empezar una vista nueva, escanear `shared/` antes de codear. Si un patrón recurrente aún no está en `shared/`, proponer **extracción explícita con un diff aislado** — no mezclar con el feature nuevo (dos commits separados).
151
+
152
+ **Candidatos típicos:**
153
+
154
+ - `readonly-input` — input + candado + fondo atenuado.
155
+ - `section-card` — wrapper con section-title + icono + contenido.
156
+ - `switch-aligned` — switch con label alineado verticalmente.
157
+ - `combo-hint` — select + hint muted debajo.
158
+ - `primary-button-spinner` — botón de acción con estado de loading.
159
+
160
+ **Regla para el asistente:** al implementar un patrón del skill `frontend-design` en código, primero `grep`/`glob` por nombres similares en `shared/`; si existe, usar; si no, preguntar al usuario si vale extraerlo antes de inline-ar.
161
+
162
+ ## Framework-first CSS
163
+
164
+ Aplicar el principio ~90/10 documentado en `frontend-design` (§11): utilities del framework primero, CSS custom sólo cuando el framework no da la variante o la combinación se repite 5+ veces y amerita una clase semántica.
165
+
166
+ En este monorepo: **SCSS + Bootstrap + Angular Material**. Regla práctica:
167
+
168
+ - **Spacing / flex / grid / tipografía / colores semánticos** → utilities Bootstrap (`p-3`, `d-flex align-items-center gap-2`, `text-muted small`, `fw-bold`, `text-danger`).
169
+ - **Componentes complejos** (autocomplete, datepicker, dialog) → Angular Material.
170
+ - **SCSS custom** reservado para **tema**: colores del sistema (en secciones específicas), dimensiones custom de switch (3em×1.5em), tema de readonly (fondo atenuado con candado).
171
+
172
+ **Anti-patrón:** reescribir `.my-card { border: 1px solid; padding: 1rem; box-shadow: ... }` cuando `border rounded-3 shadow-sm p-3` lo resuelve.
173
+
174
+ **Criterio práctico:** antes de escribir una regla CSS custom, revisar utilities del framework. Si no existe la utility, evaluar si el tema aplicará a 3+ lugares antes de crear clase.
175
+
176
+ ## Build
177
+
178
+ - Producción: `npm run build:prod` → `ng build -c=production`
179
+ - Desarrollo: `npm run build:dev` → `ng build -c=development`
180
+ - Serve local: `npm run start:dev` → `ng serve -c=development`
181
+ - Tests: `ng test --watch=false`
182
+ - Estilos: SCSS