@ingeniomaps/cauce 0.53.2 → 0.54.0

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 (129) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +1 -1
  3. package/agents/README.md +24 -0
  4. package/agents/roles/system/accounting-specialist/SKILL.md +2 -0
  5. package/agents/roles/system/ai-governance-lead/SKILL.md +2 -0
  6. package/agents/roles/system/ai-product-manager/SKILL.md +2 -0
  7. package/agents/roles/system/analytics-engineer/SKILL.md +2 -0
  8. package/agents/roles/system/backend-engineer/SKILL.md +4 -2
  9. package/agents/roles/system/backend-engineer/learning/HISTORY.md +1 -0
  10. package/agents/roles/system/business-strategist/SKILL.md +4 -2
  11. package/agents/roles/system/cloud-architect/SKILL.md +5 -0
  12. package/agents/roles/system/cloud-architect/learning/HISTORY.md +4 -0
  13. package/agents/roles/system/community-manager/SKILL.md +2 -0
  14. package/agents/roles/system/content-specialist/SKILL.md +4 -2
  15. package/agents/roles/system/customer-success-manager/SKILL.md +9 -2
  16. package/agents/roles/system/customer-success-manager/learning/HISTORY.md +1 -0
  17. package/agents/roles/system/customer-support-specialist/SKILL.md +4 -2
  18. package/agents/roles/system/data-analyst/SKILL.md +9 -2
  19. package/agents/roles/system/data-analyst/learning/HISTORY.md +1 -0
  20. package/agents/roles/system/data-engineer/SKILL.md +2 -0
  21. package/agents/roles/system/data-governance-steward/SKILL.md +2 -0
  22. package/agents/roles/system/data-scientist/SKILL.md +2 -0
  23. package/agents/roles/system/database-administrator/SKILL.md +2 -0
  24. package/agents/roles/system/database-administrator/learning/HISTORY.md +1 -0
  25. package/agents/roles/system/developer-relations-engineer/SKILL.md +2 -0
  26. package/agents/roles/system/devops-engineer/SKILL.md +4 -2
  27. package/agents/roles/system/engineering-manager/SKILL.md +2 -0
  28. package/agents/roles/system/financial-controller/SKILL.md +4 -2
  29. package/agents/roles/system/finops-engineer/SKILL.md +2 -0
  30. package/agents/roles/system/finops-engineer/learning/HISTORY.md +1 -0
  31. package/agents/roles/system/finops-engineer/learning/sources.yaml +12 -0
  32. package/agents/roles/system/fraud-risk-analyst/SKILL.md +7 -0
  33. package/agents/roles/system/fraud-risk-analyst/learning/HISTORY.md +1 -0
  34. package/agents/roles/system/frontend-engineer/SKILL.md +8 -2
  35. package/agents/roles/system/frontend-engineer/evaluations/cases/09-comment-panel/InternalNote.jsx +30 -0
  36. package/agents/roles/system/frontend-engineer/evaluations/cases/09-comment-panel.md +10 -0
  37. package/agents/roles/system/frontend-engineer/learning/HISTORY.md +1 -0
  38. package/agents/roles/system/growth-marketer/SKILL.md +17 -0
  39. package/agents/roles/system/growth-marketer/evaluations/cases/08-briefing-de-referidos.md +23 -0
  40. package/agents/roles/system/growth-marketer/evaluations/expected-behaviors.yaml +1 -0
  41. package/agents/roles/system/growth-marketer/learning/HISTORY.md +3 -0
  42. package/agents/roles/system/implementation-manager/SKILL.md +10 -0
  43. package/agents/roles/system/implementation-manager/evaluations/cases/08-signed-cutover-runbook/plan-cutover-tesela-rev-b.md +70 -0
  44. package/agents/roles/system/implementation-manager/evaluations/cases/08-signed-cutover-runbook.md +12 -0
  45. package/agents/roles/system/implementation-manager/evaluations/expected-behaviors.yaml +1 -0
  46. package/agents/roles/system/implementation-manager/learning/HISTORY.md +5 -0
  47. package/agents/roles/system/integrations-engineer/SKILL.md +6 -4
  48. package/agents/roles/system/kyc-aml-specialist/SKILL.md +11 -4
  49. package/agents/roles/system/kyc-aml-specialist/learning/HISTORY.md +2 -0
  50. package/agents/roles/system/kyc-aml-specialist/learning/sources.yaml +76 -1
  51. package/agents/roles/system/legal-counsel/SKILL.md +2 -0
  52. package/agents/roles/system/logistics-operations-manager/SKILL.md +17 -0
  53. package/agents/roles/system/logistics-operations-manager/evaluations/cases/07-entrega-a-tiempo/api-seguimiento-andesexpress.md +40 -0
  54. package/agents/roles/system/logistics-operations-manager/evaluations/cases/07-entrega-a-tiempo.md +2 -3
  55. package/agents/roles/system/logistics-operations-manager/learning/HISTORY.md +2 -0
  56. package/agents/roles/system/machine-learning-engineer/SKILL.md +2 -0
  57. package/agents/roles/system/mlops-engineer/SKILL.md +2 -0
  58. package/agents/roles/system/mobile-engineer/SKILL.md +4 -2
  59. package/agents/roles/system/partnerships-manager/SKILL.md +2 -0
  60. package/agents/roles/system/people-operations-manager/SKILL.md +2 -0
  61. package/agents/roles/system/privacy-compliance-specialist/SKILL.md +4 -2
  62. package/agents/roles/system/procurement-manager/SKILL.md +2 -0
  63. package/agents/roles/system/product-manager/SKILL.md +2 -0
  64. package/agents/roles/system/product-marketing-manager/SKILL.md +9 -2
  65. package/agents/roles/system/product-marketing-manager/learning/HISTORY.md +1 -0
  66. package/agents/roles/system/project-manager/SKILL.md +2 -0
  67. package/agents/roles/system/qa-engineer/SKILL.md +11 -2
  68. package/agents/roles/system/qa-engineer/evaluations/cases/07-agent-test-repair.md +1 -1
  69. package/agents/roles/system/qa-engineer/evaluations/cases/11-accessibility-sampling.md +10 -0
  70. package/agents/roles/system/qa-engineer/evaluations/cases/12-quoted-from-a-summary/resumen-legal-wcag22.md +28 -0
  71. package/agents/roles/system/qa-engineer/evaluations/cases/12-quoted-from-a-summary.md +10 -0
  72. package/agents/roles/system/qa-engineer/evaluations/cases/13-matrix-from-a-summary/wiki-plataforma-conformidad.md +24 -0
  73. package/agents/roles/system/qa-engineer/evaluations/cases/13-matrix-from-a-summary.md +10 -0
  74. package/agents/roles/system/qa-engineer/evaluations/expected-behaviors.yaml +2 -0
  75. package/agents/roles/system/qa-engineer/learning/HISTORY.md +4 -0
  76. package/agents/roles/system/qa-engineer/learning/sources.yaml +24 -3
  77. package/agents/roles/system/release-manager/SKILL.md +5 -3
  78. package/agents/roles/system/release-manager/evaluations/cases/09-provenance-without-origin.md +12 -0
  79. package/agents/roles/system/release-manager/learning/HISTORY.md +1 -0
  80. package/agents/roles/system/release-manager/references/operating-model.md +8 -0
  81. package/agents/roles/system/sales-representative/SKILL.md +4 -2
  82. package/agents/roles/system/security-engineer/SKILL.md +4 -2
  83. package/agents/roles/system/security-engineer/learning/HISTORY.md +1 -0
  84. package/agents/roles/system/site-reliability-engineer/SKILL.md +4 -2
  85. package/agents/roles/system/software-architect/SKILL.md +4 -2
  86. package/agents/roles/system/solutions-engineer/SKILL.md +2 -0
  87. package/agents/roles/system/tech-lead/SKILL.md +2 -0
  88. package/agents/roles/system/technical-program-manager/SKILL.md +2 -0
  89. package/agents/roles/system/technical-writer/SKILL.md +2 -0
  90. package/agents/roles/system/treasury-analyst/SKILL.md +6 -4
  91. package/agents/roles/system/ui-designer/SKILL.md +15 -0
  92. package/agents/roles/system/ui-designer/learning/HISTORY.md +2 -0
  93. package/agents/roles/system/user-researcher/SKILL.md +6 -0
  94. package/agents/roles/system/user-researcher/learning/HISTORY.md +1 -0
  95. package/agents/roles/system/ux-designer/SKILL.md +2 -0
  96. package/automatization/shared/eval-measured.js +35 -0
  97. package/automatization/shared/eval-only.js +15 -0
  98. package/automatization/workflows/README.md +27 -0
  99. package/automatization/workflows/agent-eval.js +42 -7
  100. package/automatization/workflows/agent-promote.js +65 -15
  101. package/automatization/workflows/autobuild.js +52 -8
  102. package/automatization/workflows/flow-eval.js +27 -7
  103. package/engine/agents/catalog.js +1 -1
  104. package/engine/agents/fork.js +1 -1
  105. package/engine/agents/learning-files.js +7 -2
  106. package/engine/agents/learning-seal.js +123 -0
  107. package/engine/agents/learning-sources.js +33 -3
  108. package/engine/agents/learning.js +80 -87
  109. package/engine/automation/hooks.js +0 -1
  110. package/engine/automation/index.js +0 -2
  111. package/engine/cli/args.js +2 -2
  112. package/engine/cli/catalog.js +33 -4
  113. package/engine/cli/instance.js +0 -2
  114. package/engine/cli/ops.js +2 -18
  115. package/engine/config/validate.js +7 -2
  116. package/engine/core/onboarding.js +0 -3
  117. package/engine/core/scan.js +1 -1
  118. package/engine/hooks/input.js +1 -1
  119. package/engine/integrations/proposals.js +1 -1
  120. package/engine/integrations/providers/jira.js +1 -1
  121. package/engine/integrations/registry.js +0 -1
  122. package/engine/planning/business-rules.js +1 -1
  123. package/engine/planning/contracts.js +8 -1
  124. package/engine/planning/parser.js +7 -1
  125. package/engine/schemas/ops-config.schema.json +60 -13
  126. package/flows/system/incident-review/flow.json +1 -1
  127. package/flows/system/incident-review/learning/HISTORY.md +1 -0
  128. package/package.json +4 -3
  129. package/template/planning/rules/system/conduct.md +19 -0
