siesa-agents 2.1.95 → 2.1.97

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/bin/install.js CHANGED
@@ -412,6 +412,40 @@ class SiesaBmadInstaller {
412
412
  return modifiedFiles;
413
413
  }
414
414
 
415
+ // Returns true if `relativePath` (relative to source root) is inside a
416
+ // `skills/` directory AND the skill name does NOT start with 'sa-'.
417
+ // The package only ships siesa-agents skills (sa-*); if a non-sa-* entry
418
+ // ever appears in the tarball it would shadow the engineer's own skill with
419
+ // the same name. This guard prevents that, and makes the intent explicit.
420
+ isForeignSkillPath(relativePath) {
421
+ const parts = relativePath.replace(/\\/g, '/').split('/');
422
+ const skillsIdx = parts.indexOf('skills');
423
+ if (skillsIdx >= 0 && parts.length > skillsIdx + 1) {
424
+ const skillName = parts[skillsIdx + 1];
425
+ return Boolean(skillName) && !skillName.startsWith('sa-');
426
+ }
427
+ return false;
428
+ }
429
+
430
+ // Single filter factory used in every fs.copy call.
431
+ // Rules (in order):
432
+ // 1. Never overwrite user-owned ignored files when they already exist.
433
+ // 2. Never copy non-sa-* skill directories from the source package —
434
+ // the engineer's custom skills must survive every re-install/update.
435
+ makeCopyFilter(sourcePath, targetPath) {
436
+ return (src) => {
437
+ const relativePath = path.relative(sourcePath, src);
438
+ if (this.ignoredFiles.includes(relativePath)) {
439
+ const targetFile = path.join(targetPath, relativePath);
440
+ return !fs.existsSync(targetFile);
441
+ }
442
+ if (this.isForeignSkillPath(relativePath)) {
443
+ return false;
444
+ }
445
+ return true;
446
+ };
447
+ }
448
+
415
449
  async getAllFiles(dir) {
416
450
  const files = [];
417
451
  const stat = await fs.stat(dir);
@@ -581,15 +615,7 @@ class SiesaBmadInstaller {
581
615
  await fs.copy(sourcePath, targetPath, {
582
616
  overwrite: true,
583
617
  recursive: true,
584
- filter: (src) => {
585
- const relativePath = path.relative(sourcePath, src);
586
- // No sobrescribir archivos ignorados si ya existen
587
- if (this.ignoredFiles.includes(relativePath)) {
588
- const targetFile = path.join(targetPath, relativePath);
589
- return !fs.existsSync(targetFile);
590
- }
591
- return true;
592
- }
618
+ filter: this.makeCopyFilter(sourcePath, targetPath)
593
619
  });
594
620
  }
595
621
 
@@ -670,15 +696,7 @@ class SiesaBmadInstaller {
670
696
  await fs.copy(sourcePath, targetPath, {
671
697
  overwrite: true,
672
698
  recursive: true,
673
- filter: (src) => {
674
- const relativePath = path.relative(sourcePath, src);
675
- // No sobrescribir archivos ignorados si ya existen
676
- if (this.ignoredFiles.includes(relativePath)) {
677
- const targetFile = path.join(targetPath, relativePath);
678
- return !fs.existsSync(targetFile);
679
- }
680
- return true;
681
- }
699
+ filter: this.makeCopyFilter(sourcePath, targetPath)
682
700
  });
683
701
  } else {
684
702
  console.warn(`⚠️ Carpeta ${mapping.source} no encontrada en el paquete`);
@@ -787,15 +805,7 @@ class SiesaBmadInstaller {
787
805
  await fs.copy(sourcePath, stagingPath, {
788
806
  overwrite: true,
789
807
  recursive: true,
790
- filter: (src) => {
791
- const relativePath = path.relative(sourcePath, src);
792
- // No sobrescribir archivos ignorados si ya existen en el target real.
793
- if (this.ignoredFiles.includes(relativePath)) {
794
- const realTargetFile = path.join(targetPath, relativePath);
795
- return !fs.existsSync(realTargetFile);
796
- }
797
- return true;
798
- }
808
+ filter: this.makeCopyFilter(sourcePath, targetPath)
799
809
  });
800
810
  }
801
811
  // Ocultar el staging mientras existe (cosmético, solo Windows).
@@ -58,13 +58,18 @@ nothing or to several candidates is asked about, never guessed.
58
58
  Key definitions you take from the UX spec instead of inferring:
59
59
 
60
60
  - **§2.1 Component Selection Priority** (mandatory order): 1) a siesa-ui-kit
61
- molecule, 2) a **composition** of kit molecules, 3) **shadcn as the
61
+ molecule, 2) a **composition** of kit molecules, 3) **shadcn or Radix as the
62
62
  fallback** when neither expresses the widget — used directly, flagged in the
