siesa-agents 2.1.96 → 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 +
@@ -324,8 +329,49 @@ the screen's archetype, is the screen `❌ BLOCKED: <screen> — no mockup and n
324
329
  memory precedent`. Steps 2–6 then run identically, with the synthesized plan
325
330
  standing in for the mockup.
326
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
+
327
341
  ### Step 2 — Build the homologation map
328
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
+
329
375
  Inventory every widget the mockup draws — buttons, checkboxes, data grids,
330
376
  tabs, badges, dropdown menus, inputs, labels with descriptions, pagination,
331
377
  dividers, avatars — and map **each one** to its kit realization before touching
@@ -403,6 +449,24 @@ With the map in hand, audit the **current** screen and write down:
403
449
  - **Stays identical** — every field name, validation, hook call, query,
404
450
  mutation, handler, prop and type; every aria-label and accessible behavior.
405
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
+
406
470
  Two asymmetries, both flagged, never silently resolved:
407
471
 
408
472
  - A mockup element with **no counterpart in the current screen** (an extra
@@ -462,6 +526,24 @@ The hard-won mechanics, worth understanding rather than copying:
462
526
  and declares no fields. If that file ever needs a validation or an API call,
463
527
  the change stopped being layout — back to Step 3.
464
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
+
465
547
  Whichever kind: keep field `name`s/`accessorKey`s, react-hook-form
466
548
  registrations and resolvers, zod schemas, TanStack Query/Router bindings,
467
549
  `useEffect` dependencies, event handlers, i18n keys and TypeScript types
@@ -644,6 +726,10 @@ do with a blocked screen.
644
726
  - Weaken what a test verifies. Updating a structural assertion whose markup you
645
727
  replaced is legitimate (and reported); loosening a behavioral assertion to
646
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
647
733
  - Start a run without an explicit user-declared target (a module/feature name,
648
734
  or an explicit full-scope instruction) — inferring what to refactor is
649
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.96",
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": {