@imolko/ultra-agent 0.1.0-beta

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 (239) hide show
  1. package/README.md +93 -0
  2. package/bin/cli.js +2 -0
  3. package/dist-node/bin.d.ts +2 -0
  4. package/dist-node/bin.d.ts.map +1 -0
  5. package/dist-node/bin.js +5 -0
  6. package/dist-node/bin.js.map +1 -0
  7. package/dist-node/cli.d.ts +41 -0
  8. package/dist-node/cli.d.ts.map +1 -0
  9. package/dist-node/cli.js +170 -0
  10. package/dist-node/cli.js.map +1 -0
  11. package/dist-node/index.d.ts +14 -0
  12. package/dist-node/index.d.ts.map +1 -0
  13. package/dist-node/index.js +40 -0
  14. package/dist-node/index.js.map +1 -0
  15. package/dist-node/init-lint.d.ts +43 -0
  16. package/dist-node/init-lint.d.ts.map +1 -0
  17. package/dist-node/init-lint.js +84 -0
  18. package/dist-node/init-lint.js.map +1 -0
  19. package/dist-node/manifest.d.ts +33 -0
  20. package/dist-node/manifest.d.ts.map +1 -0
  21. package/dist-node/manifest.js +59 -0
  22. package/dist-node/manifest.js.map +1 -0
  23. package/dist-node/materializer.d.ts +52 -0
  24. package/dist-node/materializer.d.ts.map +1 -0
  25. package/dist-node/materializer.js +194 -0
  26. package/dist-node/materializer.js.map +1 -0
  27. package/dist-node/package-root.d.ts +5 -0
  28. package/dist-node/package-root.d.ts.map +1 -0
  29. package/dist-node/package-root.js +17 -0
  30. package/dist-node/package-root.js.map +1 -0
  31. package/dist-node/payload.d.ts +22 -0
  32. package/dist-node/payload.d.ts.map +1 -0
  33. package/dist-node/payload.js +49 -0
  34. package/dist-node/payload.js.map +1 -0
  35. package/dist-node/pointer-hub.d.ts +22 -0
  36. package/dist-node/pointer-hub.d.ts.map +1 -0
  37. package/dist-node/pointer-hub.js +50 -0
  38. package/dist-node/pointer-hub.js.map +1 -0
  39. package/dist-node/publication.cli.d.ts +9 -0
  40. package/dist-node/publication.cli.d.ts.map +1 -0
  41. package/dist-node/publication.cli.js +17 -0
  42. package/dist-node/publication.cli.js.map +1 -0
  43. package/dist-node/publication.d.ts +23 -0
  44. package/dist-node/publication.d.ts.map +1 -0
  45. package/dist-node/publication.js +47 -0
  46. package/dist-node/publication.js.map +1 -0
  47. package/dist-node/reconcile.cli.d.ts +11 -0
  48. package/dist-node/reconcile.cli.d.ts.map +1 -0
  49. package/dist-node/reconcile.cli.js +39 -0
  50. package/dist-node/reconcile.cli.js.map +1 -0
  51. package/dist-node/reconcile.d.ts +30 -0
  52. package/dist-node/reconcile.d.ts.map +1 -0
  53. package/dist-node/reconcile.js +51 -0
  54. package/dist-node/reconcile.js.map +1 -0
  55. package/dist-node/ship/prompts/fix.md +22 -0
  56. package/dist-node/ship/prompts/implement.md +34 -0
  57. package/dist-node/ship/prompts/review.md +28 -0
  58. package/dist-node/ship/ship.agent.d.ts +22 -0
  59. package/dist-node/ship/ship.agent.d.ts.map +1 -0
  60. package/dist-node/ship/ship.agent.js +142 -0
  61. package/dist-node/ship/ship.agent.js.map +1 -0
  62. package/dist-node/ship/ship.args.d.ts +15 -0
  63. package/dist-node/ship/ship.args.d.ts.map +1 -0
  64. package/dist-node/ship/ship.args.js +93 -0
  65. package/dist-node/ship/ship.args.js.map +1 -0
  66. package/dist-node/ship/ship.context.d.ts +12 -0
  67. package/dist-node/ship/ship.context.d.ts.map +1 -0
  68. package/dist-node/ship/ship.context.js +3 -0
  69. package/dist-node/ship/ship.context.js.map +1 -0
  70. package/dist-node/ship/ship.d.ts +4 -0
  71. package/dist-node/ship/ship.d.ts.map +1 -0
  72. package/dist-node/ship/ship.js +221 -0
  73. package/dist-node/ship/ship.js.map +1 -0
  74. package/dist-node/ship/ship.mr.d.ts +9 -0
  75. package/dist-node/ship/ship.mr.d.ts.map +1 -0
  76. package/dist-node/ship/ship.mr.js +171 -0
  77. package/dist-node/ship/ship.mr.js.map +1 -0
  78. package/dist-node/ship/ship.output.d.ts +9 -0
  79. package/dist-node/ship/ship.output.d.ts.map +1 -0
  80. package/dist-node/ship/ship.output.js +21 -0
  81. package/dist-node/ship/ship.output.js.map +1 -0
  82. package/dist-node/ship/ship.tracker.d.ts +37 -0
  83. package/dist-node/ship/ship.tracker.d.ts.map +1 -0
  84. package/dist-node/ship/ship.tracker.js +220 -0
  85. package/dist-node/ship/ship.tracker.js.map +1 -0
  86. package/dist-node/version.cli.d.ts +9 -0
  87. package/dist-node/version.cli.d.ts.map +1 -0
  88. package/dist-node/version.cli.js +30 -0
  89. package/dist-node/version.cli.js.map +1 -0
  90. package/dist-node/version.d.ts +24 -0
  91. package/dist-node/version.d.ts.map +1 -0
  92. package/dist-node/version.js +76 -0
  93. package/dist-node/version.js.map +1 -0
  94. package/docs/adr/ADR-0000-proceso-y-formato-de-adrs.md +115 -0
  95. package/docs/adr/foundational/A-001-clean-architecture-4-capas.md +88 -0
  96. package/docs/adr/foundational/A-002-cqrs-semantico.md +58 -0
  97. package/docs/adr/foundational/A-003-tdd.md +97 -0
  98. package/docs/adr/foundational/A-005-either-return-custom-methods.md +80 -0
  99. package/docs/adr/foundational/A-006-feature-completion-criteria.md +47 -0
  100. package/docs/adr/foundational/A-007-data-contract-fail-fast.md +109 -0
  101. package/docs/adr/foundational/A-008-bounded-context-decomposition.md +130 -0
  102. package/docs/adr/foundational/A-009-use-case-taxonomy.md +99 -0
  103. package/docs/adr/foundational/A-010-propiedad-emision-eventos-dominio.md +95 -0
  104. package/docs/adr/foundational/A-011-characterization-first-refactoring.md +90 -0
  105. package/docs/adr/foundational/A-012-helm-mecanismo-primario-despliegue.md +67 -0
  106. package/docs/adr/foundational/A-013-contrato-settings-unica-fuente-configuracion.md +74 -0
  107. package/docs/adr/foundational/A-014-generacion-artefactos-despliegue-desde-contrato-settings.md +75 -0
  108. package/docs/adr/foundational/A-015-cloudevents-estandar-eventos.md +85 -0
  109. package/docs/adr/foundational/A-016-cicd-gitlab-pipeline-raiz-pipelines-modulares.md +92 -0
  110. package/docs/adr/foundational/A-017-taxonomia-repositorios-librerias-sistemas.md +93 -0
  111. package/docs/adr/foundational/A-018-practicas-build-imagenes-docker.md +85 -0
  112. package/docs/adr/foundational/A-019-convenciones-autoria-helm-charts.md +97 -0
  113. package/docs/adr/foundational/A-020-entorno-desarrollo-estandarizado-devcontainer.md +58 -0
  114. package/docs/adr/foundational/A-022-formato-reporte-tests-ctrf.md +55 -0
  115. package/docs/adr/foundational/A-023-composicion-bloques-prompt-agentes.md +65 -0
  116. package/docs/adr/foundational/A-024-features-slices-verticales-portables.md +41 -0
  117. package/docs/adr/foundational/A-025-anatomia-mecanica-feature-puertos-adaptadores-drivers.md +104 -0
  118. package/docs/adr/foundational/A-026-infraestructura-compartida.md +44 -0
  119. package/docs/adr/foundational/A-027-patron-wiring-entry-point.md +67 -0
  120. package/docs/adr/foundational/A-029-verbos-intencion-metodos-lado-negocio.md +54 -0
  121. package/docs/adr/foundational/A-030-global-development-tooling.md +52 -0
  122. package/docs/adr/foundational/A-031-ubiquitous-language.md +64 -0
  123. package/docs/adr/foundational/A-032-domain-artifact-documentation-format.md +128 -0
  124. package/docs/adr/foundational/A-033-estandar-mensajes-commit.md +127 -0
  125. package/docs/adr/foundational/A-034-canonical-skill-set.md +64 -0
  126. package/docs/adr/foundational/A-035-captura-ideas-reanclaje-candies.md +51 -0
  127. package/docs/adr/foundational/A-036-adopcion-wayfinder-ortogonalidad-labels.md +37 -0
  128. package/docs/adr/foundational/A-037-formalizacion-taxonomia-labels.md +98 -0
  129. package/docs/adr/foundational/A-038-issues-referencian-skills-nombre.md +54 -0
  130. package/docs/adr/foundational/A-039-pipeline-ship-issues-hijos-spec.md +64 -0
  131. package/docs/adr/foundational/A-040-punteros-configuracion-repo-skills.md +44 -0
  132. package/docs/adr/foundational/A-041-estrategia-de-ramas.md +45 -0
  133. package/docs/adr/foundational/A-042-formato-documentos-issue-tracker.md +78 -0
  134. package/docs/adr/foundational/A-043-vocabulario-etiquetas-adrs.md +42 -0
  135. package/docs/adr/foundational/A-044-composicion-funcional-procesos-operaciones.md +44 -0
  136. package/docs/adr/foundational/A-045-guardrails-aplicables-no-directrices.md +48 -0
  137. package/docs/adr/foundational/A-046-metricas-de-forma-y-legibilidad-del-codigo.md +50 -0
  138. package/docs/adr/foundational/A-047-dependencias-explicitas-sin-globales-ambientales.md +40 -0
  139. package/docs/adr/foundational/A-048-cobertura-minima-codigo.md +39 -0
  140. package/docs/adr/foundational/A-049-materializacion-bucle-guardrails-extension-nativa-pi.md +49 -0
  141. package/docs/adr/foundational/A-050-el-caso-de-uso-pide-al-dominio-no-lee-su-representacion.md +50 -0
  142. package/docs/adr/foundational/A-051-orden-imports-por-distancia.md +47 -0
  143. package/docs/adr/foundational/A-052-distribucion-metodologia-paquete-versionado.md +42 -0
  144. package/docs/adr/foundational/A-053-errores-compartidos-entre-features-dos-hogares-por-capa.md +43 -0
  145. package/docs/adr/foundational/A-054-contrato-costura-driver-port-raw-data-canal-error.md +65 -0
  146. package/docs/adr/foundational/index.md +98 -0
  147. package/docs/adr/index.md +19 -0
  148. package/docs/adr/python/P-001-dependencias-por-feature-fastapi-depends.md +63 -0
  149. package/docs/adr/python/P-002-inyeccion-token-por-request-sin-persistirlo.md +35 -0
  150. package/docs/adr/python/P-003-sqlalchemy-async-connection-pooling.md +59 -0
  151. package/docs/adr/python/P-004-serializer-json-custom-modelos-pydantic.md +47 -0
  152. package/docs/adr/python/P-005-patrones-pitfalls-nicegui.md +148 -0
  153. package/docs/adr/python/P-006-convenciones-pytest.md +96 -0
  154. package/docs/adr/python/P-007-ci-python-alineacion-poetry-version-unica.md +55 -0
  155. package/docs/adr/python/P-008-empaquetado-infraestructura-compartida-por-tecnologia.md +38 -0
  156. package/docs/adr/python/index.md +14 -0
  157. package/docs/adr/typescript/T-001-ddd-artifact-validation-zod-primitives.md +136 -0
  158. package/docs/adr/typescript/T-002-test-documentation-jsdoc.md +133 -0
  159. package/docs/adr/typescript/T-003-readme-formatting-domain-artifacts.md +51 -0
  160. package/docs/adr/typescript/T-005-input-optionality-use-case-not-entity.md +130 -0
  161. package/docs/adr/typescript/T-006-small-enums-inlined-zod-regex.md +77 -0
  162. package/docs/adr/typescript/T-007-controller-input-zod-schema.md +79 -0
  163. package/docs/adr/typescript/T-008-expressive-use-case-pipe.md +207 -0
  164. package/docs/adr/typescript/T-009-mdx-brace-escaping.md +80 -0
  165. package/docs/adr/typescript/T-010-stack-tooling-typescript-dominio.md +53 -0
  166. package/docs/adr/typescript/T-011-ultra-reporter-herramienta-canonica-documentacion.md +52 -0
  167. package/docs/adr/typescript/T-012-npm-workspaces-estructura-monorepo-clean-architecture.md +54 -0
  168. package/docs/adr/typescript/T-013-definicion-eventos-versionados-ultra-ddd.md +45 -0
  169. package/docs/adr/typescript/T-014-publicacion-distribucion-librerias-npm-semver.md +53 -0
  170. package/docs/adr/typescript/T-015-method-placement-definition.md +35 -0
  171. package/docs/adr/typescript/T-016-contrato-settings-zod.md +34 -0
  172. package/docs/adr/typescript/T-017-characterization-tests-golden-files.md +39 -0
  173. package/docs/adr/typescript/T-018-procedencia-campos-frontmatter.md +55 -0
  174. package/docs/adr/typescript/T-019-ultra-generator-herramienta-canonica-generacion.md +35 -0
  175. package/docs/adr/typescript/T-020-ultra-settings-herramienta-canonica-exportacion-despliegue.md +36 -0
  176. package/docs/adr/typescript/T-021-pipe-flujo-datos-operadores-semantica-contexto-inmutable.md +105 -0
  177. package/docs/adr/typescript/T-022-construction-is-execution-single-boundary.md +112 -0
  178. package/docs/adr/typescript/T-023-registry-cli-declara-dependencias-reales.md +84 -0
  179. package/docs/adr/typescript/T-024-paquete-ultra-agent-manifiesto-pi-peers-cli.md +39 -0
  180. package/docs/adr/typescript/T-025-publicacion-npm-trusted-publishing-procedencia.md +59 -0
  181. package/docs/adr/typescript/index.md +30 -0
  182. package/eslint/index.mjs +721 -0
  183. package/package.json +94 -0
  184. package/pi/extensions/handoff/README.md +92 -0
  185. package/pi/extensions/handoff/handoff-prompt.txt +9 -0
  186. package/pi/extensions/handoff/index.ts +296 -0
  187. package/pi/extensions/handoff/package.json +12 -0
  188. package/pi/extensions/qa-guardrail/README.md +108 -0
  189. package/pi/extensions/qa-guardrail/adapters/cli.ts +100 -0
  190. package/pi/extensions/qa-guardrail/adapters/eslint.ts +90 -0
  191. package/pi/extensions/qa-guardrail/adapters/registry.ts +45 -0
  192. package/pi/extensions/qa-guardrail/baseline.ts +74 -0
  193. package/pi/extensions/qa-guardrail/cerco.ts +134 -0
  194. package/pi/extensions/qa-guardrail/check.ts +185 -0
  195. package/pi/extensions/qa-guardrail/config.ts +189 -0
  196. package/pi/extensions/qa-guardrail/delta.ts +52 -0
  197. package/pi/extensions/qa-guardrail/feedback.ts +26 -0
  198. package/pi/extensions/qa-guardrail/index.ts +311 -0
  199. package/pi/extensions/qa-guardrail/nstop.ts +82 -0
  200. package/pi/extensions/qa-guardrail/package.json +12 -0
  201. package/pi/extensions/qa-guardrail/selection.ts +98 -0
  202. package/pi/extensions/qa-guardrail/types.ts +64 -0
  203. package/scripts/copy-assets.sh +10 -0
  204. package/scripts/reconcile-tags.sh +94 -0
  205. package/scripts/release-beta.sh +64 -0
  206. package/scripts/release-build.sh +53 -0
  207. package/scripts/release.sh +51 -0
  208. package/scripts/verify-adr-consistency.py +217 -0
  209. package/skills/code-review/SKILL.md +66 -0
  210. package/skills/codebase-design/SKILL.md +46 -0
  211. package/skills/configure-repo/SKILL.md +33 -0
  212. package/skills/diagnose-bug/SKILL.md +63 -0
  213. package/skills/domain-modeling/SKILL.md +56 -0
  214. package/skills/grill-me/SKILL.md +34 -0
  215. package/skills/i-have-an-idea/SKILL.md +166 -0
  216. package/skills/implement/SKILL.md +22 -0
  217. package/skills/research/SKILL.md +17 -0
  218. package/skills/ship/SKILL.md +26 -0
  219. package/skills/spike/SKILL.md +27 -0
  220. package/skills/tdd/SKILL.md +68 -0
  221. package/skills/tdd/references/deep-modules.md +53 -0
  222. package/skills/tdd/references/interface-design.md +74 -0
  223. package/skills/tdd/references/mocking.md +80 -0
  224. package/skills/tdd/references/refactoring.md +49 -0
  225. package/skills/tdd/references/tests.md +184 -0
  226. package/skills/to-specs/SKILL.md +141 -0
  227. package/skills/to-tasks/SKILL.md +143 -0
  228. package/skills/triage/SKILL.md +73 -0
  229. package/skills/ultra-generator/SKILL.md +263 -0
  230. package/skills/ultra-generator/references/aggregate-root.md +149 -0
  231. package/skills/ultra-generator/references/domain-event.md +174 -0
  232. package/skills/ultra-generator/references/entity.md +133 -0
  233. package/skills/ultra-generator/references/service.md +92 -0
  234. package/skills/ultra-generator/references/value-object.md +135 -0
  235. package/skills/wayfinder/SKILL.md +201 -0
  236. package/skills/workflow/SKILL.md +31 -0
  237. package/skills/writing-for-agents/SKILL-MECHANICS.md +32 -0
  238. package/skills/writing-for-agents/SKILL.md +86 -0
  239. package/skills/writing-for-agents/references/adrs.md +19 -0
