paperclip-plugin-autopilot-ops 0.1.42 → 0.1.44

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/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.42";
3
+ var PLUGIN_VERSION = "0.1.44";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
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.42";
11
+ var PLUGIN_VERSION = "0.1.44";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
package/dist/worker.js CHANGED
@@ -39932,7 +39932,7 @@ function startWorkerRpcHost(options) {
39932
39932
 
39933
39933
  // src/manifest.ts
39934
39934
  var PLUGIN_ID = "alephoo.autopilot-ops";
39935
- var PLUGIN_VERSION = "0.1.42";
39935
+ var PLUGIN_VERSION = "0.1.44";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -46994,6 +46994,19 @@ function controlarTabla(ref, columnas, filas, problemas) {
46994
46994
  }
46995
46995
  }
46996
46996
  }
46997
+ function jergaEn(texto10) {
46998
+ const m = /\b[A-Z]{2,5}-\d+\b|\b[a-z]+_[a-z0-9_]+\b|\bv\d+\.\d+(\.\d+)?\b|\b[Ii][Dd] \d+\b/.exec(texto10) ?? /\bAlephoo\b|\bcapa sem[aá]ntica\b|\brecetas? sem[aá]nticas?\b|\bborrad[oa]s? l[oó]gicamente\b|\bSELECT\b/i.exec(texto10);
46999
+ return m ? m[0] : null;
47000
+ }
47001
+ var MAX_TEXTOS = 1;
47002
+ var MAX_LARGO_LECTURA = 900;
47003
+ var MAX_LARGO_PERIODO = 60;
47004
+ var MAX_LARGO_DESCRIPCION = 160;
47005
+ var MAX_LARGO_CONTEXTO = 120;
47006
+ function marcaDelSistemaEn(texto10) {
47007
+ const m = /\bAlephoo\b|\b[Ii][Dd] \d+\b/.exec(texto10);
47008
+ return m ? m[0] : null;
47009
+ }
46997
47010
  var MAX_BARRAS = 12;
46998
47011
  function validarWidgets(entrada) {
46999
47012
  const problemas = [];
@@ -47019,7 +47032,7 @@ function validarWidgets(entrada) {
47019
47032
  const unidad = texto9(o.unidad, 16, `${ref}.unidad`, problemas);
47020
47033
  if (unidad === "%" && !ES_VARIACION.test(etiqueta)) controlarPorcentaje(valor, `${ref}.valor`, problemas);
47021
47034
  const { calculo, origen } = leerCalculo(o.calculo, ref, problemas);
47022
- salida.push({ tipo, etiqueta, valor, unidad, contexto: texto9(o.contexto, 160, `${ref}.contexto`, problemas), tono, ancho: a, ...calculo ? { calculo } : {}, origen });
47035
+ salida.push({ tipo, etiqueta, valor, unidad, contexto: texto9(o.contexto, MAX_LARGO_CONTEXTO, `${ref}.contexto`, problemas), tono, ancho: a, ...calculo ? { calculo } : {}, origen });
47023
47036
  break;
47024
47037
  }
47025
47038
  case "barras": {
@@ -47077,9 +47090,37 @@ function validarWidgets(entrada) {
47077
47090
  }
47078
47091
  }
47079
47092
  });
