paperclip-plugin-autopilot-ops 0.1.0 → 0.1.6

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 CHANGED
@@ -16,18 +16,20 @@ Arquitectura completa: documento *Arquitectura Autopilot Care sobre Paperclip*.
16
16
  | --- | --- | --- |
17
17
  | Workflows | `src/workflows.ts` | Estados, tabla de transiciones, quién puede ejecutar cada una, validaciones puras. Sin IA. |
18
18
  | Registro de negocio | `migrations/001_autopilot_ops.sql`, `src/ops.ts` | Tablas `caso`, `transicion`, `accion`, `politica`, `politica_historial` en el namespace del plugin. Todo lleva `company_id`. |
19
- | Herramientas para agentes | `src/worker.ts` (`ctx.tools`) | `ops_listar_casos`, `ops_leer_caso`, `ops_abrir_caso`, `ops_transicionar`, `ops_registrar_accion`, `ops_consultar_indicador`. Pasan por el tool gateway. |
20
- | Gobierno | `politica` + UI | Modo por workflow e institución: `corte` · `observa` · `propone` · `ejecuta`. Default `propone`. |
19
+ | Herramientas para agentes | `src/worker.ts` (`ctx.tools`) | `ops_listar_casos`, `ops_leer_caso`, `ops_abrir_caso`, `ops_transicionar`, `ops_registrar_accion`, `ops_consultar_indicador`, `ops_publicar_tablero`, `ops_listar_tableros`. Pasan por el tool gateway. |
20
+ | Tableros del hospital | `migrations/002_tableros.sql`, `src/tableros.ts` | Tabla `tablero`: lo que publica el Agente de tableros sobre los datos de Alephoo (clave estable, título, período, fuentes, widgets). El plugin valida la forma de los widgets; el portal los dibuja. |
21
+ | Gobierno | `politica` + UI | Modo por workflow e institución: `corte` · `observa` · `propone` · `ejecuta` · `autonomo` (aprobación por excepción: salta a aprobado salvo que una regla de excepción se dispare: variación > 20 %, sin valor actual, reintento tras diferencias, baja de valor). Default `propone`. |
21
22
  | Tablero del director | `src/ui/index.tsx` | Pantalla `/<empresa>/autopilot`: horas absorbidas, pendientes de aprobación con Aprobar / Rechazar, estado por puesto, políticas y corte. |
22
- | API para el portal | `apiRoutes` (auth `board`) | `GET /tablero`, `GET /casos`, `GET /casos/:id`, `POST /casos/:id/aprobar`, `POST /casos/:id/rechazar`, `GET /politicas`, `POST /politicas`. Montadas en `/api/plugins/alephoo.autopilot-ops/api/*`. |
23
+ | API para el portal | `apiRoutes` (auth `board`) | `GET /tablero`, `GET /serie`, `GET /casos`, `GET /casos/:id`, `POST /casos/:id/aprobar`, `POST /casos/:id/rechazar`, `POST /casos/:id/cargado`, `GET /politicas`, `GET /politicas/historial`, `POST /politicas`, `GET /tableros`, `GET /tableros/:clave`, `GET /version`. Montadas en `/api/plugins/alephoo.autopilot-ops/api/*`. |
23
24
 
24
25
  ### Workflows incluidos
25
26
 
26
27
  **`actualizacion_arancel`** (puesto Convenios y facturación, 25 min absorbidos por caso)
27
28
 
28
29
  ```
29
- detectado ─proponer(agente)→ pendiente_aprobacion ─aprobar(humano)→ aprobado ─aplicar(agente, modo ejecuta)→ aplicado ─verificar→ verificado
30
- └rechazar(humano)→ rechazado └→ con_diferencias ─proponer→ …
30
+ detectado ─proponer(agente)→ pendiente_aprobacion ─aprobar(humano)→ aprobado ─aplicar(agente en ejecuta, o persona: carga manual)→ aplicado ─verificar→ verificado
31
+ └rechazar(humano)→ rechazado └→ con_diferencias ─proponer→ …
32
+ └corregir(persona)→ aplicado
31
33
  ```
32
34
 
33
35
  Validaciones de `proponer`: valor nuevo > 0, vigencia `AAAA-MM-DD`, fuente
@@ -51,6 +53,60 @@ releído con el aprobado y decide el destino.
51
53
  activity log de Paperclip.
