@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.
- package/README.md +93 -0
- package/bin/cli.js +2 -0
- package/dist-node/bin.d.ts +2 -0
- package/dist-node/bin.d.ts.map +1 -0
- package/dist-node/bin.js +5 -0
- package/dist-node/bin.js.map +1 -0
- package/dist-node/cli.d.ts +41 -0
- package/dist-node/cli.d.ts.map +1 -0
- package/dist-node/cli.js +170 -0
- package/dist-node/cli.js.map +1 -0
- package/dist-node/index.d.ts +14 -0
- package/dist-node/index.d.ts.map +1 -0
- package/dist-node/index.js +40 -0
- package/dist-node/index.js.map +1 -0
- package/dist-node/init-lint.d.ts +43 -0
- package/dist-node/init-lint.d.ts.map +1 -0
- package/dist-node/init-lint.js +84 -0
- package/dist-node/init-lint.js.map +1 -0
- package/dist-node/manifest.d.ts +33 -0
- package/dist-node/manifest.d.ts.map +1 -0
- package/dist-node/manifest.js +59 -0
- package/dist-node/manifest.js.map +1 -0
- package/dist-node/materializer.d.ts +52 -0
- package/dist-node/materializer.d.ts.map +1 -0
- package/dist-node/materializer.js +194 -0
- package/dist-node/materializer.js.map +1 -0
- package/dist-node/package-root.d.ts +5 -0
- package/dist-node/package-root.d.ts.map +1 -0
- package/dist-node/package-root.js +17 -0
- package/dist-node/package-root.js.map +1 -0
- package/dist-node/payload.d.ts +22 -0
- package/dist-node/payload.d.ts.map +1 -0
- package/dist-node/payload.js +49 -0
- package/dist-node/payload.js.map +1 -0
- package/dist-node/pointer-hub.d.ts +22 -0
- package/dist-node/pointer-hub.d.ts.map +1 -0
- package/dist-node/pointer-hub.js +50 -0
- package/dist-node/pointer-hub.js.map +1 -0
- package/dist-node/publication.cli.d.ts +9 -0
- package/dist-node/publication.cli.d.ts.map +1 -0
- package/dist-node/publication.cli.js +17 -0
- package/dist-node/publication.cli.js.map +1 -0
- package/dist-node/publication.d.ts +23 -0
- package/dist-node/publication.d.ts.map +1 -0
- package/dist-node/publication.js +47 -0
- package/dist-node/publication.js.map +1 -0
- package/dist-node/reconcile.cli.d.ts +11 -0
- package/dist-node/reconcile.cli.d.ts.map +1 -0
- package/dist-node/reconcile.cli.js +39 -0
- package/dist-node/reconcile.cli.js.map +1 -0
- package/dist-node/reconcile.d.ts +30 -0
- package/dist-node/reconcile.d.ts.map +1 -0
- package/dist-node/reconcile.js +51 -0
- package/dist-node/reconcile.js.map +1 -0
- package/dist-node/ship/prompts/fix.md +22 -0
- package/dist-node/ship/prompts/implement.md +34 -0
- package/dist-node/ship/prompts/review.md +28 -0
- package/dist-node/ship/ship.agent.d.ts +22 -0
- package/dist-node/ship/ship.agent.d.ts.map +1 -0
- package/dist-node/ship/ship.agent.js +142 -0
- package/dist-node/ship/ship.agent.js.map +1 -0
- package/dist-node/ship/ship.args.d.ts +15 -0
- package/dist-node/ship/ship.args.d.ts.map +1 -0
- package/dist-node/ship/ship.args.js +93 -0
- package/dist-node/ship/ship.args.js.map +1 -0
- package/dist-node/ship/ship.context.d.ts +12 -0
- package/dist-node/ship/ship.context.d.ts.map +1 -0
- package/dist-node/ship/ship.context.js +3 -0
- package/dist-node/ship/ship.context.js.map +1 -0
- package/dist-node/ship/ship.d.ts +4 -0
- package/dist-node/ship/ship.d.ts.map +1 -0
- package/dist-node/ship/ship.js +221 -0
- package/dist-node/ship/ship.js.map +1 -0
- package/dist-node/ship/ship.mr.d.ts +9 -0
- package/dist-node/ship/ship.mr.d.ts.map +1 -0
- package/dist-node/ship/ship.mr.js +171 -0
- package/dist-node/ship/ship.mr.js.map +1 -0
- package/dist-node/ship/ship.output.d.ts +9 -0
- package/dist-node/ship/ship.output.d.ts.map +1 -0
- package/dist-node/ship/ship.output.js +21 -0
- package/dist-node/ship/ship.output.js.map +1 -0
- package/dist-node/ship/ship.tracker.d.ts +37 -0
- package/dist-node/ship/ship.tracker.d.ts.map +1 -0
- package/dist-node/ship/ship.tracker.js +220 -0
- package/dist-node/ship/ship.tracker.js.map +1 -0
- package/dist-node/version.cli.d.ts +9 -0
- package/dist-node/version.cli.d.ts.map +1 -0
- package/dist-node/version.cli.js +30 -0
- package/dist-node/version.cli.js.map +1 -0
- package/dist-node/version.d.ts +24 -0
- package/dist-node/version.d.ts.map +1 -0
- package/dist-node/version.js +76 -0
- package/dist-node/version.js.map +1 -0
- package/docs/adr/ADR-0000-proceso-y-formato-de-adrs.md +115 -0
- package/docs/adr/foundational/A-001-clean-architecture-4-capas.md +88 -0
- package/docs/adr/foundational/A-002-cqrs-semantico.md +58 -0
- package/docs/adr/foundational/A-003-tdd.md +97 -0
- package/docs/adr/foundational/A-005-either-return-custom-methods.md +80 -0
- package/docs/adr/foundational/A-006-feature-completion-criteria.md +47 -0
- package/docs/adr/foundational/A-007-data-contract-fail-fast.md +109 -0
- package/docs/adr/foundational/A-008-bounded-context-decomposition.md +130 -0
- package/docs/adr/foundational/A-009-use-case-taxonomy.md +99 -0
- package/docs/adr/foundational/A-010-propiedad-emision-eventos-dominio.md +95 -0
- package/docs/adr/foundational/A-011-characterization-first-refactoring.md +90 -0
- package/docs/adr/foundational/A-012-helm-mecanismo-primario-despliegue.md +67 -0
- package/docs/adr/foundational/A-013-contrato-settings-unica-fuente-configuracion.md +74 -0
- package/docs/adr/foundational/A-014-generacion-artefactos-despliegue-desde-contrato-settings.md +75 -0
- package/docs/adr/foundational/A-015-cloudevents-estandar-eventos.md +85 -0
- package/docs/adr/foundational/A-016-cicd-gitlab-pipeline-raiz-pipelines-modulares.md +92 -0
- package/docs/adr/foundational/A-017-taxonomia-repositorios-librerias-sistemas.md +93 -0
- package/docs/adr/foundational/A-018-practicas-build-imagenes-docker.md +85 -0
- package/docs/adr/foundational/A-019-convenciones-autoria-helm-charts.md +97 -0
- package/docs/adr/foundational/A-020-entorno-desarrollo-estandarizado-devcontainer.md +58 -0
- package/docs/adr/foundational/A-022-formato-reporte-tests-ctrf.md +55 -0
- package/docs/adr/foundational/A-023-composicion-bloques-prompt-agentes.md +65 -0
- package/docs/adr/foundational/A-024-features-slices-verticales-portables.md +41 -0
- package/docs/adr/foundational/A-025-anatomia-mecanica-feature-puertos-adaptadores-drivers.md +104 -0
- package/docs/adr/foundational/A-026-infraestructura-compartida.md +44 -0
- package/docs/adr/foundational/A-027-patron-wiring-entry-point.md +67 -0
- package/docs/adr/foundational/A-029-verbos-intencion-metodos-lado-negocio.md +54 -0
- package/docs/adr/foundational/A-030-global-development-tooling.md +52 -0
- package/docs/adr/foundational/A-031-ubiquitous-language.md +64 -0
- package/docs/adr/foundational/A-032-domain-artifact-documentation-format.md +128 -0
- package/docs/adr/foundational/A-033-estandar-mensajes-commit.md +127 -0
- package/docs/adr/foundational/A-034-canonical-skill-set.md +64 -0
- package/docs/adr/foundational/A-035-captura-ideas-reanclaje-candies.md +51 -0
- package/docs/adr/foundational/A-036-adopcion-wayfinder-ortogonalidad-labels.md +37 -0
- package/docs/adr/foundational/A-037-formalizacion-taxonomia-labels.md +98 -0
- package/docs/adr/foundational/A-038-issues-referencian-skills-nombre.md +54 -0
- package/docs/adr/foundational/A-039-pipeline-ship-issues-hijos-spec.md +64 -0
- package/docs/adr/foundational/A-040-punteros-configuracion-repo-skills.md +44 -0
- package/docs/adr/foundational/A-041-estrategia-de-ramas.md +45 -0
- package/docs/adr/foundational/A-042-formato-documentos-issue-tracker.md +78 -0
- package/docs/adr/foundational/A-043-vocabulario-etiquetas-adrs.md +42 -0
- package/docs/adr/foundational/A-044-composicion-funcional-procesos-operaciones.md +44 -0
- package/docs/adr/foundational/A-045-guardrails-aplicables-no-directrices.md +48 -0
- package/docs/adr/foundational/A-046-metricas-de-forma-y-legibilidad-del-codigo.md +50 -0
- package/docs/adr/foundational/A-047-dependencias-explicitas-sin-globales-ambientales.md +40 -0
- package/docs/adr/foundational/A-048-cobertura-minima-codigo.md +39 -0
- package/docs/adr/foundational/A-049-materializacion-bucle-guardrails-extension-nativa-pi.md +49 -0
- package/docs/adr/foundational/A-050-el-caso-de-uso-pide-al-dominio-no-lee-su-representacion.md +50 -0
- package/docs/adr/foundational/A-051-orden-imports-por-distancia.md +47 -0
- package/docs/adr/foundational/A-052-distribucion-metodologia-paquete-versionado.md +42 -0
- package/docs/adr/foundational/A-053-errores-compartidos-entre-features-dos-hogares-por-capa.md +43 -0
- package/docs/adr/foundational/A-054-contrato-costura-driver-port-raw-data-canal-error.md +65 -0
- package/docs/adr/foundational/index.md +98 -0
- package/docs/adr/index.md +19 -0
- package/docs/adr/python/P-001-dependencias-por-feature-fastapi-depends.md +63 -0
- package/docs/adr/python/P-002-inyeccion-token-por-request-sin-persistirlo.md +35 -0
- package/docs/adr/python/P-003-sqlalchemy-async-connection-pooling.md +59 -0
- package/docs/adr/python/P-004-serializer-json-custom-modelos-pydantic.md +47 -0
- package/docs/adr/python/P-005-patrones-pitfalls-nicegui.md +148 -0
- package/docs/adr/python/P-006-convenciones-pytest.md +96 -0
- package/docs/adr/python/P-007-ci-python-alineacion-poetry-version-unica.md +55 -0
- package/docs/adr/python/P-008-empaquetado-infraestructura-compartida-por-tecnologia.md +38 -0
- package/docs/adr/python/index.md +14 -0
- package/docs/adr/typescript/T-001-ddd-artifact-validation-zod-primitives.md +136 -0
- package/docs/adr/typescript/T-002-test-documentation-jsdoc.md +133 -0
- package/docs/adr/typescript/T-003-readme-formatting-domain-artifacts.md +51 -0
- package/docs/adr/typescript/T-005-input-optionality-use-case-not-entity.md +130 -0
- package/docs/adr/typescript/T-006-small-enums-inlined-zod-regex.md +77 -0
- package/docs/adr/typescript/T-007-controller-input-zod-schema.md +79 -0
- package/docs/adr/typescript/T-008-expressive-use-case-pipe.md +207 -0
- package/docs/adr/typescript/T-009-mdx-brace-escaping.md +80 -0
- package/docs/adr/typescript/T-010-stack-tooling-typescript-dominio.md +53 -0
- package/docs/adr/typescript/T-011-ultra-reporter-herramienta-canonica-documentacion.md +52 -0
- package/docs/adr/typescript/T-012-npm-workspaces-estructura-monorepo-clean-architecture.md +54 -0
- package/docs/adr/typescript/T-013-definicion-eventos-versionados-ultra-ddd.md +45 -0
- package/docs/adr/typescript/T-014-publicacion-distribucion-librerias-npm-semver.md +53 -0
- package/docs/adr/typescript/T-015-method-placement-definition.md +35 -0
- package/docs/adr/typescript/T-016-contrato-settings-zod.md +34 -0
- package/docs/adr/typescript/T-017-characterization-tests-golden-files.md +39 -0
- package/docs/adr/typescript/T-018-procedencia-campos-frontmatter.md +55 -0
- package/docs/adr/typescript/T-019-ultra-generator-herramienta-canonica-generacion.md +35 -0
- package/docs/adr/typescript/T-020-ultra-settings-herramienta-canonica-exportacion-despliegue.md +36 -0
- package/docs/adr/typescript/T-021-pipe-flujo-datos-operadores-semantica-contexto-inmutable.md +105 -0
- package/docs/adr/typescript/T-022-construction-is-execution-single-boundary.md +112 -0
- package/docs/adr/typescript/T-023-registry-cli-declara-dependencias-reales.md +84 -0
- package/docs/adr/typescript/T-024-paquete-ultra-agent-manifiesto-pi-peers-cli.md +39 -0
- package/docs/adr/typescript/T-025-publicacion-npm-trusted-publishing-procedencia.md +59 -0
- package/docs/adr/typescript/index.md +30 -0
- package/eslint/index.mjs +721 -0
- package/package.json +94 -0
- package/pi/extensions/handoff/README.md +92 -0
- package/pi/extensions/handoff/handoff-prompt.txt +9 -0
- package/pi/extensions/handoff/index.ts +296 -0
- package/pi/extensions/handoff/package.json +12 -0
- package/pi/extensions/qa-guardrail/README.md +108 -0
- package/pi/extensions/qa-guardrail/adapters/cli.ts +100 -0
- package/pi/extensions/qa-guardrail/adapters/eslint.ts +90 -0
- package/pi/extensions/qa-guardrail/adapters/registry.ts +45 -0
- package/pi/extensions/qa-guardrail/baseline.ts +74 -0
- package/pi/extensions/qa-guardrail/cerco.ts +134 -0
- package/pi/extensions/qa-guardrail/check.ts +185 -0
- package/pi/extensions/qa-guardrail/config.ts +189 -0
- package/pi/extensions/qa-guardrail/delta.ts +52 -0
- package/pi/extensions/qa-guardrail/feedback.ts +26 -0
- package/pi/extensions/qa-guardrail/index.ts +311 -0
- package/pi/extensions/qa-guardrail/nstop.ts +82 -0
- package/pi/extensions/qa-guardrail/package.json +12 -0
- package/pi/extensions/qa-guardrail/selection.ts +98 -0
- package/pi/extensions/qa-guardrail/types.ts +64 -0
- package/scripts/copy-assets.sh +10 -0
- package/scripts/reconcile-tags.sh +94 -0
- package/scripts/release-beta.sh +64 -0
- package/scripts/release-build.sh +53 -0
- package/scripts/release.sh +51 -0
- package/scripts/verify-adr-consistency.py +217 -0
- package/skills/code-review/SKILL.md +66 -0
- package/skills/codebase-design/SKILL.md +46 -0
- package/skills/configure-repo/SKILL.md +33 -0
- package/skills/diagnose-bug/SKILL.md +63 -0
- package/skills/domain-modeling/SKILL.md +56 -0
- package/skills/grill-me/SKILL.md +34 -0
- package/skills/i-have-an-idea/SKILL.md +166 -0
- package/skills/implement/SKILL.md +22 -0
- package/skills/research/SKILL.md +17 -0
- package/skills/ship/SKILL.md +26 -0
- package/skills/spike/SKILL.md +27 -0
- package/skills/tdd/SKILL.md +68 -0
- package/skills/tdd/references/deep-modules.md +53 -0
- package/skills/tdd/references/interface-design.md +74 -0
- package/skills/tdd/references/mocking.md +80 -0
- package/skills/tdd/references/refactoring.md +49 -0
- package/skills/tdd/references/tests.md +184 -0
- package/skills/to-specs/SKILL.md +141 -0
- package/skills/to-tasks/SKILL.md +143 -0
- package/skills/triage/SKILL.md +73 -0
- package/skills/ultra-generator/SKILL.md +263 -0
- package/skills/ultra-generator/references/aggregate-root.md +149 -0
- package/skills/ultra-generator/references/domain-event.md +174 -0
- package/skills/ultra-generator/references/entity.md +133 -0
- package/skills/ultra-generator/references/service.md +92 -0
- package/skills/ultra-generator/references/value-object.md +135 -0
- package/skills/wayfinder/SKILL.md +201 -0
- package/skills/workflow/SKILL.md +31 -0
- package/skills/writing-for-agents/SKILL-MECHANICS.md +32 -0
- package/skills/writing-for-agents/SKILL.md +86 -0
- package/skills/writing-for-agents/references/adrs.md +19 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: to-tasks
|
|
3
|
+
description: Break a spec into independently-grabbable tasks, each declaring its blocking edges, using tracer-bullet vertical slices.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# To Tasks
|
|
8
|
+
|
|
9
|
+
Break a spec into independently-grabbable tasks using vertical slices (tracer bullets), then publish them to the issue tracker via `tracker_cli`.
|
|
10
|
+
|
|
11
|
+
Read `docs/agents/repo-config.md` for the repo pointers (`adr_dir`, `domain_dir`, `issue_language`, `tracker_cli`) — use them instead of hardcoded paths.
|
|
12
|
+
|
|
13
|
+
Reference: A-042 (task structure), A-038 (skill-first in `Skill recomendado`), A-037 (labels), A-039 (spec → child issues).
|
|
14
|
+
|
|
15
|
+
## Process
|
|
16
|
+
|
|
17
|
+
### 1. Gather context
|
|
18
|
+
|
|
19
|
+
Work from whatever is already in the conversation context. If the user passes an issue reference (issue number, URL, or path) as an argument, fetch it from the issue tracker using `tracker_cli` and read its full body and comments:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
<tracker_cli> issue view <issue-id>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. Explore the codebase (optional)
|
|
26
|
+
|
|
27
|
+
If you have not already explored the codebase, do so to understand the current state. Task titles and descriptions should use the project's domain glossary vocabulary, and respect ADRs in the area you are touching.
|
|
28
|
+
|
|
29
|
+
### 3. Draft vertical slices
|
|
30
|
+
|
|
31
|
+
Break the spec into **tracer bullet** tasks. Each task is a thin vertical slice that cuts through ALL integration layers end-to-end.
|
|
32
|
+
|
|
33
|
+
Slices may be **HITL** or **AFK** — the `exec::` dimension (A-037). HITL requires a human in the loop (an architectural decision or a design review); AFK can be implemented and merged without one. Prefer AFK over HITL where possible.
|
|
34
|
+
|
|
35
|
+
Rules for vertical slices:
|
|
36
|
+
- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, tests, etc.)
|
|
37
|
+
- A completed slice is demoable or verifiable on its own
|
|
38
|
+
- Prefer many thin slices over few thick ones
|
|
39
|
+
|
|
40
|
+
### 4. Quiz the user
|
|
41
|
+
|
|
42
|
+
Present the proposed breakdown as a numbered list. For each task, show:
|
|
43
|
+
|
|
44
|
+
- **Titulo**: short descriptive name in `issue_language`
|
|
45
|
+
- **Modo**: `exec::AFK` o `exec::HITL`
|
|
46
|
+
- **Bloqueado por**: which other tasks (if any) must complete first
|
|
47
|
+
|
|
48
|
+
Iterate with the user until they approve the breakdown.
|
|
49
|
+
|
|
50
|
+
### 5. Publish the tasks to the issue tracker
|
|
51
|
+
|
|
52
|
+
For each approved slice, publish a new issue using `tracker_cli` (default `glab`). Write all tasks in `issue_language` (default Spanish).
|
|
53
|
+
|
|
54
|
+
Publish tasks in dependency order (blockers first) so you can reference real issue identifiers in the "Bloqueado por" section.
|
|
55
|
+
|
|
56
|
+
#### Task Template
|
|
57
|
+
|
|
58
|
+
Each task body must follow this structure — the canonical task structure is owned by A-042; this is its operational copy:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
# Skill recomendado
|
|
62
|
+
|
|
63
|
+
Name the skill(s) to use, by exact name (`/skill:<name>`) as the first instruction (A-038), and the next step in the flow. Example: `Para comenzar, usa /skill:tdd (→ /skill:ship).`
|
|
64
|
+
|
|
65
|
+
# Contexto
|
|
66
|
+
|
|
67
|
+
Explain the situation and general context for the task. This is important to give the person that will work on the task a general context and information to be productive really quickly.
|
|
68
|
+
|
|
69
|
+
# Alcance
|
|
70
|
+
|
|
71
|
+
Define the precise scope — short paragraphs on what is needed to close the task.
|
|
72
|
+
|
|
73
|
+
# Criterio de cierre
|
|
74
|
+
|
|
75
|
+
Indicate in tasks what is the criteria for finishing this task. Each task must have a clear focus and allows the worker to have a clear view of the goals required.
|
|
76
|
+
|
|
77
|
+
This section helps the person responsible for approving the task (a different person from the implementer) to check if all the work has been done.
|
|
78
|
+
|
|
79
|
+
Use a task format for each point: one checkbox per criterion (checkbox-list format owned by A-042).
|
|
80
|
+
|
|
81
|
+
# Pruebas recomendadas
|
|
82
|
+
|
|
83
|
+
When the responsible for the task completes the work, another person must check if it is OK.
|
|
84
|
+
|
|
85
|
+
In this section, provide a suggestion of minimum tests the reviewer must perform to verify the work. The reviewer can approve if all tests pass, or reject otherwise.
|
|
86
|
+
|
|
87
|
+
Each test should include a detailed list of steps and verifications to perform.
|
|
88
|
+
|
|
89
|
+
# Tarea padre
|
|
90
|
+
|
|
91
|
+
A reference to the parent spec.
|
|
92
|
+
|
|
93
|
+
# Bloqueado por
|
|
94
|
+
|
|
95
|
+
- A reference to the blocking task (if any)
|
|
96
|
+
|
|
97
|
+
If no blockers, write: "Ninguno - puede iniciarse de inmediato"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Creating the Issue
|
|
101
|
+
|
|
102
|
+
Before publishing each task, show a preview and ask for confirmation. On confirmation:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Write the body to a temp file to avoid shell escaping issues
|
|
106
|
+
cat > /tmp/issue-body.md << 'ISSUE_EOF'
|
|
107
|
+
<CUERPO_DEL_ISSUE>
|
|
108
|
+
ISSUE_EOF
|
|
109
|
+
|
|
110
|
+
# Create the issue
|
|
111
|
+
<tracker_cli> issue create \
|
|
112
|
+
--title "<TITULO_DEL_ISSUE>" \
|
|
113
|
+
--description "$(cat /tmp/issue-body.md)" \
|
|
114
|
+
--label "state::ready,<EXEC_MODE>" \
|
|
115
|
+
--linked-issues <PARENT_IID>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
(`<EXEC_MODE>` in the command above is `exec::AFK` or `exec::HITL`.)
|
|
119
|
+
|
|
120
|
+
**Linked issues:** Use `--linked-issues <PARENT_IID>` to link each task to the parent spec. This enables `ship` to discover children via the tracker's API.
|
|
121
|
+
|
|
122
|
+
The task title should be concise and descriptive in `issue_language`.
|
|
123
|
+
|
|
124
|
+
### 6. Confirm
|
|
125
|
+
|
|
126
|
+
After creating all tasks, show a summary table:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
| # | Titulo | Modo | Bloqueado por |
|
|
130
|
+
|---|--------|------|---------------|
|
|
131
|
+
| #1 | ... | exec::AFK | Ninguno |
|
|
132
|
+
| #2 | ... | exec::HITL | #1 |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Include each task's URL.
|
|
136
|
+
|
|
137
|
+
Leave the parent spec open and untouched — you create only the child tasks.
|
|
138
|
+
|
|
139
|
+
Offer the next step: `/skill:ship` over the parent spec — its IID is already resolved.
|
|
140
|
+
|
|
141
|
+
## Rules
|
|
142
|
+
|
|
143
|
+
The task's formatting rules are owned by A-042 — read and apply them from there, not restated here.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: triage
|
|
3
|
+
description: Move issues and external merge requests through a state machine of triage roles — categorise, verify, grill if needed, and write agent-ready briefs.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Triage
|
|
8
|
+
|
|
9
|
+
Move issues on the issue tracker through a small state machine of triage roles. External merge requests are the same machine applied to attached code.
|
|
10
|
+
|
|
11
|
+
Read `docs/agents/repo-config.md` for the repo pointers (`adr_dir`, `domain_dir`, `issue_language`, `tracker_cli`) — use them instead of hardcoded paths.
|
|
12
|
+
|
|
13
|
+
Reference: A-037 (label taxonomy and state machine), A-042 (issue-triado brief), A-038 (skill-first), A-031 (ubiquitous language).
|
|
14
|
+
|
|
15
|
+
Every comment or issue posted during triage **must** start with:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
> *This was generated by AI during triage.*
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Triage's part of the machine
|
|
22
|
+
|
|
23
|
+
Triage fills the ingestion region of the label taxonomy: `type::` (bug/enhancement), `state::` up to `ready`, and `exec::` when the brief is written. The dimension values and the state transitions are owned by A-037 — read them there, not restated here.
|
|
24
|
+
|
|
25
|
+
An MR: `state::ready` + `exec::AFK` means an agent takes the next step on the diff; `state::ready` + `exec::HITL` means ready for a human to merge.
|
|
26
|
+
|
|
27
|
+
If state labels conflict, flag it and ask the maintainer before doing anything else. The maintainer can override any transition — flag unusual ones and ask before proceeding.
|
|
28
|
+
|
|
29
|
+
## Invocation
|
|
30
|
+
|
|
31
|
+
The maintainer invokes `/skill:triage` and describes what they want:
|
|
32
|
+
|
|
33
|
+
- "Show me anything that needs my attention"
|
|
34
|
+
- "Let's look at #42"
|
|
35
|
+
- "Move #42 to state::ready"
|
|
36
|
+
- "What's ready for agents to pick up?"
|
|
37
|
+
|
|
38
|
+
## Show what needs attention
|
|
39
|
+
|
|
40
|
+
Query the issue tracker and present three buckets, oldest first:
|
|
41
|
+
|
|
42
|
+
1. **Unlabeled** (no `state::`) — never triaged.
|
|
43
|
+
2. **`state::needs-info`** — waiting on the reporter.
|
|
44
|
+
3. **`state::ready`** — specified, in the queue (`exec::` says who takes it).
|
|
45
|
+
|
|
46
|
+
## Categorise and verify
|
|
47
|
+
|
|
48
|
+
For each issue:
|
|
49
|
+
|
|
50
|
+
1. Read the body and comments (`<tracker_cli> issue view <id>`).
|
|
51
|
+
2. Assign the category (`type::bug`/`type::enhancement`) and initial state (`state::`).
|
|
52
|
+
3. **Verify**: can the issue be actioned as written? If it's ambiguous, move to `state::needs-info` with the specific questions the reporter must answer.
|
|
53
|
+
4. If a design decision is half-baked, grill it (`/skill:grill-me`) before writing the brief.
|
|
54
|
+
|
|
55
|
+
## Write the agent-ready brief
|
|
56
|
+
|
|
57
|
+
When an issue reaches `state::ready`, write the brief the implementing agent will consume without asking, and set the execution mode — `exec::AFK` if an agent can do it alone, `exec::HITL` if a human must stay in the loop. The brief's required content is owned by A-042 (issue triado) — read it there. Point the brief at the relevant skill as its first instruction (A-038): `type::bug` → `/skill:diagnose-bug` first, then `/skill:implement` + `/skill:tdd` for the fix; `type::enhancement` → `/skill:implement` + `/skill:tdd` (+ `/skill:ultra-generator` if scaffolding).
|
|
58
|
+
|
|
59
|
+
## Apply labels
|
|
60
|
+
|
|
61
|
+
Apply the labels via `tracker_cli` (default `glab`) — the mapping from triage roles to labels is fixed in A-037. Post the brief as a comment on the issue, prefixed with the disclaimer:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
<tracker_cli> issue note <iid> -m "> *This was generated by AI during triage.*
|
|
65
|
+
|
|
66
|
+
<brief>"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
A comment on the issue is the brief's only home — the reporter's body stays untouched.
|
|
70
|
+
|
|
71
|
+
## Rules
|
|
72
|
+
|
|
73
|
+
The label taxonomy and state machine are owned by A-037; the triaged-issue brief content is owned by A-042 — read and apply them from there, not restated here.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultra-generator
|
|
3
|
+
description: Generate ultra-ddd compliant domain artifacts using ultra-generator
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ultra-Generator
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Ultra-Generator is a scaffolding tool for [ultra-ddd](https://gitlab.com/imolko/ultra-ddd) projects. It generates domain artifacts (value objects, entities, aggregates, services, domain events), features (commands and queries with minimal in-memory infrastructure), actions, errors, and infrastructure drivers with boilerplate code that is immediately compilable and testable.
|
|
11
|
+
|
|
12
|
+
Ultra-Generator works in tandem with [ultra-reporter](https://gitlab.com/imolko/ultra-reporter), which scans generated files to produce Docusaurus-based documentation.
|
|
13
|
+
|
|
14
|
+
## DDD Philosophy: Forget About Infrastructure First
|
|
15
|
+
|
|
16
|
+
Ultra-Generator follows Clean Architecture principles. The recommended workflow is:
|
|
17
|
+
|
|
18
|
+
1. **Define domain objects** using `add-domain`
|
|
19
|
+
2. **Create features** using `add-feature` — this generates the use case with **minimal in-memory drivers** (no database, no GraphQL, no NestJS)
|
|
20
|
+
3. **Validate business logic** — run tests against in-memory drivers, iterate with domain experts
|
|
21
|
+
4. **Add actions** using `add-action` — extend ports with specific methods
|
|
22
|
+
5. **Wire infrastructure** using `add-driver` — ONLY after business logic is validated, add MongoDB, GraphQL, or NestJS drivers
|
|
23
|
+
|
|
24
|
+
This ensures the domain layer stays pure and infrastructure choices are deferred until the business rules are correct.
|
|
25
|
+
|
|
26
|
+
## When to Use
|
|
27
|
+
|
|
28
|
+
Use ultra-generator when the user needs to:
|
|
29
|
+
- Create a new domain artifact (value object, entity, aggregate-root, service, domain event)
|
|
30
|
+
- Create a new feature (command or query) with minimal in-memory infrastructure
|
|
31
|
+
- Add actions to a feature
|
|
32
|
+
- Define domain errors
|
|
33
|
+
- Add infrastructure drivers (MongoDB, GraphQL + NestJS) to a feature
|
|
34
|
+
|
|
35
|
+
## How to Invoke
|
|
36
|
+
|
|
37
|
+
### Primary: CLI Mode
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Preview (dry-run)
|
|
41
|
+
npx ultra-generator generate --json-file /tmp/input.json --dry-run
|
|
42
|
+
|
|
43
|
+
# Execute
|
|
44
|
+
npx ultra-generator generate --json-file /tmp/input.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Input JSON format: `{ "generator": "<generator-name>", "data": { ... } }`
|
|
48
|
+
|
|
49
|
+
### Advanced: JS/TS API
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { run } from '@imolko/ultra-generator';
|
|
53
|
+
|
|
54
|
+
const result = await run(
|
|
55
|
+
{ generator: 'add-domain', data: { ... } },
|
|
56
|
+
{ dryRun: true }
|
|
57
|
+
);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Agent Workflow
|
|
61
|
+
|
|
62
|
+
1. **Collect data** from the user (see Generator Input Guides below)
|
|
63
|
+
2. **Construct JSON** with `{ generator, data }`
|
|
64
|
+
3. **Dry-run** to preview generated files
|
|
65
|
+
4. **Present summary** to the user (recommended)
|
|
66
|
+
5. **Execute** generation
|
|
67
|
+
6. **Read the `.instructions.md` stub** in the generated artifact directory
|
|
68
|
+
7. **Follow the checklist** — the stub links to canonical instructions
|
|
69
|
+
8. **Implement customizations** following the TDD red-green-refactor loop
|
|
70
|
+
|
|
71
|
+
### Recommended Agent Workflow for Features
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
User requests a new business capability
|
|
75
|
+
→ Step 1: add-domain (define domain objects needed)
|
|
76
|
+
→ Step 2: add-feature (create command/query with in-memory drivers)
|
|
77
|
+
→ Step 3: add-errors (define domain/feature errors)
|
|
78
|
+
→ Step 4: add-action (add methods to ports — repository, presenter, etc.)
|
|
79
|
+
→ Step 5: User validates business logic with domain experts
|
|
80
|
+
→ Step 6: add-driver (wire MongoDB, GraphQL, NestJS after validation)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Response Interpretation
|
|
84
|
+
|
|
85
|
+
The `GeneratorResult` response contains:
|
|
86
|
+
- `success: boolean` — whether generation succeeded
|
|
87
|
+
- `generator: string` — which generator was used
|
|
88
|
+
- `changes: FileChange[]` — list of created/modified files
|
|
89
|
+
- `dryRun: boolean` — whether changes were written to disk
|
|
90
|
+
- `instructions: { canonical: string, stubPath: string }` — references to instructions
|
|
91
|
+
|
|
92
|
+
After generation, the agent should read the `.instructions.md` stub (path in `instructions.stubPath`) and follow the canonical instructions (path in `instructions.canonical`).
|
|
93
|
+
|
|
94
|
+
## Batch Generation
|
|
95
|
+
|
|
96
|
+
For creating multiple artifacts at once, collect data as an array of `GeneratorInput` objects. Order matters — resolve dependencies:
|
|
97
|
+
|
|
98
|
+
- An artifact may reference other artifacts via `conditions[].type` and `props[].type`
|
|
99
|
+
- Build a dependency graph from these references
|
|
100
|
+
- Topologically sort: leaf artifacts first, dependent artifacts after
|
|
101
|
+
- Generate artifacts in dependency order
|
|
102
|
+
- **Important**: `add-driver` should always be the LAST step — add infrastructure only after business logic is defined and validated
|
|
103
|
+
|
|
104
|
+
## Generator Input Guides
|
|
105
|
+
|
|
106
|
+
### add-domain
|
|
107
|
+
|
|
108
|
+
| Field | Required | Type | Description |
|
|
109
|
+
|-------|----------|------|-------------|
|
|
110
|
+
| `domainType` | ✅ | `value-object` \| `entity` \| `aggregate-root` \| `service` \| `domain-event` | Type of domain artifact |
|
|
111
|
+
| `domainName` | ✅ | string (kebab-case) | Name of the artifact |
|
|
112
|
+
| `description` | ✅ | string | Human-readable description |
|
|
113
|
+
| `conditions` | [] | `DomainProperty[]` | Validation conditions |
|
|
114
|
+
| `props` | [] | `DomainProperty[]` | Computed properties |
|
|
115
|
+
| `conditionsErrorsName` | [] | `string[]` | Custom error names for conditions |
|
|
116
|
+
| `othersErrorsName` | [] | `string[]` | Other domain error names |
|
|
117
|
+
| `testCases` | [] | `string[]` | Test case descriptions |
|
|
118
|
+
| `contextName` | — | string | Domain context (default: `''`) |
|
|
119
|
+
| `boundedContext` | — | string | Bounded context for documentation tagging (fallback: `contextName`) |
|
|
120
|
+
| `language` | — | `'en'` \| `'es'` | Language for generated README (default: `'en'`) |
|
|
121
|
+
| `tags` | — | string | Comma-separated tags |
|
|
122
|
+
| `directory` | — | string | Custom output directory |
|
|
123
|
+
|
|
124
|
+
#### Domain event fields
|
|
125
|
+
|
|
126
|
+
These fields apply when `domainType` is `domain-event`:
|
|
127
|
+
|
|
128
|
+
| Field | Required | Type | Description |
|
|
129
|
+
|-------|----------|------|-------------|
|
|
130
|
+
| `eventTitle` | ✅ | string | Human-readable event title |
|
|
131
|
+
| `aggregateName` | ✅ | string (kebab-case) | Owning aggregate name |
|
|
132
|
+
| `scope` | — | `LOCAL` \| `GLOBAL` | Event scope (default: `LOCAL`) |
|
|
133
|
+
| `emitterApp` | — | string | Emitting application name (default: from config `appName`, then context) |
|
|
134
|
+
| `dataContentType` | — | string | Content type of event data (default: `application/json`) |
|
|
135
|
+
| `eventOwner` | — | string | Organization/team identifier (default: `default`) |
|
|
136
|
+
| `sampleData` | — | `object[]` | Sample data payloads (auto-generated from conditions if omitted) |
|
|
137
|
+
|
|
138
|
+
#### DomainProperty
|
|
139
|
+
|
|
140
|
+
| Field | Required | Type | Description |
|
|
141
|
+
|-------|----------|------|-------------|
|
|
142
|
+
| `name` | ✅ | string (camelCase) | Property name |
|
|
143
|
+
| `type` | ✅ | string | Property type (e.g., `string`, `number`, `Uuid`, domain object name) |
|
|
144
|
+
| `category` | ✅ | `basic` \| `value-object` \| `entity` \| `aggregate-root` \| `service` | Type category |
|
|
145
|
+
| `description` | — | string | Human-readable description |
|
|
146
|
+
| `validation` | — | `ValidationConstraints` | Zod native constraints (see below) |
|
|
147
|
+
|
|
148
|
+
#### ValidationConstraints
|
|
149
|
+
|
|
150
|
+
Native Zod primitives for standard validations. Only applicable when `category` is `basic`.
|
|
151
|
+
|
|
152
|
+
| Field | Type | Applies to | Generates |
|
|
153
|
+
|-------|------|-----------|-----------|
|
|
154
|
+
| `minLength` | `number` | `string` | `.min(n)` |
|
|
155
|
+
| `maxLength` | `number` | `string` | `.max(n)` |
|
|
156
|
+
| `pattern` | `string` | `string` | `.regex(new RegExp(pattern))` |
|
|
157
|
+
| `min` | `number` | `number` | `.min(n)` |
|
|
158
|
+
| `max` | `number` | `number` | `.max(n)` |
|
|
159
|
+
| `customErrors` | `string[]` | any | `superRefine` at object level + triggers `add-errors` |
|
|
160
|
+
|
|
161
|
+
**Constraints are validated at schema level**: string properties reject `min`/`max`, number properties reject `minLength`/`maxLength`/`pattern`, and `min` must be ≤ `max`.
|
|
162
|
+
|
|
163
|
+
**Examples:**
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
// String with native validations
|
|
167
|
+
{ "name": "email", "type": "string", "category": "basic",
|
|
168
|
+
"validation": { "minLength": 5, "maxLength": 100, "pattern": "^[a-z]+@[a-z]+\\.com$" } }
|
|
169
|
+
|
|
170
|
+
// Number with range
|
|
171
|
+
{ "name": "age", "type": "number", "category": "basic",
|
|
172
|
+
"validation": { "min": 0, "max": 150 } }
|
|
173
|
+
|
|
174
|
+
// Complex domain rule with custom error
|
|
175
|
+
{ "name": "password", "type": "string", "category": "basic",
|
|
176
|
+
"validation": { "customErrors": ["weak-password"] } }
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### add-errors
|
|
180
|
+
|
|
181
|
+
| Field | Required | Type | Description |
|
|
182
|
+
|-------|----------|------|-------------|
|
|
183
|
+
| `target` | ✅ | `features` \| `domain-rules` \| `domain-others` | Where to add errors |
|
|
184
|
+
| `featureTargetName` | ✅ | string | Target artifact name |
|
|
185
|
+
| `errorsName` | ✅ | `string[]` | Error names (kebab-case) |
|
|
186
|
+
| `contextName` | — | string | Domain context |
|
|
187
|
+
| `domainFeatureRoot` | — | string | Auto-derived from config if omitted |
|
|
188
|
+
|
|
189
|
+
### add-feature
|
|
190
|
+
|
|
191
|
+
Generates a feature (command or query) with **minimal in-memory infrastructure** — no database, no GraphQL, no NestJS. The use case is immediately compilable and testable.
|
|
192
|
+
|
|
193
|
+
Generated structure:
|
|
194
|
+
```
|
|
195
|
+
feature/
|
|
196
|
+
├── use-case/ # Pure business logic
|
|
197
|
+
│ ├── use-case.ts # Functional pipeline (seedTV → checkRequirements → executeSequentially → when)
|
|
198
|
+
│ ├── presenter.port.ts
|
|
199
|
+
│ ├── repository.port.ts
|
|
200
|
+
│ └── errors/
|
|
201
|
+
├── adapters/ # Port adapters
|
|
202
|
+
│ ├── presenter/
|
|
203
|
+
│ ├── repository/
|
|
204
|
+
│ └── controller/
|
|
205
|
+
└── drivers/ # In-memory implementations
|
|
206
|
+
├── in-memory-presenter/
|
|
207
|
+
└── in-memory-repository/
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
| Field | Required | Type | Description |
|
|
211
|
+
|-------|----------|------|-------------|
|
|
212
|
+
| `featureName` | ✅ | string (kebab-case) | Feature name |
|
|
213
|
+
| `featureType` | ✅ | `command` \| `query` | Feature type |
|
|
214
|
+
| `testCases` | [] | `string[]` | Test case descriptions |
|
|
215
|
+
| `featuresRoot` | — | string | Auto-derived from config if omitted |
|
|
216
|
+
|
|
217
|
+
### add-action
|
|
218
|
+
|
|
219
|
+
Adds methods to service ports and adapters within an existing feature. The generator discovers available service ports by scanning `use-case/*.port.ts` files in the target feature. It updates the use case, adapters, controller, and spec — but does **NOT** touch any driver implementations.
|
|
220
|
+
|
|
221
|
+
| Field | Required | Type | Description |
|
|
222
|
+
|-------|----------|------|-------------|
|
|
223
|
+
| `serviceTargetName` | ✅ | string | Service name (e.g., `repository`, `presenter`) |
|
|
224
|
+
| `featureTargetName` | ✅ | string | Target feature name in kebab-case |
|
|
225
|
+
| `actionName` | ✅ | string (camelCase) | Action/method name |
|
|
226
|
+
| `actionType` | ✅ | `command` \| `query` \| `validation` | Type of action |
|
|
227
|
+
| `params` | [] | `ActionParams[]` | Method parameters |
|
|
228
|
+
| `executionDataType` | — | string | Return type for queries (default: `void`) |
|
|
229
|
+
| `errorsName` | [] | `string[]` | Error names for this action |
|
|
230
|
+
| `featuresRoot` | — | string | Auto-derived from config if omitted |
|
|
231
|
+
|
|
232
|
+
### add-driver
|
|
233
|
+
|
|
234
|
+
Adds infrastructure-specific drivers to an existing feature. Should be invoked **AFTER** business logic is validated with in-memory drivers.
|
|
235
|
+
|
|
236
|
+
Available driver types:
|
|
237
|
+
- `mongodb` — Repository driver with Mongoose model injection port
|
|
238
|
+
- `graphql` — Presenter driver + NestJS resolver/module (generated together)
|
|
239
|
+
|
|
240
|
+
| Field | Required | Type | Description |
|
|
241
|
+
|-------|----------|------|-------------|
|
|
242
|
+
| `featureTargetName` | ✅ | string | Target feature name in kebab-case |
|
|
243
|
+
| `driverType` | ✅ | `mongodb` \| `graphql` | Type of driver to add |
|
|
244
|
+
| `templatePath` | — | string | Custom driver template directory path (for team-specific drivers) |
|
|
245
|
+
| `featuresRoot` | — | string | Auto-derived from config if omitted |
|
|
246
|
+
|
|
247
|
+
**Important**: Running `add-driver` on a feature with no port actions will fail. Use `add-action` first to define the ports, then `add-driver` to add the implementation.
|
|
248
|
+
|
|
249
|
+
## Canonical Instructions
|
|
250
|
+
|
|
251
|
+
After generating an artifact, read the canonical instructions for post-generation steps:
|
|
252
|
+
|
|
253
|
+
| Artifact Type | Canonical Instructions |
|
|
254
|
+
|---------------|----------------------|
|
|
255
|
+
| Value Object | `@imolko/ultra-generator/skills/ultra-generator/references/value-object.md` |
|
|
256
|
+
| Entity | `@imolko/ultra-generator/skills/ultra-generator/references/entity.md` |
|
|
257
|
+
| Aggregate Root | `@imolko/ultra-generator/skills/ultra-generator/references/aggregate-root.md` |
|
|
258
|
+
| Service | `@imolko/ultra-generator/skills/ultra-generator/references/service.md` |
|
|
259
|
+
| Domain Event | `@imolko/ultra-generator/skills/ultra-generator/references/domain-event.md` |
|
|
260
|
+
| Feature | (coming soon) |
|
|
261
|
+
| Action | (coming soon) |
|
|
262
|
+
| Errors | (coming soon) |
|
|
263
|
+
| Driver | (coming soon) |
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Working with an Aggregate Root
|
|
2
|
+
|
|
3
|
+
## Files Generated
|
|
4
|
+
|
|
5
|
+
| File | Purpose |
|
|
6
|
+
|------|---------|
|
|
7
|
+
| `aggregate.ts` | Main class with `@RegisterAggregate` decorator |
|
|
8
|
+
| `definition.ts` | Validation, serialization, identity, and snapshot logic |
|
|
9
|
+
| `props.ts` | Internal state interface |
|
|
10
|
+
| `conditions.ts` | Zod validation rules (build + rebuild schemas) |
|
|
11
|
+
| `primitive.ts` | Public read shape (exposed to application layer) |
|
|
12
|
+
| `snapshot.ts` | Persistence shape for event sourcing / database storage |
|
|
13
|
+
| `payload.ts` | Serialization format for reconstruction |
|
|
14
|
+
| `security-token.ts` | Security token for snapshot integrity |
|
|
15
|
+
| `index.ts` | Barrel exports |
|
|
16
|
+
| `errors/index.ts` | Domain error types |
|
|
17
|
+
| `README.md` | Frontmatter metadata + narrative documentation |
|
|
18
|
+
| `aggregate.spec.ts` | Test file |
|
|
19
|
+
|
|
20
|
+
## What to Customize
|
|
21
|
+
|
|
22
|
+
### `props.ts` — Internal State
|
|
23
|
+
|
|
24
|
+
The `Props` interface defines the internal representation of this aggregate.
|
|
25
|
+
Aggregates have identity (`id: Uuid`) and a `version` field managed automatically.
|
|
26
|
+
|
|
27
|
+
**Checklist:**
|
|
28
|
+
- [ ] Verify property types match your domain model
|
|
29
|
+
- [ ] Update or add property descriptions in JSDoc
|
|
30
|
+
- [ ] Ensure all domain concepts are represented
|
|
31
|
+
|
|
32
|
+
### `conditions.ts` — Validation Rules
|
|
33
|
+
|
|
34
|
+
Zod validation schema that guards construction and reconstruction.
|
|
35
|
+
Aggregates have two schemas: `build` (for creation) and `rebuild` (for restoring from persistence).
|
|
36
|
+
|
|
37
|
+
**Checklist:**
|
|
38
|
+
- [ ] Review each validation rule in both `build` and `rebuild`
|
|
39
|
+
- [ ] Add custom refinements for domain-specific constraints
|
|
40
|
+
- [ ] Ensure the `id` and `version` conditions are present
|
|
41
|
+
|
|
42
|
+
### `primitive.ts` — Public API Shape
|
|
43
|
+
|
|
44
|
+
Defines what the application layer can read from this aggregate.
|
|
45
|
+
|
|
46
|
+
**Checklist:**
|
|
47
|
+
- [ ] Verify the public shape includes all necessary fields
|
|
48
|
+
- [ ] Ensure internal-only fields are excluded
|
|
49
|
+
|
|
50
|
+
### `snapshot.ts` — Persistence Shape
|
|
51
|
+
|
|
52
|
+
Defines the shape for persisting the aggregate (event sourcing, database storage).
|
|
53
|
+
This may differ from `Primitive` to include versioning metadata.
|
|
54
|
+
|
|
55
|
+
**Checklist:**
|
|
56
|
+
- [ ] Ensure the snapshot includes all fields needed for reconstruction
|
|
57
|
+
- [ ] Verify the version field is included for optimistic concurrency
|
|
58
|
+
|
|
59
|
+
### `definition.ts` — Identity, Snapshot & Serialization
|
|
60
|
+
|
|
61
|
+
Contains `getPrimitive()`, `getSnapshot()`, and lifecycle methods.
|
|
62
|
+
The base class handles identity and version management.
|
|
63
|
+
|
|
64
|
+
**Checklist:**
|
|
65
|
+
- [ ] Review `getSnapshot()` — does it capture all persistence-relevant fields?
|
|
66
|
+
- [ ] Review `getPrimitive()` — does it properly expose the public shape?
|
|
67
|
+
- [ ] Add custom methods for domain operations
|
|
68
|
+
- [ ] Add methods that mutate state (with proper version tracking)
|
|
69
|
+
|
|
70
|
+
### `errors/` — Domain Errors
|
|
71
|
+
|
|
72
|
+
Domain-specific errors that this aggregate can produce.
|
|
73
|
+
|
|
74
|
+
**Checklist:**
|
|
75
|
+
- [ ] Define custom error classes for each failure mode
|
|
76
|
+
- [ ] Register errors in `errors/index.ts`
|
|
77
|
+
|
|
78
|
+
### `aggregate.spec.ts` — Tests
|
|
79
|
+
|
|
80
|
+
The template includes tests for valid creation, snapshot save/restore, and
|
|
81
|
+
placeholder tests for error cases and invalid snapshots.
|
|
82
|
+
|
|
83
|
+
**Checklist:**
|
|
84
|
+
- [ ] The valid-creation test should already pass (green)
|
|
85
|
+
- [ ] The snapshot restore test should pass (green)
|
|
86
|
+
- [ ] Add a test for invalid snapshot restoration (tampered data)
|
|
87
|
+
- [ ] Add tests for domain operations and state mutations
|
|
88
|
+
- [ ] Add tests for error scenarios
|
|
89
|
+
|
|
90
|
+
### `README.md` — Narrative Documentation
|
|
91
|
+
|
|
92
|
+
Rich documentation rendered by ultra-reporter on the Docusaurus site.
|
|
93
|
+
|
|
94
|
+
**Checklist:**
|
|
95
|
+
- [ ] Fill the `Purpose` section — what is this aggregate for?
|
|
96
|
+
- [ ] Document `Domain Rules` — what invariants does it enforce?
|
|
97
|
+
- [ ] Add `Usage Examples` — how is it created and used?
|
|
98
|
+
- [ ] Document `Relationships` — to other domain artifacts
|
|
99
|
+
|
|
100
|
+
## What Not to Touch
|
|
101
|
+
|
|
102
|
+
These files are managed by scaffolding. Avoid direct edits:
|
|
103
|
+
|
|
104
|
+
| File | Reason |
|
|
105
|
+
|------|--------|
|
|
106
|
+
| `index.ts` | Barrel exports — regenerated on scaffold updates |
|
|
107
|
+
| `payload.ts` | Type derived from conditions — managed automatically |
|
|
108
|
+
| `security-token.ts` | Security token — managed by generator |
|
|
109
|
+
| `errors/index.ts` | Error re-exports — managed automatically |
|
|
110
|
+
|
|
111
|
+
## Validation & Errors
|
|
112
|
+
|
|
113
|
+
Aggregates use Zod for validation via `conditions.ts` with two schemas:
|
|
114
|
+
- `build`: Validates creation inputs, transforms with `setVersionOne`
|
|
115
|
+
- `rebuild`: Extends `build` with a required `version` field for restoring from persistence
|
|
116
|
+
|
|
117
|
+
## Testing
|
|
118
|
+
|
|
119
|
+
### TDD Cycle
|
|
120
|
+
|
|
121
|
+
Aggregates follow the red-green-refactor TDD loop:
|
|
122
|
+
|
|
123
|
+
1. **Red**: Write a failing test for an invalid input, state transition, or snapshot scenario
|
|
124
|
+
2. **Green**: Add the validation rule or domain logic to make it pass
|
|
125
|
+
3. **Refactor**: Clean up while keeping tests green
|
|
126
|
+
|
|
127
|
+
### Example
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// Test: aggregate creation with valid input
|
|
131
|
+
it('crear Order válida', async () => {
|
|
132
|
+
const payload: Payload = { customerId: 'abc-123', amount: 100 };
|
|
133
|
+
const result = Order.create(payload);
|
|
134
|
+
expect(result).toBeValid();
|
|
135
|
+
const aggregate = result.getValue();
|
|
136
|
+
expect(aggregate).toBeInstanceOf(Order);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Test: snapshot save and restore
|
|
140
|
+
it('restaurar snapshot', async () => {
|
|
141
|
+
const payload: Payload = { customerId: 'abc-123', amount: 100 };
|
|
142
|
+
const createResult = Order.create(payload);
|
|
143
|
+
expect(createResult).toBeValid();
|
|
144
|
+
const memento = createResult.getValue().takeMemento();
|
|
145
|
+
const mementoSerialized = memento.getValue().getPrimitive();
|
|
146
|
+
const restored = Order.restore(mementoSerialized);
|
|
147
|
+
expect(restored).toBeValid();
|
|
148
|
+
});
|
|
149
|
+
```
|