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: (
|
|
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: (
|
|
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: (
|
|
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>`
|
|
64
|
-
to promote it into the kit.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|