52
54
  - `idempotencyKey` en `ops_abrir_caso` y `ops_transicionar` hace los reintentos
53
55
  seguros; `referencia` evita abrir dos casos sobre el mismo objeto.
56
+ - Quien carga no se controla a sí mismo: una carga manual la comprueba después
57
+ el agente releyendo el sistema (`verificar`).
58
+
59
+ ### Carga manual del equipo del hospital (0.1.5)
60
+
61
+ En `propone` el agente no escribe en Alephoo: lo aprobado lo carga una persona
62
+ del hospital. El portal lo muestra en **Para cargar** y la persona lo marca con
63
+ `POST /casos/:id/cargado` (`valorCargado?`, `comentario?`, `decididoPor`,
64
+ `idempotencyKey?`), o la acción `marcar-cargado` desde la UI de Paperclip:
65
+
66
+ - El plugin registra una **escritura manual** (`conector: "manual"`) con su
67
+ evidencia (`cargado_por`, `valor_cargado`, `valor_aprobado`, `vigencia_desde`,
68
+ `nota`) y mueve el caso con la transición de carga de su estado: `aplicar`
69
+ desde `aprobado`, o `corregir` desde `con_diferencias` (una carga que no
70
+ coincidió se corrige y se vuelve a comprobar sin otra aprobación, porque el
71
+ valor aprobado no cambia; `corregir` es solo humana y descarta la lectura anterior).
72
+ - Antes de escribir evalúa la transición; si el caso no está para cargar,
73
+ responde `estado_invalido` con el motivo y no toca nada.
74
+ - Después el agente comprueba: lee el valor en Alephoo, registra la
75
+ verificación y llama `verificar` con `datos.valor_leido`. El portal se lo pide
76
+ con una tarea en Paperclip (`Comprobar carga: …`, asignada al agente del caso).
77
+ - `GET /version` devuelve `{version, capacidades: ["carga-manual"]}`: el portal
78
+ lo usa para saber si el plugin instalado ya registra cargas.
79
+
80
+ ### Tableros publicados por agentes (0.1.4)
81
+
82
+ El Agente de tableros no mueve casos: lee Alephoo por API, calcula lo que pidió
83
+ la dirección y publica el resultado con `ops_publicar_tablero`:
84
+
85
+ ```json
86
+ {
87
+ "clave": "turnos-ausentismo",
88
+ "titulo": "Turnos y ausentismo por servicio",
89
+ "pedido": "Quiero ver cuántos turnos damos por servicio y cuántos pacientes faltan",
90
+ "periodo": "septiembre 2026",
91
+ "fuentes": ["Alephoo · api-consultas · turnos 01/09–30/09"],
92
+ "widgets": [
93
+ { "tipo": "indicador", "etiqueta": "Turnos dados", "valor": 1842, "contexto": "22 días hábiles", "tono": "senal" },
94
+ { "tipo": "barras", "titulo": "Turnos por servicio", "series": [{ "etiqueta": "Clínica", "valor": 620 }] },
95
+ { "tipo": "linea", "titulo": "Turnos por día", "puntos": [{ "x": "2026-09-01", "y": 61 }] },
96
+ { "tipo": "tabla", "titulo": "Más ausentes", "columnas": ["Profesional", "Ausentes"], "filas": [["Dra. Medina", 14]] },
97
+ { "tipo": "texto", "titulo": "Lectura", "texto": "El ausentismo baja 1,5 puntos." }
98
+ ],
99
+ "issueId": "<uuid de la tarea que lo pidió>"
100
+ }
101
+ ```
102
+
103
+ - `clave` es estable: volver a publicar con la misma clave actualiza el tablero
104
+ en el lugar y suma una versión (`ops_listar_tableros` muestra las existentes).
105
+ - Tipos de widget: `indicador`, `barras`, `linea`, `tabla`, `texto`; `ancho` 1–3
106
+ opcional. La validación devuelve todos los problemas juntos
107
+ (`tablero_invalido: widgets[2].filas[0] tiene 1 celdas y la tabla 2 columnas`).
108
+ - El portal del hospital los muestra en la sección **Tableros**; los pedidos de
109
+ la dirección llegan como tareas de Paperclip con título `Tablero: …`.
54
110
 
55
111
  ## Desarrollo
56
112
 
package/dist/manifest.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/manifest.ts
2
2
  var PLUGIN_ID = "alephoo.autopilot-ops";