63
- report (`⚠️ shadcn fallback: <widget>`) so the team can later decide whether
64
- to promote it into the kit. Hand-rolled HTML widgets are never an option at
65
- any step. A shadcn component obeys the same `rules/` as everything else:
66
- design-system token classes, rem, no inline styles — restyled to the design
67
- system, never left on shadcn defaults.
63
+ report (`⚠️ shadcn fallback: <widget>` / `⚠️ radix fallback: <widget>`) so
64
+ the team can later decide whether to promote it into the kit. Prefer shadcn
65
+ when it covers the widget; reach for Radix primitives
66
+ (`@radix-ui/react-dialog`, `Popover`, `Collapsible`, etc.) when the
67
+ interaction pattern (slide-in panels, floating overlays, controlled
68
+ disclosure) needs headless primitives that shadcn doesn't expose cleanly.
69
+ Hand-rolled HTML widgets are never an option at any step. shadcn and Radix
70
+ components obey the same `rules/` as everything else: design-system token
71
+ classes, rem, no inline styles — restyled to the design system, never left
72
+ on defaults.
68
73
  - **§1 Design System Foundation**: brand palette (primary `#0e79fd`), semantic
69
74
  colors, surfaces; neutrals are `slate.*`, never the secondary brand scale.
70
75
  - **§4.3 Page Structure**: the standard page scaffold (header with title +
@@ -146,6 +151,53 @@ review:
146
151
  Tailwind token class), px → rem (1rem = 16px, `44px → 2.75rem`), inline
147
152
  styles → Tailwind classes.
148
153
 
154
+ ## Pre-gate: directory validation and design memory
155
+
156
+ Before asking for a target, the skill validates the two key directories and
157
+ offers to refresh the design memory.
158
+
159
+ **1. Validate `_bmad-output/design-artifacts/html-and-design`**
160
+
161
+ - **Does not exist** → create it, then tell the user:
162
+
163
+ > `📁 Directorio creado: _bmad-output/design-artifacts/html-and-design`
164
+ > `Por favor pega en ese directorio las plantillas HTML antes de continuar.`
165
+
166
+ Stop here. The directory is the input for memory generation; proceeding
167
+ without templates would produce an empty memory.
168
+
169
+ - **Exists** → continue.
170
+
171
+ **2. Validate `_bmad-output/design-artifacts/design-memory`**
172
+
173
+ - **Does not exist** → create it empty and continue (no user action needed).
174
+ - **Exists** → continue.
175
+
176
+ **3. Authorization for memory generation**
177
+
178
+ Use `AskUserQuestion` with the following exact text:
179
+
180
+ > *"Procederé a inspeccionar las plantillas para generar/actualizar las memorias
181
+ > de diseño, ¿Autorizas esta acción? Esto podría tardar unos minutos."*
182
+
183
+ Options: **Aceptar** / **Cancelar**.
184
+
185
+ - **Aceptar** → run the full sync algorithm from `references/design-memory.md`
186
+ ("Sync algorithm"): hash every `.html` in `html-and-design`, compare against
187
+ `design-memory/manifest.yaml`, build or update only what changed. Report one
188
+ line: `🧠 Memory: current (N sources)` or
189
+ `🧠 Memory: rebuilt/updated (+A new, B changed, C removed)`.
190
+ - **Cancelar** → explain to the user why this step matters, then stop:
191
+
192
+ > Las memorias de diseño son el insumo que permite homologar pantallas sin
193
+ > un mockup directo y mantener los patrones de diseño sincronizados con las
194
+ > plantillas más recientes. Omitir esta actualización puede causar que el
195
+ > refactor use patrones desactualizados o incompletos. Por este motivo, la
196
+ > skill no puede continuar sin ejecutar o tener memorias válidas.
197
+ > `❌ DETENIDO: generación de memorias cancelada por el usuario.`
198
+
199
+ After this step, proceed to the Gate.
200
+
149
201
  ## Gate: explicit target, before anything else