47093
+ for (const [k, w] of salida.entries()) {
47094
+ const textos2 = [w.tipo === "texto" ? w.texto : null, w.tipo === "texto" ? w.titulo : null, "titulo" in w ? w.titulo : null, w.tipo === "indicador" ? w.contexto : null, w.tipo === "indicador" ? w.etiqueta : null].filter((x) => typeof x === "string");
47095
+ for (const x of textos2) {
47096
+ const jerga = jergaEn(x);
47097
+ if (jerga) problemas.push(`widgets[${k}]: \xAB${jerga}\xBB es un t\xE9rmino interno; la direcci\xF3n no lo entiende (us\xE1 \xABel HIS\xBB y nombres de negocio; el detalle t\xE9cnico va en fuentes o en el comentario de la tarea)`);
47098
+ }
47099
+ }
47100
+ const vistos = /* @__PURE__ */ new Map();
47101
+ for (const [k, w] of salida.entries()) {
47102
+ if (w.tipo !== "indicador" || w.valor === "" || w.valor === 0) continue;
47103
+ const llave = `${w.valor}|${w.unidad ?? ""}`;
47104
+ if (vistos.has(llave)) problemas.push(`widgets[${k}]: repite el n\xFAmero de widgets[${vistos.get(llave)}] (${w.valor}${w.unidad ? ` ${w.unidad}` : ""}): dej\xE1 uno solo y llev\xE1 el otro dato al contexto`);
47105
+ else vistos.set(llave, k);
47106
+ }
47107
+ for (const [k, w] of salida.entries()) {
47108
+ const titulo = "titulo" in w ? w.titulo : void 0;
47109
+ if (titulo && /\$\s?\d|\d{1,3}(\.\d{3})+/.test(titulo)) problemas.push(`widgets[${k}]: el t\xEDtulo lleva una cifra (\xAB${titulo}\xBB): el t\xEDtulo dice qu\xE9 muestra; la cifra va en un indicador`);
47110
+ }
47111
+ for (const [k, w] of salida.entries()) {
47112
+ if (w.tipo === "indicador" && (w.tono === "ambar" || w.tono === "corte") && !w.contexto) problemas.push(`widgets[${k}]: un n\xFAmero en ${w.tono === "corte" ? "rojo" : "\xE1mbar"} lleva en \xABcontexto\xBB por qu\xE9 pide atenci\xF3n (una l\xEDnea)`);
47113
+ }
47114
+ for (const [k, w] of salida.entries()) {
47115
+ const nombres = w.tipo === "barras" ? w.series.map((x) => x.etiqueta) : w.tipo === "tabla" ? w.filas.flatMap((f) => f.filter((c) => typeof c === "string")) : [];
47116
+ const marca = nombres.map(marcaDelSistemaEn).find(Boolean);
47117
+ if (marca) problemas.push(`widgets[${k}]: \xAB${marca}\xBB no es un dato de la instituci\xF3n (un usuario o la marca del sistema): sac\xE1 esa fila o agrupala en \xABSin asignar\xBB`);
47118
+ }
47119
+ const textos = salida.filter((w) => w.tipo === "texto");
47120
+ if (textos.length > MAX_TEXTOS) problemas.push(`un solo widget de texto (\xABLectura\xBB): lo que cambi\xF3 va en una frase al final de ella, el resto en el comentario de la tarea`);
47121
+ for (const t6 of textos) if (t6.texto.length > MAX_LARGO_LECTURA) problemas.push(`la Lectura tiene ${t6.texto.length} caracteres: hasta ${MAX_LARGO_LECTURA} (2 o 3 p\xE1rrafos breves; el primero, qu\xE9 conviene hacer)`);
47080
47122
  const tonos = (t6) => salida.filter((w) => w.tipo === "indicador" && w.tono === t6).length;
47081
- if (tonos("ambar") > 1) problemas.push("como m\xE1ximo un indicador en \xE1mbar por tablero: el que pide una acci\xF3n de la direcci\xF3n (los dem\xE1s, neutro)");
47082
- if (tonos("corte") > 1) problemas.push("como m\xE1ximo un indicador en rojo (corte) por tablero: solo lo urgente");
47123
+ if (tonos("ambar") + tonos("corte") > 1) problemas.push("como m\xE1ximo un indicador en \xE1mbar o rojo por tablero: el que pide una acci\xF3n de la direcci\xF3n (rojo solo si es urgente); los dem\xE1s, neutro");
47083
47124
  if (problemas.length) throw new OpsError("tablero_invalido", `el tablero no se puede publicar: ${problemas.slice(0, 12).join("; ")}${problemas.length > 12 ? ` (y ${problemas.length - 12} m\xE1s)` : ""}`, { problemas });
47084
47125
  return salida;
47085
47126
  }