@@ -45,10 +45,15 @@ function validateWorkspaces(workspaces, errors) {
45
45
  continue
46
46
  }
47
47
  for (const key of Object.keys(workspace)) {
48
- if (!['name', 'path'].includes(key)) {
48
+ if (!['name', 'path', 'verify'].includes(key)) {
49
49
  errors.push(`ops.config.json: workspaceRoots[${index}].${key} no está permitido`)
50
50
  }
51
51
  }
52
+ // Opcional: la raíz que no lo declara deja que quien verifica descubra la puerta, como siempre.
53
+ // Declararlo vacío es peor que no declararlo —promete una puerta y no la da—, así que se rechaza.
54
+ if ('verify' in workspace && (typeof workspace.verify !== 'string' || !workspace.verify.trim())) {
55
+ errors.push(`ops.config.json: workspaceRoots[${index}].verify debe ser el comando, o no estar`)
56
+ }
52
57
  if (typeof workspace.name !== 'string' || !workspace.name.trim()) {
53
58
  errors.push(`ops.config.json: workspaceRoots[${index}].name es obligatorio`)
54
59
  }
@@ -78,4 +83,4 @@ function validateRunner(runner, errors) {
78
83
  }
79
84
  }
80
85
 
81
- module.exports = { MODES, validateOpsConfig }
86
+ module.exports = { validateOpsConfig }
@@ -120,8 +120,5 @@ module.exports = {
120
120
  missingSections,
121
121
  orphanCredentials,
122
122
  guide,
123
- OPENING,
124
- DIMENSIONS,
125
- FOLLOW_UPS,
126
123
  PLACEHOLDERS,
127
124
  }