150
202
 
151
203
  The run starts blind and stays blind until the user names the target. The
@@ -212,13 +264,9 @@ processed "while we're at it".
212
264
  styles, px/hex from specs are converted on entry, never copied). New rule
213
265
  files dropped there later bind exactly the same way, without editing this
214
266
  skill.
215
- 0b. **Sync the design memory** (`references/design-memory.md`, "Sync
216
- algorithm"): hash every `.html` in the mockup dir and compare against
217
- `design-memory/manifest.yaml`. No manifest full build of the memory
218
- files; new/changed/removed sources → incremental update / flag; all hashes
219
- match → skip. Report one line: `🧠 Memory: current (N sources)` or
220
- `🧠 Memory: rebuilt/updated (+A new, B changed, C removed)`. If the user
221
- provided a custom memory path, use it and record it in the manifest.
267
+ 0b. **Design memory** — already synced in the pre-gate step; skip. If the
268
+ user provided a custom memory path via argument, record it in
269
+ `manifest.yaml` now so the next run picks it up.
222
270
  1. List the queue: every `.html` in the resolved mockup dir, sorted by name —
223
271
  that is the FIFO processing order — then **filter it to the target declared
224
272
  at the gate**: only mockups matching the named module/feature stay in the
@@ -281,8 +329,49 @@ the screen's archetype, is the screen `❌ BLOCKED: <screen> — no mockup and n
281
329
  memory precedent`. Steps 2–6 then run identically, with the synthesized plan
282
330
  standing in for the mockup.
283
331
 
332
+ **If the target screen already uses siesa-ui-kit components** (e.g. it is
333
+ built on `MasterCrud`, `Table`, or any other kit molecule), this is **not a
334
+ skip condition**. The refactor goal is the *distribution* — how widgets are
335
+ arranged, grouped, and presented — not the widget vocabulary. If the
336
+ distribution in the mockup or the user's instruction differs from the current
337
+ screen, proceed with the full refactor using kit compositions (more complex
338
+ compositions are acceptable and expected). Only when no kit composition covers
339
+ a widget should shadcn or Radix be considered.
340
+
284
341
  ### Step 2 — Build the homologation map
285
342
 
343
+ #### Interaction audit (before the widget inventory)
344
+
345
+ For every interactive element in the mockup (buttons, toggles, switches,
346
+ disclosure triggers, tab groups), read the associated JS/event logic in the
347
+ source HTML and document the full contract:
348
+
349
+ | Trigger | Event | Effect | Position / layout |
350
+ |---------|-------|--------|-------------------|
351
+ | Filter button | click | opens filter panel | slide-in from right (Sheet / Drawer) |
352
+ | Toggle switch | change | reveals option group | appears to the right of the switch |
353
+ | … | … | … | … |
354
+
355
+ This table is **mandatory input for the homologation map**. A widget whose
356
+ interaction contract is not documented here cannot be mapped correctly — the
357
+ model will default to stacking everything vertically, which is the failure
358
+ mode. Map each effect to its kit realization:
359
+
360
+ - A **slide-in panel** (sidebar, drawer) → `Sheet` (shadcn) or
361
+ `@radix-ui/react-dialog` in sheet mode, never a `div` below the trigger.
362
+ - A **floating overlay / popover** → `Popover` (shadcn or Radix).
363
+ - A **conditionally revealed section beside the trigger** → `Collapsible`
364
+ (`@radix-ui/react-collapsible`) with `flex-row` layout so the revealed
365
+ content appears to the right, not below.
366
+ - A **tab-like switch that swaps content areas** → `Tabs` (kit) with the
367
+ content panel beside or below as the mockup dictates.
368
+
369
+ If the source HTML has no JS for a trigger (static mockup), infer the pattern
370
+ from the visual layout annotation (labels like "→ panel", arrows, overlapping
371
+ layers) and record it as `inferred`. An `inferred` entry still produces a
372
+ mapping; it is flagged `⚠️ inferred behavior` in the screen report so a
373
+ reviewer can confirm before shipping.
374
+
286
375
  Inventory every widget the mockup draws — buttons, checkboxes, data grids,
287
376
  tabs, badges, dropdown menus, inputs, labels with descriptions, pagination,
288
377
  dividers, avatars — and map **each one** to its kit realization before touching
@@ -360,6 +449,24 @@ With the map in hand, audit the **current** screen and write down:
360
449
  - **Stays identical** — every field name, validation, hook call, query,
361
450
  mutation, handler, prop and type; every aria-label and accessible behavior.
362
451
 
452
+ **Filter continuity check (MasterCrud targets only):** If the current screen
453
+ is built on `MasterCrud`, inventory its active filter logic before doing
454
+ anything else:
455
+
456
+ ```bash
457
+ grep -rn "useFilter\|filterParams\|queryKey\|searchParams\|filterState\|onFilter" \
458
+ apps/Frontend/src/modules/<module-slug>/presentation/
459
+ ```
460
+
461
+ Record every hook, param key, and callback that drives filtering. If the
462
+ mockup or the user's instruction calls for a composition that does **not** use
463
+ `MasterCrud`, these filter hooks are now orphaned — their UI trigger will
464
+ disappear. Document them in the gap analysis as **"filter bindings requiring
465
+ rewire"** (not as warnings to ignore) and carry them into Step 4 as a required
466
+ output: the new composition must expose a UI element (filter button, search
467
+ input, panel) wired to the same hook calls. No filter that worked before the
468
+ refactor may be left unreachable after it.
469
+
363
470
  Two asymmetries, both flagged, never silently resolved:
364
471
 
365
472
  - A mockup element with **no counterpart in the current screen** (an extra
@@ -419,6 +526,24 @@ The hard-won mechanics, worth understanding rather than copying:
419
526
  and declares no fields. If that file ever needs a validation or an API call,
420
527
  the change stopped being layout — back to Step 3.
421
528
 
529
+ **Filter rewiring (when leaving MasterCrud):** If Step 3 identified orphaned
530
+ filter bindings, the new composition must reconnect them. This is strictly
531
+ presentation-layer work — the hooks already know how to filter; they only
532
+ need a new UI trigger:
533
+
534
+ - A filter button → opens a `Sheet` (shadcn) or `Collapsible` panel; its
535
+ `onApply` / `onChange` calls the same hook callback that `MasterCrud`'s
536
+ built-in filter used.
537
+ - A search input → bound to the same `filterParams` key, same debounce if
538
+ it existed.
539
+ - Advanced vs. basic filter sections → same state split, new visual grouping
540
+ inside the panel.
541
+
542
+ Wire each binding explicitly. Close this sub-step with a checklist: one line
543
+ per orphaned filter binding, marked `✅ rewired` or `❌ no UI trigger found`.
544
+ A binding left `❌` blocks the screen (`❌ BLOCKED: <screen> — filter
545
+ binding <name> has no UI trigger in new composition`).
546
+
422
547
  Whichever kind: keep field `name`s/`accessorKey`s, react-hook-form
423
548
  registrations and resolvers, zod schemas, TanStack Query/Router bindings,
424
549
  `useEffect` dependencies, event handlers, i18n keys and TypeScript types
@@ -601,6 +726,10 @@ do with a blocked screen.
601
726
  - Weaken what a test verifies. Updating a structural assertion whose markup you
602
727
  replaced is legitimate (and reported); loosening a behavioral assertion to
603
728
  get green is not
729
+ - Touch a view (create, edit, detail, list) for which the user provided **no
730
+ reference mockup or explicit instruction** — if only the list view was
731
+ referenced, the create/edit views are out of scope even if they share the
732
+ same module; scope is per-view, not per-module
604
733
  - Start a run without an explicit user-declared target (a module/feature name,
605
734
  or an explicit full-scope instruction) — inferring what to refactor is
606
735
  forbidden; process anything the declared scope doesn't cover
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siesa-agents",
3
- "version": "2.1.95",
3
+ "version": "2.1.97",
4
4
  "description": "Paquete para instalar y configurar agentes SIESA en tu proyecto",
5
5
  "main": "index.js",
6
6
  "bin": {