3
- var PLUGIN_VERSION = "0.1.0";
3
+ var PLUGIN_VERSION = "0.1.6";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
@@ -9,10 +9,14 @@ var TOOL_NAMES = {
9
9
  abrirCaso: "ops_abrir_caso",
10
10
  transicionar: "ops_transicionar",
11
11
  registrarAccion: "ops_registrar_accion",
12
- consultarIndicador: "ops_consultar_indicador"
12
+ consultarIndicador: "ops_consultar_indicador",
13
+ publicarTablero: "ops_publicar_tablero",
14
+ listarTableros: "ops_listar_tableros"
13
15
  };
14
16
  var DATA_KEYS = {
15
17
  tablero: "tablero",
18
+ serie: "serie",
19
+ historialPoliticas: "historial-politicas",
16
20
  casos: "casos",
17
21
  caso: "caso",
18
22
  politicas: "politicas",
@@ -21,6 +25,7 @@ var DATA_KEYS = {
21
25
  var ACTION_KEYS = {
22
26
  aprobar: "aprobar",
23
27
  rechazar: "rechazar",
28
+ marcarCargado: "marcar-cargado",
24
29
  cambiarPolitica: "cambiar-politica",
25
30
  abrirCaso: "abrir-caso"
26
31
  };
@@ -29,7 +34,7 @@ var manifest = {
29
34
  apiVersion: 1,
30
35
  version: PLUGIN_VERSION,
31
36
  displayName: "Autopilot Care",
32
- description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / corte) y tablero del director.",
37
+ description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, tableros de gesti\xF3n publicados por agentes y panel del director.",
33
38
  author: "Alephoo",
34
39
  categories: ["automation", "ui"],
35
40
  capabilities: [
@@ -79,7 +84,7 @@ var manifest = {
79
84
  {
80
85
  name: TOOL_NAMES.abrirCaso,
81
86
  displayName: "Abrir caso",
82
- description: "Abre un caso nuevo en un workflow, en su estado inicial. `referencia` identifica el objeto real (convenio, cuenta, profesional) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.",
87
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
83
88
  parametersSchema: {
84
89
  type: "object",
85
90
  properties: {
@@ -87,7 +92,8 @@ var manifest = {
87
92
  referencia: { type: "string" },
88
93
  titulo: { type: "string" },
89
94
  datos: { type: "object" },
90
- idempotencyKey: { type: "string" }
95
+ idempotencyKey: { type: "string" },
96
+ issueId: { type: "string", description: "Tarea de Paperclip que origina el caso (opcional; UUID)." }
91
97
  },
92
98
  required: ["workflow", "titulo"]
93
99
  }
@@ -95,7 +101,7 @@ var manifest = {
95
101
  {
96
102
  name: TOOL_NAMES.transicionar,
97
103
  displayName: "Transicionar caso",
98
- description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar) no est\xE1n disponibles para agentes.",
104
+ description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo.",
99
105
  parametersSchema: {
100
106
  type: "object",
101
107
  properties: {
@@ -139,6 +145,31 @@ var manifest = {
139
145
  },
140
146
  required: ["indicador"]
141
147
  }
148
+ },
149
+ {
150
+ name: TOOL_NAMES.publicarTablero,
151
+ displayName: "Publicar tablero",
152
+ description: "Publica o actualiza un tablero de gesti\xF3n para la direcci\xF3n del hospital, armado sobre datos reales de Alephoo (turnos, facturaci\xF3n, internaci\xF3n, producci\xF3n). `clave` identifica el tablero de forma estable (min\xFAsculas y guiones; volver a publicar con la misma clave lo actualiza en el lugar). `widgets` es la lista de piezas que se muestran, en orden: {tipo:'indicador', etiqueta, valor, unidad?, contexto?, tono?: neutro|ambar|senal|corte} \xB7 {tipo:'barras', titulo, unidad?, series:[{etiqueta, valor}]} \xB7 {tipo:'linea', titulo, unidad?, puntos:[{x, y}]} \xB7 {tipo:'tabla', titulo, columnas:[\u2026], filas:[[\u2026]]} \xB7 {tipo:'texto', titulo?, texto}. Cada widget admite `ancho` 1, 2 o 3 (columnas de 3). `fuentes` lista qu\xE9 se consult\xF3 (p. ej. 'Alephoo \xB7 api-consultas \xB7 turnos 01/09\u201330/09'). Si el pedido vino de una tarea, pasar `issueId`.",
153
+ parametersSchema: {
154
+ type: "object",
155
+ properties: {
156
+ clave: { type: "string" },
157
+ titulo: { type: "string" },
158
+ descripcion: { type: "string" },
159
+ pedido: { type: "string", description: "Qu\xE9 pidi\xF3 la direcci\xF3n, en sus palabras." },
160
+ periodo: { type: "string", description: "Per\xEDodo que cubren los datos, p. ej. 'septiembre 2026'." },
161
+ fuentes: { type: "array", items: { type: "string" } },
162
+ widgets: { type: "array", items: { type: "object" } },
163
+ issueId: { type: "string", description: "Tarea de Paperclip que origin\xF3 el tablero (opcional; UUID)." }
164
+ },
165
+ required: ["clave", "titulo", "widgets"]
166
+ }
167
+ },
168
+ {
169
+ name: TOOL_NAMES.listarTableros,
170
+ displayName: "Listar tableros",
171
+ description: "Lista los tableros publicados para esta instituci\xF3n (clave, t\xEDtulo, per\xEDodo, fuentes, cu\xE1ndo se actualiz\xF3 y cu\xE1ntos widgets tiene). Usar antes de publicar para reutilizar la clave de un tablero existente en vez de crear uno nuevo. Solo lectura.",
172
+ parametersSchema: { type: "object", properties: {} }
142
173
  }
143
174
  ],
144
175
  apiRoutes: [
@@ -182,6 +213,38 @@ var manifest = {
182
213
  capability: "api.routes.register",
183
214
  companyResolution: { from: "body", key: "companyId" }
184
215
  },
216
+ {
217
+ routeKey: "marcar-cargado",
218
+ method: "POST",
219
+ path: "/casos/:casoId/cargado",
220
+ auth: "board",
221
+ capability: "api.routes.register",
222
+ companyResolution: { from: "body", key: "companyId" }
223
+ },
224
+ {
225
+ routeKey: "version",
226
+ method: "GET",
227
+ path: "/version",
228
+ auth: "board",
229
+ capability: "api.routes.register",
230
+ companyResolution: { from: "query", key: "companyId" }
231
+ },
232
+ {
233
+ routeKey: "serie",
234
+ method: "GET",
235
+ path: "/serie",
236
+ auth: "board",
237
+ capability: "api.routes.register",
238
+ companyResolution: { from: "query", key: "companyId" }
239
+ },
240
+ {
241
+ routeKey: "historial-politicas",
242
+ method: "GET",
243
+ path: "/politicas/historial",
244
+ auth: "board",
245
+ capability: "api.routes.register",
246
+ companyResolution: { from: "query", key: "companyId" }
247
+ },
185
248
  {
186
249
  routeKey: "politicas",
187
250
  method: "GET",
@@ -197,6 +260,22 @@ var manifest = {
197
260
  auth: "board",
198
261
  capability: "api.routes.register",
199
262
  companyResolution: { from: "body", key: "companyId" }
263
+ },
264
+ {
265
+ routeKey: "tableros",
266
+ method: "GET",
267
+ path: "/tableros",
268
+ auth: "board",
269
+ capability: "api.routes.register",
270
+ companyResolution: { from: "query", key: "companyId" }
271
+ },
272
+ {
273
+ routeKey: "tablero-publicado",
274
+ method: "GET",
275
+ path: "/tableros/:clave",
276
+ auth: "board",
277
+ capability: "api.routes.register",
278
+ companyResolution: { from: "query", key: "companyId" }
200
279
  }
201
280
  ],
202
281
  ui: {
package/dist/ui/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  // src/manifest.ts
10
10
  var PLUGIN_ID = "alephoo.autopilot-ops";
11
- var PLUGIN_VERSION = "0.1.0";
11
+ var PLUGIN_VERSION = "0.1.6";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
@@ -17,10 +17,14 @@ var TOOL_NAMES = {
17
17
  abrirCaso: "ops_abrir_caso",
18
18
  transicionar: "ops_transicionar",
19
19
  registrarAccion: "ops_registrar_accion",
20
- consultarIndicador: "ops_consultar_indicador"
20
+ consultarIndicador: "ops_consultar_indicador",
21
+ publicarTablero: "ops_publicar_tablero",
22
+ listarTableros: "ops_listar_tableros"
21
23
  };
22
24
  var DATA_KEYS = {
23
25
  tablero: "tablero",
26
+ serie: "serie",
27
+ historialPoliticas: "historial-politicas",
24
28
  casos: "casos",
25
29
  caso: "caso",
26
30
  politicas: "politicas",
@@ -29,6 +33,7 @@ var DATA_KEYS = {
29
33
  var ACTION_KEYS = {
30
34
  aprobar: "aprobar",
31
35
  rechazar: "rechazar",
36
+ marcarCargado: "marcar-cargado",
32
37
  cambiarPolitica: "cambiar-politica",
33
38
  abrirCaso: "abrir-caso"
34
39
  };
@@ -37,7 +42,7 @@ var manifest = {
37
42
  apiVersion: 1,
38
43
  version: PLUGIN_VERSION,
39
44
  displayName: "Autopilot Care",
40
- description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / corte) y tablero del director.",
45
+ description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, tableros de gesti\xF3n publicados por agentes y panel del director.",
41
46
  author: "Alephoo",
42
47
  categories: ["automation", "ui"],
43
48
  capabilities: [
@@ -87,7 +92,7 @@ var manifest = {
87
92
  {
88
93
  name: TOOL_NAMES.abrirCaso,
89
94
  displayName: "Abrir caso",
90
- description: "Abre un caso nuevo en un workflow, en su estado inicial. `referencia` identifica el objeto real (convenio, cuenta, profesional) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.",
95
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
91
96
  parametersSchema: {
92
97
  type: "object",
93
98
  properties: {
@@ -95,7 +100,8 @@ var manifest = {
95
100
  referencia: { type: "string" },
96
101
  titulo: { type: "string" },
97
102
  datos: { type: "object" },
98
- idempotencyKey: { type: "string" }
103
+ idempotencyKey: { type: "string" },
104
+ issueId: { type: "string", description: "Tarea de Paperclip que origina el caso (opcional; UUID)." }
99
105
  },
100
106
  required: ["workflow", "titulo"]
101
107
  }
@@ -103,7 +109,7 @@ var manifest = {
103
109
  {
104
110
  name: TOOL_NAMES.transicionar,
105
111
  displayName: "Transicionar caso",
106
- description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar) no est\xE1n disponibles para agentes.",
112
+ description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo.",
107
113
  parametersSchema: {
108
114
  type: "object",
109
115
  properties: {
@@ -147,6 +153,31 @@ var manifest = {
147
153
  },
148
154
  required: ["indicador"]
149
155
  }
156
+ },
157
+ {
158
+ name: TOOL_NAMES.publicarTablero,
159
+ displayName: "Publicar tablero",
160
+ description: "Publica o actualiza un tablero de gesti\xF3n para la direcci\xF3n del hospital, armado sobre datos reales de Alephoo (turnos, facturaci\xF3n, internaci\xF3n, producci\xF3n). `clave` identifica el tablero de forma estable (min\xFAsculas y guiones; volver a publicar con la misma clave lo actualiza en el lugar). `widgets` es la lista de piezas que se muestran, en orden: {tipo:'indicador', etiqueta, valor, unidad?, contexto?, tono?: neutro|ambar|senal|corte} \xB7 {tipo:'barras', titulo, unidad?, series:[{etiqueta, valor}]} \xB7 {tipo:'linea', titulo, unidad?, puntos:[{x, y}]} \xB7 {tipo:'tabla', titulo, columnas:[\u2026], filas:[[\u2026]]} \xB7 {tipo:'texto', titulo?, texto}. Cada widget admite `ancho` 1, 2 o 3 (columnas de 3). `fuentes` lista qu\xE9 se consult\xF3 (p. ej. 'Alephoo \xB7 api-consultas \xB7 turnos 01/09\u201330/09'). Si el pedido vino de una tarea, pasar `issueId`.",
161
+ parametersSchema: {
162
+ type: "object",
163
+ properties: {
164
+ clave: { type: "string" },
165
+ titulo: { type: "string" },
166
+ descripcion: { type: "string" },
167
+ pedido: { type: "string", description: "Qu\xE9 pidi\xF3 la direcci\xF3n, en sus palabras." },
168
+ periodo: { type: "string", description: "Per\xEDodo que cubren los datos, p. ej. 'septiembre 2026'." },
169
+ fuentes: { type: "array", items: { type: "string" } },
170
+ widgets: { type: "array", items: { type: "object" } },
171
+ issueId: { type: "string", description: "Tarea de Paperclip que origin\xF3 el tablero (opcional; UUID)." }
172
+ },
173
+ required: ["clave", "titulo", "widgets"]
174
+ }
175
+ },
176
+ {
177
+ name: TOOL_NAMES.listarTableros,
178
+ displayName: "Listar tableros",
179
+ description: "Lista los tableros publicados para esta instituci\xF3n (clave, t\xEDtulo, per\xEDodo, fuentes, cu\xE1ndo se actualiz\xF3 y cu\xE1ntos widgets tiene). Usar antes de publicar para reutilizar la clave de un tablero existente en vez de crear uno nuevo. Solo lectura.",
180
+ parametersSchema: { type: "object", properties: {} }
150
181
  }
151
182
  ],
152
183
  apiRoutes: [
@@ -190,6 +221,38 @@ var manifest = {
190
221
  capability: "api.routes.register",
191
222
  companyResolution: { from: "body", key: "companyId" }
192
223
  },
224
+ {
225
+ routeKey: "marcar-cargado",
226
+ method: "POST",
227
+ path: "/casos/:casoId/cargado",
228
+ auth: "board",
229
+ capability: "api.routes.register",
230
+ companyResolution: { from: "body", key: "companyId" }
231
+ },
232
+ {
233
+ routeKey: "version",
234
+ method: "GET",
235
+ path: "/version",
236
+ auth: "board",
237
+ capability: "api.routes.register",
238
+ companyResolution: { from: "query", key: "companyId" }
239
+ },
240
+ {
241
+ routeKey: "serie",
242
+ method: "GET",
243
+ path: "/serie",
244
+ auth: "board",
245
+ capability: "api.routes.register",
246
+ companyResolution: { from: "query", key: "companyId" }
247
+ },
248
+ {
249
+ routeKey: "historial-politicas",
250
+ method: "GET",
251
+ path: "/politicas/historial",
252
+ auth: "board",
253
+ capability: "api.routes.register",
254
+ companyResolution: { from: "query", key: "companyId" }
255
+ },
193
256
  {
194
257
  routeKey: "politicas",
195
258
  method: "GET",
@@ -205,6 +268,22 @@ var manifest = {
205
268
  auth: "board",
206
269
  capability: "api.routes.register",
207
270
  companyResolution: { from: "body", key: "companyId" }
271
+ },
272
+ {
273
+ routeKey: "tableros",
274
+ method: "GET",
275
+ path: "/tableros",
276
+ auth: "board",
277
+ capability: "api.routes.register",
278
+ companyResolution: { from: "query", key: "companyId" }
279
+ },
280
+ {
281
+ routeKey: "tablero-publicado",
282
+ method: "GET",
283
+ path: "/tableros/:clave",
284
+ auth: "board",
285
+ capability: "api.routes.register",
286
+ companyResolution: { from: "query", key: "companyId" }
208
287
  }
209
288
  ],
210
289
  ui: {
@@ -233,7 +312,8 @@ var MODOS = [
233
312
  { valor: "corte", etiqueta: "Corte", ayuda: "Los agentes no pueden abrir ni mover casos." },
234
313
  { valor: "observa", etiqueta: "Observa", ayuda: "Los agentes leen, registran y verifican; no proponen." },
235
314
  { valor: "propone", etiqueta: "Propone", ayuda: "Los agentes proponen; un humano aprueba y aplica." },
236
- { valor: "ejecuta", etiqueta: "Ejecuta", ayuda: "Los agentes aplican lo aprobado en el sistema del hospital." }
315
+ { valor: "ejecuta", etiqueta: "Ejecuta", ayuda: "Los agentes aplican lo aprobado en el sistema del hospital." },
316
+ { valor: "autonomo", etiqueta: "Aut\xF3nomo", ayuda: "Aprobaci\xF3n autom\xE1tica salvo excepciones (variaci\xF3n alta, sin valor actual, reintento, baja de valor)." }
237
317
  ];
238
318
  var fuente = 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
239
319
  var estilos = {
@@ -271,6 +351,8 @@ function colorModo(modo) {
271
351
  return "#2f6fd6";
272
352
  case "ejecuta":
273
353
  return "#1e8e3e";
354
+ case "autonomo":
355
+ return "#0b6b52";
274
356
  }
275
357
  }
276
358
  function ChipModo({ modo }) {