@@ -0,0 +1,207 @@
1
+ # T-008: El pipe del caso de uso expresa el proceso con funciones nombradas
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-05-27
6
+ **originally**: imolko
7
+
8
+ ## Contexto
9
+
10
+ Un caso de uso funcional se escribe como pipeline de composición funcional: en el ecosistema ultra-ddd ([T-010](./T-010-stack-tooling-typescript-dominio.md)), `seedTV(input).pipe(...)` encadena los pasos del proceso. La lógica de validación y ejecución puede escribirse directamente como lambdas inline dentro del pipe:
11
+
12
+ ```typescript
13
+ // ❌ LAMBDAS INLINE: difícil de leer
14
+ const process = seedTV(input).pipe(
15
+ TV.checkRequirements([
16
+ TV.fromAsync(async (inp: InputDto): Promise<Validation<...>> => {
17
+ // 15-20 líneas de validación de warehouse...
18
+ }),
19
+ TV.fromAsync(async (inp: InputDto): Promise<Validation<...>> => {
20
+ // 30-40 líneas de validación de variantes...
21
+ }),
22
+ (inp: InputDto): TaskValidation<...> => {
23
+ // validación de cantidades...
24
+ },
25
+ (inp: InputDto): TaskValidation<...> => {
26
+ // validación de documentos...
27
+ },
28
+ ]),
29
+ TV.chain((results) => {
30
+ // combinación de resultados...
31
+ }),
32
+ TE.executeSequentially([
33
+ (ctx: PipelineContext): TaskExecution<...> => {
34
+ return () => this.executeCoreAsync(ctx);
35
+ },
36
+ ]),
37
+ TE.when({ isOk: handleSuccess, isFail: handleFailure }),
38
+ TE.map(returnVoid),
39
+ );
40
+ ```
41
+
42
+ Este estilo tiene dos problemas:
43
+
44
+ 1. **El significado del proceso queda enterrado**: para entender qué hace el pipe, hay que leer el cuerpo de cada función inline. Las lambdas no comunican intención.
45
+ 2. **El pipe ocupa 60-80 líneas**: la mezcla de lógica de negocio con la estructura del pipeline hace que el `execute()` sea difícil de navegar y revisar.
46
+
47
+ El objetivo de `seedTV(input).pipe(...)` es declarar el proceso de negocio de forma legible, siguiendo el estilo de composición funcional de [A-044](../foundational/A-044-composicion-funcional-procesos-operaciones.md). Las lambdas inline derrotan ese propósito.
48
+
49
+ ## Decisión
50
+
51
+ Cada paso del pipe debe extraerse a una **función nombrada con un nombre semántico** que describa qué hace ese paso en el proceso de negocio. La función se declara como `const` dentro de `execute()`, antes del pipe.
52
+
53
+ ### Reglas
54
+
55
+ | Regla | Descripción |
56
+ |-------|-------------|
57
+ | **Una función por paso del proceso** | Cada validador, transformación, y ejecución va en su propia función nombrada |
58
+ | **Nombre semántico** | El nombre describe **qué hace el paso en el proceso de negocio**, no cómo lo hace. Ej: `verifyWarehouseExists`, no `checkWarehouseId` |
59
+ | **Idioma inglés** | Los nombres de funciones van en inglés, consistente con el resto del código del ecosistema |
60
+ | **JSDoc descriptivo** | Cada función nombrada lleva un JSDoc de una línea explicando su rol en el proceso (extiende el JSDoc de [T-002](./T-002-test-documentation-jsdoc.md) a las funciones del pipe, en formato simplificado sin tags) |
61
+ | **El pipe es solo estructura** | El pipe contiene únicamente referencias a las funciones nombradas — sin lambdas, sin cuerpos de función |
62
+ | **Declarar antes del pipe** | Las funciones se declaran como `const` al inicio del `execute()`, antes del `const process = seedTV(...).pipe(...)` |
63
+ | **Validación vs ejecución** | Los pasos que solo leen y deciden son `TaskValidation` (`TV.*`); los que cambian estado son `TaskExecution` (`TE.*`). `TE.startExecutions()` es la única frontera entre ambas fases. |
64
+ | **El puerto fija la fase** | Un método de puerto de dominio que lee o verifica se declara `TaskValidation`/`Validation`; uno que muta, `TaskExecution`/`Execution` ([A-025](../foundational/A-025-anatomia-mecanica-feature-puertos-adaptadores-drivers.md)). El compilador impide ejecutar una lectura como mutación. |
65
+
66
+ ### Ejemplo canónico
67
+
68
+ ```typescript
69
+ public execute(input: InputDto): TaskExecution<Errors, void> {
70
+ /** Lo que sucede cuando el proceso completa exitosamente */
71
+ const handleSuccess = () => {
72
+ this.setResult(ok(undefined));
73
+ };
74
+ /** Lo que sucede cuando el proceso falla en cualquier etapa */
75
+ const handleFailure = (errors: Errors[]) => {
76
+ this.setResult(fail(errors));
77
+ };
78
+ /** Convierte el resultado del pipe a void para cumplir el contrato */
79
+ const returnVoid = (): void => undefined;
80
+
81
+ /** Verifica que el warehouse existe en el sistema */
82
+ const verifyWarehouseExists = TV.fromAsync(async (input: InputDto) => {
83
+ // lógica de validación...
84
+ });
85
+
86
+ /** Verifica que todas las variantes de producto y sus productos padre existen */
87
+ const verifyProductVariantsExist = TV.fromAsync(async (input: InputDto) => {
88
+ // lógica de validación...
89
+ });
90
+
91
+ /** Verifica que todas las cantidades sean mayores a cero */
92
+ const verifyQuantitiesPositive = (input: InputDto): TaskValidation<...> => {
93
+ // lógica de validación...
94
+ };
95
+
96
+ /** Verifica que los documentos adjuntos tengan datos válidos */
97
+ const verifyDocumentsValid = (input: InputDto): TaskValidation<...> => {
98
+ // lógica de validación...
99
+ };
100
+
101
+ /** Combina los resultados individuales de validación en un solo contexto */
102
+ const combineValidationResults = (results: any[]) => {
103
+ // lógica de combinación...
104
+ };
105
+
106
+ /** Ejecuta el core: resuelve lotes, construye StockMovement, persiste */
107
+ const executeRegistration = (ctx: PipelineContext): TaskExecution<...> => {
108
+ return () => this.executeCoreAsync(ctx);
109
+ };
110
+
111
+ // ── El pipe declara el proceso, no lo implementa ──
112
+ const process = seedTV(input).pipe(
113
+ TV.checkRequirements([
114
+ verifyWarehouseExists,
115
+ verifyProductVariantsExist,
116
+ verifyQuantitiesPositive,
117
+ verifyDocumentsValid,
118
+ ]),
119
+ TV.chain(combineValidationResults),
120
+ TE.startExecutions(),
121
+ TE.executeSequentially([executeRegistration]),
122
+ TE.when({ isOk: handleSuccess, isFail: handleFailure }),
123
+ TE.map(returnVoid),
124
+ );
125
+
126
+ return process as TaskExecution<Errors, void>;
127
+ }
128
+ ```
129
+
130
+ ### Validación antes que ejecución: la frontera del pipe
131
+
132
+ `seedTV(input).pipe(...)` tiene dos fases separadas por una única frontera:
133
+
134
+ - **Validación** (`TV.*`) — lee y decide; no toca estado. Ejemplos: `verifyWarehouseExists`, `verifyQuantitiesPositive`, `verifyNoOpenClaimExists`. Retornan `TaskValidation` con `valid(ctx)`/`invalid([...])`.
135
+ - **Frontera** — `TE.startExecutions()` convierte la `TaskValidation` en `TaskExecution`. No hay otra transición entre fases.
136
+ - **Ejecución** (`TE.*`) — cambia estado: persiste, publica eventos, muta el contexto. Retornan `TaskExecution` con `ok(...)`/`fail([...])`.
137
+
138
+ La fase no la decide quien escribe el caso de uso: la decide el **tipo del puerto** ([A-025](../foundational/A-025-anatomia-mecanica-feature-puertos-adaptadores-drivers.md)). Una verificación de solo lectura tipada como `TaskExecution` arrastra la lectura a la fase de ejecución; tipada como `TaskValidation`, el compilador impide colocarla en `TE.executeSequentially` y solo permite componerla en la fase de validación.
139
+
140
+ ❌ Incorrecto — la lectura se declara como ejecución:
141
+
142
+ ```typescript
143
+ // claim-repository.port.ts
144
+ verifyNoOpenClaim(referenceId: string): TaskExecution<Errors, void>;
145
+
146
+ // use-case.ts — la verificación queda en la fase de ejecución
147
+ TE.executeSequentially([this.verifyNoOpenClaimExists]),
148
+ ```
149
+
150
+ ✅ Correcto — el puerto declara la lectura como validación:
151
+
152
+ ```typescript
153
+ // claim-repository.port.ts
154
+ verifyNoOpenClaim(referenceId: string): TaskValidation<Errors, void>;
155
+
156
+ // use-case.ts — la verificación compone en la fase de validación
157
+ TV.chain(this.verifyNoOpenClaimExists),
158
+ ```
159
+
160
+ Convención de refuerzo: los nombres `verify*` corresponden a `TaskValidation` (fase `TV`) y `execute*` a `TaskExecution` (fase `TE`).
161
+
162
+ La semántica de flujo del valor a través del pipe — `chain` produce, `sequence` acumula, y el contexto se retorna en lugar de mutarse — la fija [T-021](./T-021-pipe-flujo-datos-operadores-semantica-contexto-inmutable.md).
163
+
164
+ Qué cuenta como validación (lectura/verificación) frente a ejecución (creación/mutación) — en particular, que la construcción de objetos es ejecución y que `TE.startExecutions()` es la única frontera — lo fija [T-022](./T-022-construction-is-execution-single-boundary.md).
165
+
166
+ ### Lo que se lee en el pipe
167
+
168
+ El pipe ahora comunica el proceso de negocio de un vistazo:
169
+
170
+ 1. **Verificar** que el warehouse existe
171
+ 2. **Verificar** que las variantes de producto existen
172
+ 3. **Verificar** que las cantidades son válidas
173
+ 4. **Verificar** que los documentos son válidos
174
+ 5. **Combinar** los resultados de validación
175
+ 6. **Ejecutar** el registro
176
+ 7. **Manejar** éxito o fallo
177
+
178
+ Un experto del dominio puede leer solo el pipe y entender el flujo completo sin ver una sola línea de implementación. Las funciones nombradas también hacen explícito dónde ocurre la resolución de opcionalidad que fija [T-005](./T-005-input-optionality-use-case-not-entity.md).
179
+
180
+ ### Criterios para extraer una función
181
+
182
+ Una lambda dentro del pipe debe extraerse a función nombrada si:
183
+
184
+ - Tiene **más de 3 líneas** de lógica
185
+ - Representa un **paso del proceso de negocio** con identidad propia (ej: "validar warehouse" vs "parsear un campo")
186
+ - Su lógica podría **reutilizarse** o **testearse de forma aislada**
187
+
188
+ No es necesario extraer:
189
+
190
+ - Funciones puramente técnicas como `returnVoid` o `handleSuccess` (ya tienen nombre)
191
+ - Lambdas de una línea que son adaptadores de tipo triviales
192
+
193
+ ## Consecuencias
194
+
195
+ ### Positivas
196
+
197
+ - **Legibilidad**: cualquier persona (desarrollador, experto del dominio, agente de código) puede leer el pipe y entender el proceso en segundos
198
+ - **Navegabilidad**: el pipe tiene ~15 líneas de estructura. La implementación de cada paso está en su función correspondiente, que se puede colapsar en el editor
199
+ - **Modificabilidad**: agregar un paso nuevo (ej: una validación adicional) es tan simple como declarar una función nueva y agregar su referencia al array correspondiente — el pipe no se desordena
200
+ - **Testabilidad**: las funciones de validación pueden extraerse a métodos privados de la clase si se necesita testeo aislado
201
+ - **Documentación viva**: el pipe es documentación ejecutable. Hace innecesarios los comentarios `// Fase 1: Validaciones` porque las funciones mismas documentan el paso
202
+
203
+ ### Negativas
204
+
205
+ - **Paso manual post-generación**: después de ejecutar `add-feature`, el desarrollador o agente debe refactorizar las lambdas inline a funciones nombradas. Se mitiga con el `.instructions.md` post-generación, que ultra-generator deja como instrucción para el agente o desarrollador ([T-003](./T-003-readme-formatting-domain-artifacts.md)), y con un futuro cambio en ultra-generator
206
+ - **Mayor número de líneas en `execute()`**: las declaraciones de funciones antes del pipe agregan líneas. En la práctica es beneficioso porque cada función encapsula su complejidad — el método `execute()` se vuelve más largo pero más navegable
207
+ - **Nombres en inglés**: el dominio y los README están en español, pero las funciones del pipe van en inglés para consistencia con el resto del código del ecosistema. Esto crea una mezcla de idiomas en el mismo archivo (JSDoc en español, nombres de función en inglés)
@@ -0,0 +1,80 @@
1
+ # T-009: Escape de llaves en contenido generado para MDX/Docusaurus
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-06-03
6
+ **originally**: imolko
7
+
8
+ ## Contexto
9
+
10
+ `ultra-reporter build` (herramienta canónica de documentación: [T-011](./T-011-ultra-reporter-herramienta-canonica-documentacion.md)) genera archivos `.md` a partir del JSDoc de los tests (cuya documentación fija [T-002](./T-002-test-documentation-jsdoc.md)), del JSDoc de propiedades y de los `README.md` de artefactos. Esos archivos se procesan con Docusaurus y soporte MDX, que interpreta `{...}` como expresiones JSX ([MDX: Interpolation](https://mdxjs.com/docs/what-is-mdx/#interpolation)).
11
+
12
+ El JSDoc y los `README.md` pueden contener llaves o ángulos literales — tipos como `{ value: string }` o `Array<{name, value}>` — que, al quedar en texto plano (fuera de code fences) del markdown generado, MDX interpreta como expresiones JSX o tags, y hacen fallar el build con errores de `acorn` o `unexpected character` ([micromark-extension-mdx-expression](https://github.com/micromark/micromark-extension-mdx-expression/tree/main/packages/micromark-extension-mdx-expression#could-not-parse-expression-with-acorn)).
13
+
14
+ ## Decisión
15
+
16
+ ### Regla
17
+
18
+ Toda llave literal (`{` o `}`) o ángulo (`<` o `>`) que aparezca en contenido que `ultra-reporter` incluye en el markdown generado **debe evitarse** usando HTML entities o texto descriptivo.
19
+
20
+ - `{` → `&#123;`
21
+ - `}` → `&#125;`
22
+ - `<` → `&#60;` (cuando aparece junto a texto que podría interpretarse como tag JSX)
23
+ - `>` → `&#62;`
24
+
25
+ ### Dónde aplica
26
+
27
+ La regla cubre todo contenido que `ultra-reporter` incluye en el markdown generado. Ejemplos concretos:
28
+
29
+ | Fuente | Ejemplo de problema | Corrección |
30
+ |--------|---------------------|------------|
31
+ | `@scenario` en JSDoc de tests | `retorna { value: string }` | `retorna &#123; value: string &#125;` |
32
+ | `@description` en JSDoc de propiedades | `el valor debe ser { ... }` | `el valor debe ser &#123; ... &#125;` |
33
+ | `README.md` — tablas, párrafos | `Array<{name, value}>` | `Array&#60;&#123;name, value&#125;&#62;` o texto descriptivo: `object (name, value)` |
34
+ | `README.md` — texto fuera de code fences | `el payload es { id: string }` | `el payload es &#123; id: string &#125;` |
35
+
36
+ > ⚠️ No se acepta el escape con backslash (`\{`). Aunque funciona en texto simple, falla en tablas
37
+ > y en contextos donde MDX interpreta patrones como JSX. Usar siempre HTML entities.
38
+
39
+ ### Dónde NO aplica (seguro sin escapar)
40
+
41
+ | Contexto | Razón |
42
+ |----------|-------|
43
+ | Dentro de ` ```mermaid ` blocks | MDX no procesa el contenido de code fences |
44
+ | Dentro de ` ```typescript ` / ` ``` ` blocks | Misma razón |
45
+ | Código TypeScript fuera de JSDoc | No llega al markdown generado |
46
+ | `@property {Type}` en JSDoc de props.ts | ultra-reporter no incluye anotaciones `@property` en el markdown generado |
47
+
48
+ ### Verificación local
49
+
50
+ Antes de pushear, ejecutar el build de documentación localmente para detectar errores MDX:
51
+
52
+ ```bash
53
+ npm run docs:build
54
+ ```
55
+
56
+ Si el build falla con errores de `acorn` o `unexpected-character`, revisar los archivos generados en `.ultra-reporter/docusaurus/docs/` para localizar el texto problemático.
57
+
58
+ ### Alternativas consideradas
59
+
60
+ | Opción | Evaluación |
61
+ |--------|------------|
62
+ | Desactivar MDX en Docusaurus | ultra-reporter usa MDX por defecto. Cambiar la configuración requeriría modificar el scaffold y perdería funcionalidad (componentes React en docs). |
63
+ | Post-procesar los .md generados | Agregar un paso de escape en el pipeline añade complejidad. Es mejor prevenir en la fuente. |
64
+ | Usar HTML entities (`&#123;`) | **Opción elegida.** Es la forma más robusta: funciona en cualquier contexto MDX (texto, tablas, atributos HTML). La contraparte es menor legibilidad en el source. |
65
+ | Evitar caracteres especiales | **Opción preferida cuando es posible.** En lugar de `Array<{name, value}>` escribir `object (name, value)`. Más limpio y legible que las entities. |
66
+ | Escapar con backslash (`\{`) | **No funciona en todos los contextos.** MDX interpreta `\{` correctamente en texto simple, pero falla dentro de tablas o cerca de patrones que MDX interpreta como JSX (`Array<...>`). El backslash mismo puede ser rechazado como "unexpected character". |
67
+
68
+ ## Consecuencias
69
+
70
+ ### Positivas
71
+
72
+ - **Build de documentación estable**: los errores MDX se detectan y corrigen en la fuente
73
+ - **Regla simple**: `{` y `}` → `&#123;` y `&#125;` en JSDoc y README.md fuera de code fences
74
+ - **Verificable localmente**: `npm run docs:build` atrapa el error antes del CI
75
+
76
+ ### Negativas
77
+
78
+ - **Sin lint automático**: no hay un linter que detecte llaves sin escapar en JSDoc o README.md. La verificación es manual o mediante build local
79
+ - **Carga cognitiva**: los colaboradores deben recordar esta regla al escribir JSDoc y README.md
80
+ - **Regeneración**: si `ultra-generator` (herramienta canónica: [T-019](./T-019-ultra-generator-herramienta-canonica-generacion.md)) regenera un README.md, las correcciones de escape se pierden y deben re-aplicarse (la reconciliación del scaffold la fija [T-003](./T-003-readme-formatting-domain-artifacts.md))
@@ -0,0 +1,53 @@
1
+ # T-010: Stack de tooling TypeScript del dominio (ultra-ddd, ultra-v8n, ultra-result, ultra-tsconfig)
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-12
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ Un dominio escrito en TypeScript que sigue convenciones DDD repite las mismas responsabilidades en cada artefacto: value-objects, entidades, agregados, validación semántica con errores tipados y manejo de resultados sin excepciones. Sin un stack declarado:
12
+
13
+ - Cada workspace podría elegir librerías o versiones distintas para resolver el mismo problema.
14
+ - Un agente o un miembro nuevo no sabe qué librería usar para modelar un agregado, validar un value-object o retornar un error.
15
+ - La configuración estricta del compilador se duplicaría en cada `tsconfig.json` con riesgo de divergencia.
16
+
17
+ Las librerías del ecosistema `@imolko` ya cubren esas responsabilidades y están optimizadas para trabajar juntas. Falta explicitar que forman el stack canónico del dominio.
18
+
19
+ ## Decisión
20
+
21
+ Adoptar un stack fijo de tooling TypeScript del ecosistema `@imolko` para el dominio, compuesto por **ultra-ddd**, **ultra-v8n**, **ultra-result** y **ultra-tsconfig**. Cada librería cubre una responsabilidad del desarrollo DDD y no se sustituye por una alternativa ad-hoc:
22
+
23
+ - **ultra-ddd** provee los artefactos DDD (value-objects, entidades, agregados, eventos de dominio y errores base) que consumen el dominio y los casos de uso.
24
+ - **ultra-v8n** aporta la validación semántica con errores tipados (las invariantes se aplican en la construcción, ver [A-007](../foundational/A-007-data-contract-fail-fast.md)); sus errores built-in son los que usan las primitivas Zod (ver [T-001](./T-001-ddd-artifact-validation-zod-primitives.md)).
25
+ - **ultra-result** provee el patrón Result para manejar errores sin excepciones (ver [A-005](../foundational/A-005-either-return-custom-methods.md)), tanto en operaciones síncronas como asíncronas.
26
+ - **ultra-tsconfig** provee la base de configuración estricta de TypeScript que extienden los `tsconfig.json` del repositorio.
27
+
28
+ La lista concreta de dependencias y sus versiones no se duplica en este ADR: la fuente canónica son los `package.json` del repositorio (raíz y workspaces), que declaran las dependencias `@imolko/*`. Este ADR fija *qué* librerías forman el stack y *por qué*; el `package.json` fija *cuál versión* está en uso.
29
+
30
+ ### Import de Zod y tree-shaking
31
+
32
+ Si el build usa `tsc --build` sin bundler, en runtime Node.js carga el módulo completo y la forma de importar Zod no cambia el tamaño del código compilado; por eso, en ese escenario, el código usa `import { z } from 'zod'` (o `import { z } from '@imolko/ultra-v8n'` en la capa de dominio).
33
+
34
+ Si el código pasa a bundlearse con esbuild, Webpack o Next.js, la forma sí importa: `import { z } from 'zod'` no es tree-shakable en esos bundlers, mientras que `import * as z from 'zod'` sí lo es (ver [zod#4569](https://github.com/colinhacks/zod/pull/4569)). En ese escenario, la convención debe pasar a `import * as z`.
35
+
36
+ ### Alcance del stack
37
+
38
+ El stack describe el tooling del **dominio** y de los casos de uso que operan sobre él. El generador de artefactos (ultra-generator, ver [T-019](./T-019-ultra-generator-herramienta-canonica-generacion.md)), el reportero de documentación (ultra-reporter, ver [T-011](./T-011-ultra-reporter-herramienta-canonica-documentacion.md)) y el exportador de artefactos de despliegue (ultra-settings, ver [T-020](./T-020-ultra-settings-herramienta-canonica-exportacion-despliegue.md)) son piezas separadas del ecosistema, con responsabilidades propias (scaffolding, documentación y exportación de configuración), y no se consideran parte del stack del dominio aunque convivan en el mismo monorepo.
39
+
40
+ ## Consecuencias
41
+
42
+ ### Positivas
43
+
44
+ - **Consistencia entre workspaces**: dominio, features y apps usan las mismas librerías con los mismos patrones.
45
+ - **Configuración estricta compartida**: extender `ultra-tsconfig` evita duplicar la política de compilación en cada workspace.
46
+ - **Descubribilidad**: un agente o un miembro nuevo sabe qué librería corresponde a cada responsabilidad DDD.
47
+ - **Una sola fuente de versiones**: el `package.json` responde "¿qué versión está en uso?" sin que el ADR quede desactualizado al actualizar dependencias.
48
+
49
+ ### Negativas
50
+
51
+ - **Acoplamiento al ecosistema `@imolko`**: migrar fuera de las librerías del stack implica tocar los artefactos del dominio, no solo un `package.json`.
52
+ - **Límite del ADR**: este documento no lista versiones; quien lea debe consultar `package.json` para conocer el estado exacto de las dependencias.
53
+ - **Stack cerrado**: introducir una librería nueva para una responsabilidad ya cubierta es una decisión que debe revisarse contra este ADR.
@@ -0,0 +1,52 @@
1
+ # T-011: ultra-reporter como herramienta canónica de documentación
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-12
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ Un repositorio TypeScript del ecosistema Imolko produce documentación de dos familias de artefactos: los artefactos del dominio (value-objects, entidades, agregados, eventos de dominio y servicios) y los casos de uso (commands y queries). Esa documentación sirve a dos audiencias distintas:
12
+
13
+ - Expertos del dominio, que validan reglas de negocio y escenarios sin leer código.
14
+ - Desarrolladores y agentes, que necesitan descubrir qué existe cada artefacto y cómo se comporta.
15
+
16
+ Sin una herramienta canónica, cada artefacto documenta con su propio formato, los tests no se traducen en casos legibles y no hay un sitio navegable que reúna todo. ultra-reporter ya resuelve ese problema: escanea el código fuente, compone la documentación de cada artefacto desde su `README.md` y sus tests, y publica un sitio Docusaurus.
17
+
18
+ ## Decisión
19
+
20
+ Adoptar **ultra-reporter** como la herramienta canónica de documentación del repositorio. Toda la documentación generada de dominio y de casos de uso sale de ultra-reporter; no se mantiene un generador alternativo ni páginas escritas a mano que dupliquen lo que la herramienta ya produce.
21
+
22
+ La configuración canónica vive en `ultra-reporter.config.json` (raíz del repositorio): define el nombre del sistema, las rutas de origen del dominio y de los casos de uso, y el destino de la documentación. Los comandos del flujo diario viven en los scripts de `package.json`; no se duplican aquí.
23
+
24
+ ### Convenciones que alimentan a ultra-reporter
25
+
26
+ ultra-reporter no impone el contenido: documenta lo que el equipo ya declara siguiendo tres convenciones. Estas son las entradas del pipeline:
27
+
28
+ - [T-002](./T-002-test-documentation-jsdoc.md): las anotaciones JSDoc `@name` y `@scenario` de cada test, junto con el resultado de los tests en formato CTRF ([A-022](../foundational/A-022-formato-reporte-tests-ctrf.md)), son las que ultra-reporter convierte en casos documentados.
29
+ - [A-032](../foundational/A-032-domain-artifact-documentation-format.md): el formato canónico del `README.md` (sin título H1, secciones en español, diagrama Mermaid en Relaciones) es el cuerpo que ultra-reporter concatena. [T-003](./T-003-readme-formatting-domain-artifacts.md) fija la reconciliación del scaffold de `ultra-generator` con ese formato, y [T-018](./T-018-procedencia-campos-frontmatter.md) la procedencia de los campos del frontmatter.
30
+ - La declaración del Bounded Context: ultra-reporter lee el campo `boundedContext` del frontmatter del `README.md` de cada artefacto para agruparlo en la columna "Context"; si falta, usa `domain.name` de `ultra-reporter.config.json` (procedencia de los campos: [T-018](./T-018-procedencia-campos-frontmatter.md)). El campo `domain` de los decoradores `@Register*` es el namespace del registro de ultra-ddd, no el criterio de agrupado. La descomposición en Bounded Contexts es una decisión fundacional (ver [A-008](../foundational/A-008-bounded-context-decomposition.md)); los nombres concretos de cada contexto los define el sistema, no esta convención.
31
+
32
+ ### Enmienda (2026-09-28): el registro de ultra-ddd no es una entrada del pipeline
33
+
34
+ La evaluación posterior contra las fuentes primarias verificó el mecanismo y precisa —sin cambiar— esta decisión:
35
+
36
+ - ultra-reporter descubre los dos catálogos **escaneando carpetas**: el dominio con `track-artifacts.js` (`getArtifacts`) y los casos de uso con `loadUseCaseFolders`. Compone cada página desde el `README.md` y los tests; no lee `DomainDirectory` ni los metadatos de `@Register*`. La `description` del decorador es **origen de autoría** del campo homónimo del frontmatter ([T-018](./T-018-procedencia-campos-frontmatter.md)), no una entrada del pipeline.
37
+ - **No se añade un `@RegisterUseCase` ni un registro de casos de uso al pipeline.** El catálogo documentado sale del escaneo de carpetas; el catálogo ejecutable vive en el manifiesto de la app ([T-023](./T-023-registry-cli-declara-dependencias-reales.md)); el registro de ultra-ddd no tiene consumidor en documentación.
38
+
39
+ ## Consecuencias
40
+
41
+ ### Positivas
42
+
43
+ - **Un solo sitio navegable**: dominio y casos de uso conviven en el mismo sitio Docusaurus, con tablas, filtros y páginas por artefacto.
44
+ - **Documentación viva**: cada test bien anotado se convierte en un caso documentado; no hay dos fuentes de verdad que divergen.
45
+ - **Descubribilidad para agentes y personas nuevas**: la documentación se genera desde el código, así que refleja lo que realmente existe.
46
+ - **Configuración explícita**: `ultra-reporter.config.json` y los scripts de `package.json` son las fuentes canónicas del flujo, sin pasos memorizados.
47
+
48
+ ### Negativas
49
+
50
+ - **Dependencia de las convenciones**: si un test no sigue T-002 o un README no sigue T-003, la página generada queda incompleta; ultra-reporter no lo valida por sí solo.
51
+ - **Generado no versionado**: el sitio generado vive fuera de git; lo que se versiona es la configuración y las fuentes, no el sitio.
52
+ - **Curva de aprendizaje**: el equipo debe conocer el modelo de descubrimiento de ultra-ddd y el formato de frontmatter para que el resultado sea correcto.
@@ -0,0 +1,54 @@
1
+ # T-012: npm workspaces como estructura del monorepo Clean Architecture
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-12
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ Un repositorio TypeScript del ecosistema Imolko sigue Clean Architecture con 4 capas (ver [A-001](../foundational/A-001-clean-architecture-4-capas.md)): dominio, features, shared-infra y apps. Esas capas conviven en un único repositorio y necesitan:
12
+
13
+ - Límites de compilación y de dependencias explícitos entre capas.
14
+ - Tests y build independientes por capa sin reconstruir todo el monorepo.
15
+ - Resolución local de las dependencias internas (`@<proyecto>/*`) durante el desarrollo, sin publicarlas a un registry antes de usarlas.
16
+
17
+ Sin una herramienta de workspaces, el monorepo tendría que resolver dependencias entre carpetas con rutas relativas frágiles o publicar paquetes internos como paso previo a consumirlos.
18
+
19
+ ## Decisión
20
+
21
+ Usar **npm workspaces** como mecanismo de estructuración del monorepo. Cada capa de [A-001](../foundational/A-001-clean-architecture-4-capas.md) que constituye una unidad consumible o desplegable es un workspace: un paquete npm con su propio `package.json`, `tsconfig.json` y tests.
22
+
23
+ ### Correspondencia capa → workspace
24
+
25
+ - **Capa 1 — dominio** corresponde al workspace `domain/`: lo consumen features y apps.
26
+ - **Capa 2 — casos de uso** corresponde al workspace `features/` — o a un workspace por feature cuando su cierre tecnológico lo exige ([A-024](../foundational/A-024-features-slices-verticales-portables.md)): lo consumen las apps.
27
+ - **Capa 4 — apps** corresponde a `apps/<app>/`: una unidad desplegable por workspace.
28
+
29
+ `shared-infra/` (Capa 3 — la infraestructura compartida de [A-026](../foundational/A-026-infraestructura-compartida.md)) es un directorio de agrupación lógica: cada tecnología (`shared-infra/mongo/`, `shared-infra/postgres/`, …) es su propio workspace, con su `package.json` declarando solo las dependencias de esa tecnología.
30
+
31
+ `representations/<protocol>/` (las representaciones de dominio de [A-026](../foundational/A-026-infraestructura-compartida.md)) es igualmente un workspace por protocolo, junto a `shared-infra/`; toda forma de wire que representa un concepto del dominio vive ahí, tenga uno o varios consumidores — los payloads de operación (input/result/filter) viven con su entrypoint.
32
+
33
+ La lista exacta de workspaces vive en el campo `workspaces` del `package.json` raíz, que es la fuente canónica. Este ADR no la duplica: la lista anterior es la *regla de correspondencia* entre capas y workspaces, no una copia de la lista.
34
+
35
+ ### Reglas
36
+
37
+ - Cada workspace declara sus dependencias internas (`@<proyecto>/*`) en su propio `package.json`; npm resuelve las referencias locales mediante el hoisting del monorepo.
38
+ - Un workspace no importa de otro saltándose la dirección de dependencias de [A-001](../foundational/A-001-clean-architecture-4-capas.md) (las dependencias siempre apuntan hacia adentro).
39
+ - El build y los tests se ejecutan por workspace (por ejemplo, `npm run build -w @<proyecto>/domain`) sin arrastrar el monorepo completo.
40
+
41
+ ## Consecuencias
42
+
43
+ ### Positivas
44
+
45
+ - **Límites de compilación alineados con la arquitectura**: cada capa compila y se testea de forma independiente.
46
+ - **Sin herramientas extra**: npm workspaces es nativo de npm, sin Nx, Turborepo ni Lerna.
47
+ - **Resolución local**: las dependencias internas se consumen directamente desde el monorepo sin publicaciones intermedias.
48
+ - **Descubribilidad**: el campo `workspaces` del `package.json` raíz responde "¿qué capas son paquetes?" sin mantener una copia manual.
49
+
50
+ ### Negativas
51
+
52
+ - **Hoisting de npm**: la resolución de dependencias puede ocultar importaciones indebidas entre workspaces; la disciplina de la dirección de dependencias sigue siendo responsabilidad del equipo.
53
+ - **Configuración repetida**: cada workspace mantiene su propio `package.json` y `tsconfig.json`, con la duplicación de setup que eso implica (mitigada por `ultra-tsconfig`, [T-010](./T-010-stack-tooling-typescript-dominio.md)).
54
+ - **`shared-infra/` por tecnología**: cada paquete `shared-infra/<tech>/` compila y se testea como workspace propio; no hay un workspace único que agrupe toda la capa.
@@ -0,0 +1,45 @@
1
+ # T-013: Definición de eventos versionados con ultra-ddd
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-12
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ [A-015](../foundational/A-015-cloudevents-estandar-eventos.md) fija CloudEvents como envolvente de todo evento y la disciplina de versionado de la data: semver, historial append-only y compatibilidad hacia atrás dentro de una misma versión mayor. Esa decisión es agnóstica al lenguaje: dice *qué* reglas debe cumplir la data, no *cómo* se implementa.
12
+
13
+ En TypeScript hace falta el mecanismo concreto que declare, para cada evento de dominio, el esquema versionado de su data y lo valide al producir y leer ocurrencias. ultra-ddd, la librería del stack ([T-010](./T-010-stack-tooling-typescript-dominio.md)), provee ese mecanismo: `ShapeEvolution`.
14
+
15
+ ## Decisión
16
+
17
+ Definir la data de cada evento de dominio con **ultra-ddd y su `ShapeEvolution`**: cada evento declara una historia versionada de esquemas (Zod) que versiona el campo `data` de la ocurrencia, en línea con las reglas de [A-015](../foundational/A-015-cloudevents-estandar-eventos.md).
18
+
19
+ ### Forma del evento
20
+
21
+ Cada evento declara, junto a su definición, una historia versionada de esquemas para su `data`: el esquema inicial, los esquemas de cada versión posterior y el esquema vigente que tipa la data al producir y leer ocurrencias. La lista concreta de eventos del repositorio vive en el dominio; este ADR no la duplica.
22
+
23
+ ### Reglas de versionado
24
+
25
+ La historia de esquemas sigue las reglas de versionado de [A-015](../foundational/A-015-cloudevents-estandar-eventos.md). ultra-ddd las hace cumplir al declarar la historia: cada versión posterior declara su esquema y su migración desde la anterior, y la herramienta rechaza una historia que las viole.
26
+
27
+ ### Correspondencia con CloudEvents
28
+
29
+ La historia de esquemas se integra con la envolvente CloudEvents de [A-015](../foundational/A-015-cloudevents-estandar-eventos.md):
30
+
31
+ - La ocurrencia lleva la versión en el campo de versión dentro de la data que A-015 permite, junto con la `data` validada contra el esquema de esa versión.
32
+ - Al producir, la data se valida contra el esquema vigente; al leer, la ocurrencia se reconstruye desde un CloudEvent serializado.
33
+ - Los esquemas versionados quedan expuestos como `dataschema` (la URI versionada que A-015 declara) para publicarlos en un registry de eventos.
34
+
35
+ ## Consecuencias
36
+
37
+ ### Positivas
38
+
39
+ - **Una sola fuente del esquema**: el esquema versionado es a la vez esquema de validación, tipo TypeScript y documentación.
40
+ - **Validación automática**: la historia de versiones queda validada por la herramienta al declararla, sin revisión manual de semver.
41
+ - **Alineado con A-015**: la implementación TypeScript materializa las reglas agnósticas del estándar sin redefinirlas.
42
+
43
+ ### Negativas
44
+
45
+ - **Acoplamiento a ultra-ddd**: el mecanismo de versionado es parte del stack de tooling; migrar a otra librería implicaría reescribir las historias de esquemas.
@@ -0,0 +1,53 @@
1
+ # T-014: Publicación y distribución de librerías TypeScript con npm y semver
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-12
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ Imolko produce librerías TypeScript reutilizables (ver [A-017](../foundational/A-017-taxonomia-repositorios-librerias-sistemas.md)) que otros repositorios consumen como dependencias. Para que una librería sea consumible hacen falta tres cosas:
12
+
13
+ - Un mecanismo de publicación que la haga instalable mediante `npm install`.
14
+ - Un esquema de versionado que comunique compatibilidad entre versiones.
15
+ - Un flujo reproducible que calcule la versión, publique el paquete y etiquete el commit correspondiente.
16
+
17
+ Sin una política escrita, cada repositorio decide cómo publicar y versionar, lo que produce paquetes sin canal beta, versiones ad-hoc y publicaciones irreproducibles.
18
+
19
+ ## Decisión
20
+
21
+ Publicar y distribuir las librerías TypeScript con **npm** como mecanismo de publicación y **semver** (`major.minor.patch`) como esquema de versionado.
22
+
23
+ ### npm como mecanismo de publicación
24
+
25
+ - Los paquetes se publican en el registry público de npm bajo el scope `@imolko`, mediante `npm publish` con acceso público.
26
+ - El scope se configura durante el flujo de release, no en el código de la librería. La autenticación de la publicación (Trusted Publishing con fallback por staging) y su procedencia se deciden en [T-025](./T-025-publicacion-npm-trusted-publishing-procedencia.md).
27
+
28
+ ### semver como esquema de versionado
29
+
30
+ Los **paquetes** (librerías publicables) se versionan con **SemVer** —no con CalVer, reservado a las imágenes desplegables— y el canal de pre-lanzamiento usa el sufijo `-beta` (ver [A-016](../foundational/A-016-cicd-gitlab-pipeline-raiz-pipelines-modulares.md)); el incremento de versión se deriva de la convención de commits de [A-033](../foundational/A-033-estandar-mensajes-commit.md).
31
+
32
+ ### Flujo de release como fuente canónica
33
+
34
+ El flujo completo de versionado y publicación está implementado en los scripts de release del repositorio (`domain/scripts/release*.sh`), que son la fuente canónica; este ADR no duplica sus pasos ni la lista de scripts.
35
+
36
+ ### Librerías, sistemas y configuración
37
+
38
+ La taxonomía de [A-017](../foundational/A-017-taxonomia-repositorios-librerias-sistemas.md) decide qué se publica: las **librerías** se publican y versionan de forma independiente; los **sistemas** y la **configuración** no se publican como paquetes consumibles.
39
+
40
+ ## Consecuencias
41
+
42
+ ### Positivas
43
+
44
+ - **Instalación estándar**: cualquier consumidor usa `npm install` sin pasos especiales.
45
+ - **Compatibilidad comunicada**: semver expresa el impacto de cada versión en el número de versión.
46
+ - **Canal beta explícito**: el sufijo `-beta` permite pre-lanzamientos sin contaminar la línea estable.
47
+ - **Reproducibilidad**: el flujo vive en scripts versionados, no en la memoria del equipo.
48
+
49
+ ### Negativas
50
+
51
+ - **Sin automatización de changelog en este ADR**: el changelog no se deriva automáticamente de los commits; depende del flujo que acompañe a cada release.
52
+ - **Punto único de publicación**: la publicación centralizada en npm requiere credenciales gestionadas en el pipeline; un fallo de autenticación bloquea el release.
53
+ - **Versiones de librerías vs. sistema**: los sistemas comparten versión con su monorepo; las librerías publicadas deben mantener su propio ciclo semver, lo que exige disciplina para no desincronizarlas.
@@ -0,0 +1,35 @@
1
+ # T-015: `Definition` como único hogar de los métodos de dominio
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-08-29
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ Los artefactos de dominio que genera ultra-generator ([T-019](./T-019-ultra-generator-herramienta-canonica-generacion.md)) dividen cada value-object, entidad y agregado en dos clases: la clase `Definition` de ultra-ddd ([T-010](./T-010-stack-tooling-typescript-dominio.md)), que contiene la implementación, y la clase fachada pública, que registra el artefacto y expone su API estática. La fachada delega en `Definition` y no posee el estado del artefacto.
12
+
13
+ Cuando un método de dominio se coloca en la fachada pública, esta deja de ser un registro declarativo, intenta acceder a estado que no posee y duplica una responsabilidad que ya vive en `Definition`. El lugar de los métodos de dominio necesita una regla explícita, distinta de *qué* deben retornar esos métodos ([A-005](../foundational/A-005-either-return-custom-methods.md)).
14
+
15
+ ## Decisión
16
+
17
+ Todo método de dominio — lógica de negocio, validaciones adicionales, operaciones aritméticas, transformaciones — se implementa exclusivamente en la clase `Definition`. La clase fachada pública contiene únicamente el registro del artefacto y su API estática; **ningún método de instancia**.
18
+
19
+ Las fábricas estáticas — `create`, `restore`, `of`, `open` — son parte de la **API estática** de la fachada y pueden vivir allí: el mixin de ultra-ddd las provee (`create`, `restore`) o la fachada las declara (`open`). La prohibición alcanza a los métodos de **instancia**: ninguno puede vivir en la fachada.
20
+
21
+ Este ADR fija *dónde* viven los métodos de dominio; *qué* deben retornar lo fija [A-005](../foundational/A-005-either-return-custom-methods.md).
22
+
23
+ ## Consecuencias
24
+
25
+ ### Positivas
26
+
27
+ - **Separación clara**: `Definition` = implementación; la fachada = registro + API estática.
28
+ - **Consistencia**: todos los artefactos siguen el mismo patrón, facilitando navegación y mantenimiento.
29
+ - **Acceso al estado**: los métodos viven en la clase que posee las propiedades, con acceso directo y tipado.
30
+ - **Testabilidad**: los tests ejercen los métodos a través de la API pública sin acoplarse a la separación interna de clases.
31
+
32
+ ### Negativas
33
+
34
+ - **Dependencia circular**: `Definition` y su fachada se importan mutuamente cuando un método referencia la clase pública como tipo de retorno. Es un patrón que requiere conocimiento.
35
+ - **Doble clase**: los desarrolladores nuevos pueden no entender por qué el artefacto está dividido en dos clases.
@@ -0,0 +1,34 @@
1
+ # T-016: Implementación del contrato de settings con schema Zod
2
+
3
+ **Estado**: Aceptado
4
+
5
+ **Fecha**: 2026-09-06
6
+
7
+ **originally**: imolko
8
+
9
+ ## Contexto
10
+
11
+ El contrato de settings como única fuente de configuración es una decisión fundacional (ver [A-013](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md)), y la generación de artefactos de despliegue desde ese contrato también lo es (ver [A-014](../foundational/A-014-generacion-artefactos-despliegue-desde-contrato-settings.md)). Ambas son agnósticas a la tecnología de validación ([A-013 §5](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md)); este ADR fija su implementación concreta en el ecosistema TypeScript.
12
+
13
+ La validación de artefactos DDD con Zod es un eje distinto, tratado en [T-001](./T-001-ddd-artifact-validation-zod-primitives.md); el contrato de settings valida la configuración de la aplicación, no los artefactos de dominio, y por eso se decide por separado.
14
+
15
+ ## Decisión
16
+
17
+ En TypeScript, el contrato de settings se implementa con un **schema Zod** que actúa como **fuente única de verdad** para todos los settings.
18
+
19
+ - Cada campo declara sus metadatos de clasificación (tipo, origen, si contiene secretos) — la taxonomía vive en [A-013 §2](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md).
20
+ - La configuración se carga en tiempo de ejecución validando contra el schema Zod, conforme al fail-fast de [A-013 §3](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md).
21
+
22
+ La exportación de artefactos de despliegue desde el schema es responsabilidad de [A-014](../foundational/A-014-generacion-artefactos-despliegue-desde-contrato-settings.md), no de este ADR: aquí solo se fija que el schema Zod es lo que habilita la clasificación y la validación fail-fast.
23
+
24
+ ## Consecuencias
25
+
26
+ ### Positivas
27
+
28
+ - **Una sola fuente de verdad en código**: el schema Zod centraliza qué settings existen y cómo se validan, cumpliendo [A-013](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md).
29
+ - **Fail-fast materializado**: el schema Zod hace ejecutable en TypeScript el fail-fast de [A-013 §3](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md).
30
+
31
+ ### Negativas
32
+
33
+ - **Acoplamiento a Zod**: el patrón es agnóstico ([A-013 §5](../foundational/A-013-contrato-settings-unica-fuente-configuracion.md)), pero la implementación TypeScript queda atada a Zod.
34
+ - **Metadatos declarados a mano**: la clasificación de cada campo (tipo/origen/secreto) se escribe manualmente en el schema; un error ahí deriva artefactos incorrectos en [A-014](../foundational/A-014-generacion-artefactos-despliegue-desde-contrato-settings.md).