@@ -218,4 +218,4 @@ module.exports = {
218
218
  workspaceRoots,
219
219
  candidates,
220
220
  inventory,
221
- commandsLine, scan, services, expectedEnv, IGNORED, DEPTH, ENV_MAX }
221
+ commandsLine, scan, services }
@@ -124,6 +124,6 @@ function findOpsRoot(start) {
124
124
  }
125
125
 
126
126
  module.exports = {
127
- readInput, commandOf, fileOf, patchOf, filesOf, contentOf, cwdOf, block, configOf,
127
+ readInput, commandOf, patchOf, filesOf, contentOf, cwdOf, block, configOf,
128
128
  gitDirectory, isCommit, stagedFiles, pushAllowed, findOpsRoot,
129
129
  }
@@ -79,4 +79,4 @@ function validate(root, provider, workspaces = []) {
79
79
  return errors
80
80
  }
81
81
 
82
- module.exports = { STATES, TYPES, read, validate }
82
+ module.exports = { read, validate }
@@ -161,4 +161,4 @@ async function fetchItems(config, options = {}) {
161
161
  return issues.map((issue) => normalizeIssue(issue, config))
162
162
  }
163
163
 
164
- module.exports = { adfToMarkdown, deriveAcceptance, fetchItems, normalizeFixture, normalizeIssue, validateConfig }
164
+ module.exports = { fetchItems, normalizeFixture, validateConfig }
@@ -397,7 +397,6 @@ function providerState(root, name) {
397
397
 
398
398
  module.exports = {
399
399
  providerState,
400
- STATES,
401
400
  adapter,
402
401
  frontmatter,
403
402
  promote,
@@ -53,4 +53,4 @@ function validate(root) {
53
53
  return errors
54
54
  }
55
55
 
56
- module.exports = { markdownFiles, validate }
56
+ module.exports = { validate }
@@ -297,6 +297,14 @@ function validateState({ epics, milestones, done, wip, roles = new Set(), humanA
297
297
  for (const milestone of milestones) {
298
298
  if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(milestone.slug)) errors.push(`hito con slug inválido: ${milestone.slug}`)
299
299
  if (milestoneSlugs.has(milestone.slug)) errors.push(`hito duplicado: ${milestone.slug}`)
300
+ // La misma puerta que la épica y la tarea, en el nivel que no la tenía. Un hito agrupa trabajo bajo
301
+ // un nombre, y abrirlo con el nombre puesto para después es el camino natural: nadie promueve una
302
+ // tarea sin aceptación, y en cambio el título del hito se decide al final, cuando ya se construyó
303
+ // debajo. El marcador es lo único que se puede juzgar sin leer — un título vago sigue pasando, y
304
+ // eso es deliberado: acá también un heurístico sobre prosa se equivocaría en los dos sentidos.
305
+ if (PLACEHOLDERS.test(milestone.title)) {
306
+ errors.push(`hito ${milestone.slug}: el título no está decidido — "${milestone.title}"`)
307
+ }
300
308
  milestoneSlugs.add(milestone.slug)
301
309
  for (const task of milestone.tasks) {
302
310
  if (!task.service) errors.push(`BACKLOG ${task.slug}: falta (service: <ruta>)`)
@@ -406,7 +414,6 @@ function oversizedUnits({ epics = [], milestones = [] }) {
406
414
  }
407
415
 
408
416
  module.exports = {
409
- testedCriteria,
410
417
  validateState,
411
418
  oversizedUnits,
412
419
  validateAdr,
@@ -153,6 +153,12 @@ function readCast(rest) {
153
153
  }
154
154
  }
155
155
 
156
+ // El texto de la aceptación, delimitado por las cursivas que lo envuelven. El cierre no es «el
157
+ // próximo guión bajo»: un identificador como `MAX_ATTEMPTS` trae los suyos, y cortar en el primero
158
+ // devolvía `MAX` con `check` en verde, que es la forma cara del error —la tarea se lee completa y no
159
+ // lo está—. Cierra el `_` que markdown cerraría: el que no está entre caracteres de palabra.
160
+ const ACCEPTANCE = /_Aceptaci[oó]n:\s*(.*?\S)_(?![A-Za-z0-9])/i
161
+
156
162
  function readBacklog(dir) {
157
163
  const text = withoutComments(read(path.join(dir, 'BACKLOG.md')))
158
164
  const milestones = []
@@ -175,7 +181,7 @@ function readBacklog(dir) {
175
181
  slug: task[1].trim(), tier: task[2] || '', cast: readCast(rest),
176
182
  epic: ((rest.match(/\(epic:\s*(\d{3})\)/) || [])[1] || ''),
177
183
  service: ((rest.match(/\(service:\s*([^)]+)\)/) || [])[1] || '').trim(),
178
- acceptance: ((rest.match(/_Aceptaci[oó]n:\s*([^_]+)_/i) || [])[1] || '').trim(),
184
+ acceptance: ((rest.match(ACCEPTANCE) || [])[1] || '').trim(),
179
185
  criteria: criteriaRefs(rest),
180
186
  noSplit: noSplitReason(rest),
181
187
  })
@@ -2,33 +2,80 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "title": "Cauce engine configuration",
4
4
  "type": "object",
5
- "required": ["project", "mode", "workspaceRoots", "runner"],
5
+ "required": [
6
+ "project",
7
+ "mode",
8
+ "workspaceRoots",
9
+ "runner"
10
+ ],
6
11
  "properties": {
7
- "$schema": { "type": "string", "minLength": 1 },
8
- "cauceVersion": { "type": "string", "minLength": 1 },
9
- "project": { "type": "string", "minLength": 1 },
10
- "mode": { "enum": ["embedded", "sidecar", "toolkit"] },
12
+ "$schema": {
13
+ "type": "string",
14
+ "minLength": 1
15
+ },
16
+ "cauceVersion": {
17
+ "type": "string",
18
+ "minLength": 1
19
+ },
20
+ "project": {
21
+ "type": "string",
22
+ "minLength": 1
23
+ },
24
+ "mode": {
25
+ "enum": [
26
+ "embedded",
27
+ "sidecar",
28
+ "toolkit"
29
+ ]
30
+ },
11
31
  "workspaceRoots": {
12
32
  "type": "array",
13
33
  "minItems": 1,
14
34
  "items": {
15
35
  "type": "object",
16
- "required": ["name", "path"],
36
+ "required": [
37
+ "name",
38
+ "path"
39
+ ],
17
40
  "properties": {
18
- "name": { "type": "string", "minLength": 1 },
19
- "path": { "type": "string", "minLength": 1 }
41
+ "name": {
42
+ "type": "string",
43
+ "minLength": 1
44
+ },
45
+ "path": {
46
+ "type": "string",
47
+ "minLength": 1
48
+ },
49
+ "verify": {
50
+ "type": "string",
51
+ "description": "Comando que corre la puerta de esta raíz —pruebas, lint, typecheck, build—, tal como se invoca desde ella. Sin él, quien verifica tiene que descubrirlo leyendo el repositorio en cada tarea, y eso es trabajo de modelo repetido para siempre sobre una respuesta que no cambia."
52
+ }
20
53
  },
21
54
  "additionalProperties": false
22
55
  }
23
56
  },
24
57
  "runner": {
25
58
  "type": "object",
26
- "required": ["maxTaskHours", "humanCheckpointBetweenMilestones", "commitPerTask", "allowPush"],
59
+ "required": [
60
+ "maxTaskHours",
61
+ "humanCheckpointBetweenMilestones",
62
+ "commitPerTask",
63
+ "allowPush"
64
+ ],
27
65
  "properties": {
28
- "maxTaskHours": { "type": "number", "exclusiveMinimum": 0 },
29
- "humanCheckpointBetweenMilestones": { "type": "boolean" },
30
- "commitPerTask": { "type": "boolean" },
31
- "allowPush": { "type": "boolean" }
66
+ "maxTaskHours": {
67
+ "type": "number",
68
+ "exclusiveMinimum": 0
69
+ },
70
+ "humanCheckpointBetweenMilestones": {
71
+ "type": "boolean"
72
+ },
73
+ "commitPerTask": {
74
+ "type": "boolean"
75
+ },
76
+ "allowPush": {
77
+ "type": "boolean"
78
+ }
32
79
  },
33
80
  "additionalProperties": false
34
81
  }
@@ -60,7 +60,7 @@
60
60
  "No se atribuye responsabilidad a personas; se analizan condiciones, no culpables.",
61
61
  "Una causa sin evidencia se declara como hipótesis, aunque cerrar el informe sea más cómodo.",
62
62
  "Ninguna comunicación a clientes ni notificación regulatoria sale de este recorrido: se propone y la decide una persona.",
63
- "Los seguimientos quedan en el INBOX sin promover; convertirlos en trabajo es una decisión humana."
63
+ "Los seguimientos quedan en el INBOX sin promover y cada uno dice si previene la repetición o sólo acelera la detección; convertirlos en trabajo es una decisión humana, y esa distinción es lo único que permite ordenarlos."
64
64
  ],
65
65
  "completion": [
66
66
  "La línea de tiempo está sostenida por registros, no por reconstrucción de memoria.",
@@ -4,3 +4,4 @@ Registrar únicamente cambios aprobados por una persona, con fecha, la corrida q
4
4
 
5
5
  | Fecha | Propuesta | Decisión | Aprobó | Cambio aplicado |
6
6
  |---|---|---|---|---|
7
+ | 2026-08-30 | `2026-08.md` | aplicada | Manuel Pinzon | Un guardrail, y sólo su texto: cada seguimiento dice si previene la repetición o sólo acelera la detección. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.53.2",
3
+ "version": "0.54.0",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "keywords": [
6
6
  "planning",
@@ -33,8 +33,9 @@
33
33
  "test": "bash test/tools/hooks-smoke.sh && node --test \"test/**/*.test.js\"",
34
34
  "coverage": "bash test/tools/coverage.sh",
35
35
  "coverage:update": "bash test/tools/coverage.sh --update",
36
- "dead-imports": "node test/tools/dead-imports.js",
37
- "ci": "npm run check && npm run automation:check && npm run integration:check && npm run coverage",
36
+ "dead-code": "node test/tools/dead-code.js",
37
+ "dead-code:engine": "node test/tools/dead-code.js --engine",
38
+ "ci": "npm run check && npm run automation:check && npm run integration:check && npm run dead-code:engine && npm run coverage",
38
39
  "prepublishOnly": "npm run ci"
39
40
  },
40
41
  "engines": {
@@ -28,6 +28,25 @@ deja el pedido sin resolver: es la mitad barata del trabajo.
28
28
  - Nombrar lo que falta no reemplaza a entregar lo que se puede: lo que sí se pudo establecer se escribe
29
29
  igual, aunque quede parcial y marcado como tal.
30
30
 
31
+ El primer punto tiene un borde que se cruza sin notarlo. Faltar contexto es no saber **cómo**: qué
32
+ formato, qué borde, qué valor. Eso se supone y se entrega marcado, porque suponerlo mal cuesta una
33
+ corrección. No saber **qué se quiere ni para qué** es otra cosa, y ahí el borrador deja de ser barato:
34
+ todo lo que se construya encima hereda la suposición, y quien lo reciba no tiene cómo ver que el
35
+ objetivo era supuesto. El para qué tampoco es adorno — es lo que permite reconocer una respuesta
36
+ correcta, y sin él se cumple la aceptación al pie y no sirve.
37
+
38
+ Lo que separa los dos casos es si la respuesta existe en algún lado. Si está escrita —en la aceptación,
39
+ en el criterio que la unidad cita, en el contexto de la épica, en el código— entonces la unidad se
40
+ entiende y lo que falta es leerla: eso lo hace quien ejecuta y no interrumpe a nadie. Si contestarla
41
+ exigiera inventarla, no hay nada que leer y es una decisión que el cargo no tiene: se escala con la
42
+ pregunta exacta y con qué se desbloquea al contestarla. Es el mismo criterio con que R6 reparte el
43
+ hallazgo que aparece a mitad de camino —quién puede resolverlo, no cuán grave parece—, aplicado antes
44
+ de empezar en vez de durante.
45
+
46
+ Aclarar la redacción no es ampliar el alcance, y partir tampoco: una unidad que no se entiende porque
47
+ son dos resultados con vidas distintas se entiende partida, y eso no pide ninguna autoridad que el
48
+ cargo no tenga (R17). La pide elegir el objetivo, que es lo único que no se puede suponer.
49
+
31
50
  Esto no afloja ningún límite: no promover, no prometer fechas, no inventar evidencia y no exceder la
32
51
  autoridad del cargo siguen siendo absolutos. Lo que se cierra es la salida de cumplirlos sin entregar.
33
52