@@ -47120,6 +47161,16 @@ async function publicarTablero(ctx, input2) {
47120
47161
  if (!CLAVE_RE2.test(clave)) throw new OpsError("clave_invalida", "clave debe ser un identificador estable en min\xFAsculas (letras, n\xFAmeros y guiones, 2 a 61 caracteres), p. ej. turnos-ausentismo");
47121
47162
  const titulo = typeof input2.titulo === "string" ? input2.titulo.trim().slice(0, 140) : "";
47122
47163
  if (!titulo) throw new OpsError("titulo_requerido", "titulo es obligatorio");
47164
+ for (const [campo, v] of [["titulo", titulo], ["descripcion", input2.descripcion], ["periodo", input2.periodo]]) {
47165
+ const jerga = typeof v === "string" ? jergaEn(v) : null;
47166
+ if (jerga) throw new OpsError("tablero_invalido", `${campo}: \xAB${jerga}\xBB es un t\xE9rmino interno; la direcci\xF3n no lo entiende (us\xE1 \xABel HIS\xBB y nombres de negocio)`);
47167
+ }
47168
+ if (typeof input2.descripcion === "string" && input2.descripcion.trim().length > MAX_LARGO_DESCRIPCION) {
47169
+ throw new OpsError("tablero_invalido", `descripcion: hasta ${MAX_LARGO_DESCRIPCION} caracteres (qu\xE9 muestra el tablero, en una o dos frases); el m\xE9todo va en fuentes o en el comentario de la tarea`);
47170
+ }
47171
+ if (typeof input2.periodo === "string" && input2.periodo.trim().length > MAX_LARGO_PERIODO) {
47172
+ throw new OpsError("tablero_invalido", `periodo: hasta ${MAX_LARGO_PERIODO} caracteres (p. ej. \xABoctubre 2025 a septiembre 2026\xBB); las aclaraciones van en la descripci\xF3n`);
47173
+ }
47123
47174
  const widgets = validarWidgets(input2.widgets);
47124
47175
  const fuentes = arr(input2.fuentes).filter((f) => typeof f === "string" && f.trim()).map((f) => String(f).trim().slice(0, 120)).slice(0, 12);
47125
47176
  const limpio = (v, max) => typeof v === "string" && v.trim() ? v.trim().slice(0, max) : null;
@@ -47193,7 +47244,12 @@ async function descartarRetiroTablero(ctx, input2) {
47193
47244
  }
47194
47245
  async function listarPublicaciones(ctx, companyId) {
47195
47246
  const rows = await ctx.db.query(`SELECT clave, version, issue_id, publicado_at FROM ${t5(ctx, "tablero_publicacion")} WHERE company_id = $1 ORDER BY publicado_at DESC LIMIT 500`, [companyId]);
47196
- return rows.map((r) => ({ clave: String(r.clave), version: Number(r.version), issueId: r.issue_id ?? null, en: iso4(r.publicado_at) }));
47247
+ const lista3 = rows.map((r) => ({ clave: String(r.clave), version: Number(r.version), issueId: r.issue_id ?? null, en: iso4(r.publicado_at) }));
47248
+ const tableros = await ctx.db.query(`SELECT clave, versiones, issue_id, updated_at FROM ${t5(ctx, "tablero")} WHERE company_id = $1 AND issue_id IS NOT NULL`, [companyId]);
47249
+ for (const tb of tableros) {
47250
+ if (!lista3.some((x) => x.issueId === tb.issue_id)) lista3.push({ clave: String(tb.clave), version: Number(tb.versiones ?? 1), issueId: String(tb.issue_id), en: iso4(tb.updated_at) });
47251
+ }
47252
+ return lista3;
47197
47253
  }
47198
47254
 
47199
47255
  // src/worker.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "type": "module",
5
5
  "description": "Autopilot Care · operación autónoma gobernada para instituciones de salud: workflows determinísticos, validaciones, registro de negocio, políticas (observa/propone/ejecuta/corte) y tablero del director, como plugin de Paperclip.",
6
6
  "files": [