siesa-agents 2.1.90 → 2.1.92
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/bmad/_config/bmad-help.csv +45 -0
- package/bmad/_config/files-manifest.csv +272 -0
- package/bmad/_config/manifest.yaml +23 -0
- package/bmad/_config/skill-manifest.csv +43 -0
- package/bmad/bmm/module-help.csv +33 -0
- package/bmad/config.toml +69 -0
- package/bmad/config.user.toml +17 -0
- package/bmad/core/config.yaml +9 -0
- package/bmad/core/module-help.csv +13 -0
- package/bmad/custom/config.toml +7 -0
- package/bmad/scripts/resolve_config.py +176 -0
- package/bmad/scripts/resolve_customization.py +230 -0
- package/claude/skills/sa-wds-visual-proposals/SKILL.md +6 -0
- package/package.json +1 -1
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/data/component-mapping.csv +47 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-01-init.md +148 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-01b-continue.md +79 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-02-bridge.md +114 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-02b-kit-warmup.md +96 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-03-scenarios.md +102 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-04-specs.md +97 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-05-prototype.md +102 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/steps/step-06-handoff.md +96 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/templates/product-brief-bridge.md +68 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/templates/proposal-index.md +46 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/templates/trigger-map-bridge.md +54 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/workflow.md +82 -0
- package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/workflow_ext.md +195 -0
- package/siesa-agents/scripts/phases/phase1.js +42 -4
- package/siesa-agents/scripts/phases/phase2.js +42 -4
- package/siesa-agents/scripts/phases/phase3.js +42 -4
- package/siesa-agents/wds/config.yaml +20 -0
- package/siesa-agents/wds/data/agent-contracts.md +72 -0
- package/siesa-agents/wds/data/agent-guides/freya/agentic-development.md +223 -0
- package/siesa-agents/wds/data/agent-guides/freya/content-creation.md +270 -0
- package/siesa-agents/wds/data/agent-guides/freya/design-system.md +333 -0
- package/siesa-agents/wds/data/agent-guides/freya/meta-content-guide.md +495 -0
- package/siesa-agents/wds/data/agent-guides/freya/specification-quality.md +262 -0
- package/siesa-agents/wds/data/agent-guides/freya/strategic-design.md +116 -0
- package/siesa-agents/wds/data/agent-guides/saga/content-structure-principles.md +190 -0
- package/siesa-agents/wds/data/agent-guides/saga/conversational-followups.md +372 -0
- package/siesa-agents/wds/data/agent-guides/saga/discovery-conversation.md +265 -0
- package/siesa-agents/wds/data/agent-guides/saga/dream-up-approach.md +1034 -0
- package/siesa-agents/wds/data/agent-guides/saga/inspiration-analysis.md +215 -0
- package/siesa-agents/wds/data/agent-guides/saga/resources/project-brief.template.md +187 -0
- package/siesa-agents/wds/data/agent-guides/saga/seo-strategy-guide.md +391 -0
- package/siesa-agents/wds/data/agent-guides/saga/strategic-documentation.md +454 -0
- package/siesa-agents/wds/data/agent-guides/saga/trigger-mapping.md +653 -0
- package/siesa-agents/wds/data/agent-guides/saga/working-with-existing-materials.md +172 -0
- package/siesa-agents/wds/data/design-system/component-boundaries.md +318 -0
- package/siesa-agents/wds/data/design-system/figma-component-structure.md +697 -0
- package/siesa-agents/wds/data/design-system/naming-conventions.md +200 -0
- package/siesa-agents/wds/data/design-system/state-management.md +93 -0
- package/siesa-agents/wds/data/design-system/token-architecture.md +474 -0
- package/siesa-agents/wds/data/design-system/validation-patterns.md +74 -0
- package/siesa-agents/wds/data/presentations/freya-how-i-help.md +63 -0
- package/siesa-agents/wds/data/presentations/freya-intro.md +269 -0
- package/siesa-agents/wds/data/presentations/freya-presentation.md +77 -0
- package/siesa-agents/wds/data/presentations/freya-workflows-guide.md +51 -0
- package/siesa-agents/wds/data/presentations/mimir-agents-overview.md +66 -0
- package/siesa-agents/wds/data/presentations/mimir-tone-setting.md +48 -0
- package/siesa-agents/wds/data/presentations/saga-how-i-help.md +62 -0
- package/siesa-agents/wds/data/presentations/saga-intro.md +285 -0
- package/siesa-agents/wds/data/presentations/saga-presentation.md +74 -0
- package/siesa-agents/wds/data/presentations/saga-workflows-guide.md +48 -0
- package/siesa-agents/wds/data/shared-activation.md +49 -0
- package/siesa-agents/wds/data/wds-glossary.md +98 -0
- package/siesa-agents/wds/module-help.csv +19 -0
- package/siesa-agents/wds/scripts/README.md +155 -0
- package/siesa-agents/wds/scripts/wds-add-object.js +207 -0
- package/siesa-agents/wds/scripts/wds-add-spacing.js +158 -0
- package/siesa-agents/wds/scripts/wds-init-page.js +234 -0
- package/siesa-agents/wds/scripts/wds-init-scenario.js +125 -0
- package/siesa-agents/wds/scripts/wds-nav.js +206 -0
- package/siesa-agents/wds/scripts/wds-validate.js +306 -0
- package/siesa-agents/wds/skills/freya.activation.md +204 -0
- package/siesa-agents/wds/skills/handoff.md +91 -0
- package/siesa-agents/wds/skills/saga.activation.md +169 -0
- package/siesa-agents/wds/skills/shared/git.md +55 -0
- package/siesa-agents/wds/skills/start.md +99 -0
- package/siesa-agents/wds/skills/wrap.md +198 -0
package/bmad/config.toml
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────
|
|
2
|
+
# Installer-managed. Regenerated on every install — treat as read-only.
|
|
3
|
+
#
|
|
4
|
+
# Direct edits to this file will be overwritten on the next install.
|
|
5
|
+
# To change an install answer durably, re-run the installer (your prior
|
|
6
|
+
# answers are remembered as defaults). To pin a value regardless of
|
|
7
|
+
# install answers, or to add custom agents / override descriptors, use:
|
|
8
|
+
# _bmad/custom/config.toml (team, committed)
|
|
9
|
+
# _bmad/custom/config.user.toml (personal, gitignored)
|
|
10
|
+
# Those files are never touched by the installer.
|
|
11
|
+
# ─────────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
[core]
|
|
14
|
+
document_output_language = "English"
|
|
15
|
+
output_folder = "{project-root}/_bmad-output"
|
|
16
|
+
|
|
17
|
+
[modules.bmm]
|
|
18
|
+
project_name = "Siesa-Agents"
|
|
19
|
+
planning_artifacts = "{project-root}/_bmad-output/planning-artifacts"
|
|
20
|
+
implementation_artifacts = "{project-root}/_bmad-output/implementation-artifacts"
|
|
21
|
+
project_knowledge = "{project-root}/docs"
|
|
22
|
+
|
|
23
|
+
[agents.bmad-agent-analyst]
|
|
24
|
+
module = "bmm"
|
|
25
|
+
team = "software-development"
|
|
26
|
+
name = "Mary"
|
|
27
|
+
title = "Business Analyst"
|
|
28
|
+
icon = "📊"
|
|
29
|
+
description = "Channels Porter's strategic rigor and Minto's Pyramid Principle, grounds every finding in verifiable evidence, represents every stakeholder voice. Speaks like a treasure hunter narrating the find: thrilled by every clue, precise once the pattern emerges."
|
|
30
|
+
|
|
31
|
+
[agents.bmad-agent-tech-writer]
|
|
32
|
+
module = "bmm"
|
|
33
|
+
team = "software-development"
|
|
34
|
+
name = "Paige"
|
|
35
|
+
title = "Technical Writer"
|
|
36
|
+
icon = "📚"
|
|
37
|
+
description = "Master of CommonMark, DITA, and OpenAPI; turns complex concepts into accessible structured docs, favors diagrams over walls of text, every word earning its place. Speaks like the patient teacher you wish you'd had, using analogies that make complex things feel simple."
|
|
38
|
+
|
|
39
|
+
[agents.bmad-agent-pm]
|
|
40
|
+
module = "bmm"
|
|
41
|
+
team = "software-development"
|
|
42
|
+
name = "John"
|
|
43
|
+
title = "Product Manager"
|
|
44
|
+
icon = "📋"
|
|
45
|
+
description = "Drives Jobs-to-be-Done over template filling, user value first, technical feasibility is a constraint not the driver. Speaks like a detective interrogating a cold case: short questions, sharper follow-ups, every 'why?' tightening the net."
|
|
46
|
+
|
|
47
|
+
[agents.bmad-agent-ux-designer]
|
|
48
|
+
module = "bmm"
|
|
49
|
+
team = "software-development"
|
|
50
|
+
name = "Sally"
|
|
51
|
+
title = "UX Designer"
|
|
52
|
+
icon = "🎨"
|
|
53
|
+
description = "Balances empathy with edge-case rigor, starts simple and evolves through feedback, every decision serves a genuine user need. Speaks like a filmmaker pitching the scene before the code exists, painting user stories that make you feel the problem."
|
|
54
|
+
|
|
55
|
+
[agents.bmad-agent-architect]
|
|
56
|
+
module = "bmm"
|
|
57
|
+
team = "software-development"
|
|
58
|
+
name = "Winston"
|
|
59
|
+
title = "System Architect"
|
|
60
|
+
icon = "🏗️"
|
|
61
|
+
description = "Favors boring technology for stability, developer productivity as architecture, ties every decision to business value. Speaks like a seasoned engineer at the whiteboard: measured, always laying out trade-offs rather than verdicts."
|
|
62
|
+
|
|
63
|
+
[agents.bmad-agent-dev]
|
|
64
|
+
module = "bmm"
|
|
65
|
+
team = "software-development"
|
|
66
|
+
name = "Amelia"
|
|
67
|
+
title = "Senior Software Engineer"
|
|
68
|
+
icon = "💻"
|
|
69
|
+
description = "Test-first discipline (red, green, refactor), 100% pass before review, no fluff all precision. Speaks like a terminal prompt: exact file paths, AC IDs, and commit-message brevity — every statement citable."
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────
|
|
2
|
+
# Installer-managed. Regenerated on every install — treat as read-only.
|
|
3
|
+
# Holds install answers scoped to YOU personally.
|
|
4
|
+
#
|
|
5
|
+
# Direct edits to this file will be overwritten on the next install.
|
|
6
|
+
# To change an answer durably, re-run the installer (your prior answers
|
|
7
|
+
# are remembered as defaults). For pinned overrides or custom sections
|
|
8
|
+
# the installer does not know about, use _bmad/custom/config.user.toml
|
|
9
|
+
# — it is never touched by the installer.
|
|
10
|
+
# ─────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
[core]
|
|
13
|
+
user_name = "Siesa-Team"
|
|
14
|
+
communication_language = "Spanish"
|
|
15
|
+
|
|
16
|
+
[modules.bmm]
|
|
17
|
+
user_skill_level = "intermediate"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
|
|
2
|
+
Core,_meta,,,,,,,,,false,https://docs.bmad-method.org/llms.txt,
|
|
3
|
+
Core,bmad-brainstorming,Brainstorming,BSP,Use early in ideation or when stuck generating ideas.,,anytime,,,false,{output_folder}/brainstorming,brainstorming session
|
|
4
|
+
Core,bmad-party-mode,Party Mode,PM,Orchestrate multi-agent discussions when you need multiple perspectives or want agents to collaborate.,,anytime,,,false,,
|
|
5
|
+
Core,bmad-help,BMad Help,BH,,,anytime,,,false,,
|
|
6
|
+
Core,bmad-index-docs,Index Docs,ID,Use when LLM needs to understand available docs without loading everything.,,anytime,,,false,,
|
|
7
|
+
Core,bmad-shard-doc,Shard Document,SD,Use when doc becomes too large (>500 lines) to manage effectively.,[path],anytime,,,false,,
|
|
8
|
+
Core,bmad-editorial-review-prose,Editorial Review - Prose,EP,Use after drafting to polish written content.,[path],anytime,,,false,report located with target document,three-column markdown table with suggested fixes
|
|
9
|
+
Core,bmad-editorial-review-structure,Editorial Review - Structure,ES,Use when doc produced from multiple subprocesses or needs structural improvement.,[path],anytime,,,false,report located with target document,
|
|
10
|
+
Core,bmad-review-adversarial-general,Adversarial Review,AR,"Use for quality assurance or before finalizing deliverables. Code Review in other modules runs this automatically, but also useful for document reviews.",[path],anytime,,,false,,
|
|
11
|
+
Core,bmad-review-edge-case-hunter,Edge Case Hunter Review,ECH,Use alongside adversarial review for orthogonal coverage — method-driven not attitude-driven.,[path],anytime,,,false,,
|
|
12
|
+
Core,bmad-distillator,Distillator,DG,Use when you need token-efficient distillates that preserve all information for downstream LLM consumption.,[path],anytime,,,false,adjacent to source document or specified output_path,distillate markdown file(s)
|
|
13
|
+
Core,bmad-customize,BMad Customize,BC,"Use when you want to change how an agent or workflow behaves — add persistent facts, swap templates, insert activation hooks, or customize menus. Scans what's customizable, picks the right scope (agent vs workflow), writes the override to _bmad/custom/, and verifies the merge. No TOML hand-authoring required.",,anytime,,,false,{project-root}/_bmad/custom,TOML override files
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Team / enterprise overrides for _bmad/config.toml.
|
|
2
|
+
# Committed to the repo — applies to every developer on the project.
|
|
3
|
+
# Tables deep-merge over base config; keyed entries merge by key.
|
|
4
|
+
# Example: override an agent descriptor, or add a new agent.
|
|
5
|
+
#
|
|
6
|
+
# [agents.bmad-agent-pm]
|
|
7
|
+
# description = "Prefers short, bulleted PRDs over narrative drafts."
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Resolve BMad's central config using four-layer TOML merge.
|
|
4
|
+
|
|
5
|
+
Reads from four layers (highest priority last):
|
|
6
|
+
1. {project-root}/_bmad/config.toml (installer-owned team)
|
|
7
|
+
2. {project-root}/_bmad/config.user.toml (installer-owned user)
|
|
8
|
+
3. {project-root}/_bmad/custom/config.toml (human-authored team, committed)
|
|
9
|
+
4. {project-root}/_bmad/custom/config.user.toml (human-authored user, gitignored)
|
|
10
|
+
|
|
11
|
+
Outputs merged JSON to stdout. Errors go to stderr.
|
|
12
|
+
|
|
13
|
+
Requires Python 3.11+ (uses stdlib `tomllib`). No `uv`, no `pip install`,
|
|
14
|
+
no virtualenv — plain `python3` is sufficient.
|
|
15
|
+
|
|
16
|
+
python3 resolve_config.py --project-root /abs/path/to/project
|
|
17
|
+
python3 resolve_config.py --project-root ... --key core
|
|
18
|
+
python3 resolve_config.py --project-root ... --key agents
|
|
19
|
+
|
|
20
|
+
Merge rules (same as resolve_customization.py):
|
|
21
|
+
- Scalars: override wins
|
|
22
|
+
- Tables: deep merge
|
|
23
|
+
- Arrays of tables where every item shares `code` or `id`: merge by that key
|
|
24
|
+
- All other arrays: append
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import json
|
|
29
|
+
import sys
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
import tomllib
|
|
34
|
+
except ImportError:
|
|
35
|
+
sys.stderr.write(
|
|
36
|
+
"error: Python 3.11+ is required (stdlib `tomllib` not found).\n"
|
|
37
|
+
)
|
|
38
|
+
sys.exit(3)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
_MISSING = object()
|
|
42
|
+
_KEYED_MERGE_FIELDS = ("code", "id")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def load_toml(file_path: Path, required: bool = False) -> dict:
|
|
46
|
+
if not file_path.exists():
|
|
47
|
+
if required:
|
|
48
|
+
sys.stderr.write(f"error: required config file not found: {file_path}\n")
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
return {}
|
|
51
|
+
try:
|
|
52
|
+
with file_path.open("rb") as f:
|
|
53
|
+
parsed = tomllib.load(f)
|
|
54
|
+
if not isinstance(parsed, dict):
|
|
55
|
+
return {}
|
|
56
|
+
return parsed
|
|
57
|
+
except tomllib.TOMLDecodeError as error:
|
|
58
|
+
level = "error" if required else "warning"
|
|
59
|
+
sys.stderr.write(f"{level}: failed to parse {file_path}: {error}\n")
|
|
60
|
+
if required:
|
|
61
|
+
sys.exit(1)
|
|
62
|
+
return {}
|
|
63
|
+
except OSError as error:
|
|
64
|
+
level = "error" if required else "warning"
|
|
65
|
+
sys.stderr.write(f"{level}: failed to read {file_path}: {error}\n")
|
|
66
|
+
if required:
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
return {}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _detect_keyed_merge_field(items):
|
|
72
|
+
if not items or not all(isinstance(item, dict) for item in items):
|
|
73
|
+
return None
|
|
74
|
+
for candidate in _KEYED_MERGE_FIELDS:
|
|
75
|
+
if all(item.get(candidate) is not None for item in items):
|
|
76
|
+
return candidate
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _merge_by_key(base, override, key_name):
|
|
81
|
+
result = []
|
|
82
|
+
index_by_key = {}
|
|
83
|
+
for item in base:
|
|
84
|
+
if not isinstance(item, dict):
|
|
85
|
+
continue
|
|
86
|
+
if item.get(key_name) is not None:
|
|
87
|
+
index_by_key[item[key_name]] = len(result)
|
|
88
|
+
result.append(dict(item))
|
|
89
|
+
for item in override:
|
|
90
|
+
if not isinstance(item, dict):
|
|
91
|
+
result.append(item)
|
|
92
|
+
continue
|
|
93
|
+
key = item.get(key_name)
|
|
94
|
+
if key is not None and key in index_by_key:
|
|
95
|
+
result[index_by_key[key]] = dict(item)
|
|
96
|
+
else:
|
|
97
|
+
if key is not None:
|
|
98
|
+
index_by_key[key] = len(result)
|
|
99
|
+
result.append(dict(item))
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _merge_arrays(base, override):
|
|
104
|
+
base_arr = base if isinstance(base, list) else []
|
|
105
|
+
override_arr = override if isinstance(override, list) else []
|
|
106
|
+
keyed_field = _detect_keyed_merge_field(base_arr + override_arr)
|
|
107
|
+
if keyed_field:
|
|
108
|
+
return _merge_by_key(base_arr, override_arr, keyed_field)
|
|
109
|
+
return base_arr + override_arr
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def deep_merge(base, override):
|
|
113
|
+
if isinstance(base, dict) and isinstance(override, dict):
|
|
114
|
+
result = dict(base)
|
|
115
|
+
for key, over_val in override.items():
|
|
116
|
+
if key in result:
|
|
117
|
+
result[key] = deep_merge(result[key], over_val)
|
|
118
|
+
else:
|
|
119
|
+
result[key] = over_val
|
|
120
|
+
return result
|
|
121
|
+
if isinstance(base, list) and isinstance(override, list):
|
|
122
|
+
return _merge_arrays(base, override)
|
|
123
|
+
return override
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def extract_key(data, dotted_key: str):
|
|
127
|
+
parts = dotted_key.split(".")
|
|
128
|
+
current = data
|
|
129
|
+
for part in parts:
|
|
130
|
+
if isinstance(current, dict) and part in current:
|
|
131
|
+
current = current[part]
|
|
132
|
+
else:
|
|
133
|
+
return _MISSING
|
|
134
|
+
return current
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def main():
|
|
138
|
+
parser = argparse.ArgumentParser(
|
|
139
|
+
description="Resolve BMad central config using four-layer TOML merge.",
|
|
140
|
+
)
|
|
141
|
+
parser.add_argument(
|
|
142
|
+
"--project-root", "-p", required=True,
|
|
143
|
+
help="Absolute path to the project root (contains _bmad/)",
|
|
144
|
+
)
|
|
145
|
+
parser.add_argument(
|
|
146
|
+
"--key", "-k", action="append", default=[],
|
|
147
|
+
help="Dotted field path to resolve (repeatable). Omit for full dump.",
|
|
148
|
+
)
|
|
149
|
+
args = parser.parse_args()
|
|
150
|
+
|
|
151
|
+
project_root = Path(args.project_root).resolve()
|
|
152
|
+
bmad_dir = project_root / "_bmad"
|
|
153
|
+
|
|
154
|
+
base_team = load_toml(bmad_dir / "config.toml", required=True)
|
|
155
|
+
base_user = load_toml(bmad_dir / "config.user.toml")
|
|
156
|
+
custom_team = load_toml(bmad_dir / "custom" / "config.toml")
|
|
157
|
+
custom_user = load_toml(bmad_dir / "custom" / "config.user.toml")
|
|
158
|
+
|
|
159
|
+
merged = deep_merge(base_team, base_user)
|
|
160
|
+
merged = deep_merge(merged, custom_team)
|
|
161
|
+
merged = deep_merge(merged, custom_user)
|
|
162
|
+
|
|
163
|
+
if args.key:
|
|
164
|
+
output = {}
|
|
165
|
+
for key in args.key:
|
|
166
|
+
value = extract_key(merged, key)
|
|
167
|
+
if value is not _MISSING:
|
|
168
|
+
output[key] = value
|
|
169
|
+
else:
|
|
170
|
+
output = merged
|
|
171
|
+
|
|
172
|
+
sys.stdout.write(json.dumps(output, indent=2, ensure_ascii=False) + "\n")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
main()
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Resolve customization for a BMad skill using three-layer TOML merge.
|
|
4
|
+
|
|
5
|
+
Reads customization from three layers (highest priority first):
|
|
6
|
+
1. {project-root}/_bmad/custom/{name}.user.toml (personal, gitignored)
|
|
7
|
+
2. {project-root}/_bmad/custom/{name}.toml (team/org, committed)
|
|
8
|
+
3. {skill-root}/customize.toml (skill defaults)
|
|
9
|
+
|
|
10
|
+
Skill name is derived from the basename of the skill directory.
|
|
11
|
+
|
|
12
|
+
Outputs merged JSON to stdout. Errors go to stderr.
|
|
13
|
+
|
|
14
|
+
Requires Python 3.11+ (uses stdlib `tomllib`). No `uv`, no `pip install`,
|
|
15
|
+
no virtualenv — plain `python3` is sufficient.
|
|
16
|
+
|
|
17
|
+
python3 resolve_customization.py --skill /abs/path/to/skill-dir
|
|
18
|
+
python3 resolve_customization.py --skill ... --key agent
|
|
19
|
+
python3 resolve_customization.py --skill ... --key agent.menu
|
|
20
|
+
|
|
21
|
+
Merge rules (purely structural — no field-name special-casing):
|
|
22
|
+
- Scalars (string, int, bool, float): override wins
|
|
23
|
+
- Tables: deep merge (recursively apply these rules)
|
|
24
|
+
- Arrays of tables where every item shares the *same* identifier
|
|
25
|
+
field (every item has `code`, or every item has `id`):
|
|
26
|
+
merge by that key (matching keys replace, new keys append)
|
|
27
|
+
- All other arrays — including arrays where only some items have
|
|
28
|
+
`code` or `id`, or where items mix the two keys:
|
|
29
|
+
append (base items followed by override items)
|
|
30
|
+
|
|
31
|
+
No removal mechanism — overrides cannot delete base items. To suppress
|
|
32
|
+
a default, fork the skill or override the item by code with a no-op
|
|
33
|
+
description/prompt.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import argparse
|
|
37
|
+
import json
|
|
38
|
+
import sys
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
import tomllib
|
|
43
|
+
except ImportError:
|
|
44
|
+
sys.stderr.write(
|
|
45
|
+
"error: Python 3.11+ is required (stdlib `tomllib` not found).\n"
|
|
46
|
+
"Install a newer Python or run the resolution manually per the\n"
|
|
47
|
+
"fallback instructions in the skill's SKILL.md.\n"
|
|
48
|
+
)
|
|
49
|
+
sys.exit(3)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
_MISSING = object()
|
|
53
|
+
_KEYED_MERGE_FIELDS = ("code", "id")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def find_project_root(start: Path):
|
|
57
|
+
current = start.resolve()
|
|
58
|
+
while True:
|
|
59
|
+
if (current / "_bmad").exists() or (current / ".git").exists():
|
|
60
|
+
return current
|
|
61
|
+
parent = current.parent
|
|
62
|
+
if parent == current:
|
|
63
|
+
return None
|
|
64
|
+
current = parent
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def load_toml(file_path: Path, required: bool = False) -> dict:
|
|
68
|
+
if not file_path.exists():
|
|
69
|
+
if required:
|
|
70
|
+
sys.stderr.write(f"error: required customization file not found: {file_path}\n")
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
return {}
|
|
73
|
+
try:
|
|
74
|
+
with file_path.open("rb") as f:
|
|
75
|
+
parsed = tomllib.load(f)
|
|
76
|
+
if not isinstance(parsed, dict):
|
|
77
|
+
if required:
|
|
78
|
+
sys.stderr.write(f"error: {file_path} did not parse to a table\n")
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
return {}
|
|
81
|
+
return parsed
|
|
82
|
+
except tomllib.TOMLDecodeError as error:
|
|
83
|
+
level = "error" if required else "warning"
|
|
84
|
+
sys.stderr.write(f"{level}: failed to parse {file_path}: {error}\n")
|
|
85
|
+
if required:
|
|
86
|
+
sys.exit(1)
|
|
87
|
+
return {}
|
|
88
|
+
except OSError as error:
|
|
89
|
+
level = "error" if required else "warning"
|
|
90
|
+
sys.stderr.write(f"{level}: failed to read {file_path}: {error}\n")
|
|
91
|
+
if required:
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
return {}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _detect_keyed_merge_field(items):
|
|
97
|
+
"""Return 'code' or 'id' if every table item carries that *same* field.
|
|
98
|
+
|
|
99
|
+
All items must share the same identifier (all `code`, or all `id`).
|
|
100
|
+
Mixed arrays — where some items use `code` and others use `id` —
|
|
101
|
+
return None and fall through to append semantics. This is intentional:
|
|
102
|
+
mixing identifier keys within one array is a schema smell, and
|
|
103
|
+
append-fallback is safer than guessing which key should merge.
|
|
104
|
+
"""
|
|
105
|
+
if not items or not all(isinstance(item, dict) for item in items):
|
|
106
|
+
return None
|
|
107
|
+
for candidate in _KEYED_MERGE_FIELDS:
|
|
108
|
+
if all(item.get(candidate) is not None for item in items):
|
|
109
|
+
return candidate
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _merge_by_key(base, override, key_name):
|
|
114
|
+
result = []
|
|
115
|
+
index_by_key = {}
|
|
116
|
+
|
|
117
|
+
for item in base:
|
|
118
|
+
if not isinstance(item, dict):
|
|
119
|
+
continue
|
|
120
|
+
if item.get(key_name) is not None:
|
|
121
|
+
index_by_key[item[key_name]] = len(result)
|
|
122
|
+
result.append(dict(item))
|
|
123
|
+
|
|
124
|
+
for item in override:
|
|
125
|
+
if not isinstance(item, dict):
|
|
126
|
+
result.append(item)
|
|
127
|
+
continue
|
|
128
|
+
key = item.get(key_name)
|
|
129
|
+
if key is not None and key in index_by_key:
|
|
130
|
+
result[index_by_key[key]] = dict(item)
|
|
131
|
+
else:
|
|
132
|
+
if key is not None:
|
|
133
|
+
index_by_key[key] = len(result)
|
|
134
|
+
result.append(dict(item))
|
|
135
|
+
|
|
136
|
+
return result
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _merge_arrays(base, override):
|
|
140
|
+
"""Shape-aware array merge. Base + override combined tables may opt into
|
|
141
|
+
keyed merge if every item has `code` or `id`. Otherwise: append."""
|
|
142
|
+
base_arr = base if isinstance(base, list) else []
|
|
143
|
+
override_arr = override if isinstance(override, list) else []
|
|
144
|
+
keyed_field = _detect_keyed_merge_field(base_arr + override_arr)
|
|
145
|
+
if keyed_field:
|
|
146
|
+
return _merge_by_key(base_arr, override_arr, keyed_field)
|
|
147
|
+
return base_arr + override_arr
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def deep_merge(base, override):
|
|
151
|
+
"""Recursively merge override into base using structural rules.
|
|
152
|
+
- Table + table: deep merge
|
|
153
|
+
- Array + array: shape-aware (keyed merge if all items have code/id, else append)
|
|
154
|
+
- Anything else: override wins
|
|
155
|
+
"""
|
|
156
|
+
if isinstance(base, dict) and isinstance(override, dict):
|
|
157
|
+
result = dict(base)
|
|
158
|
+
for key, over_val in override.items():
|
|
159
|
+
if key in result:
|
|
160
|
+
result[key] = deep_merge(result[key], over_val)
|
|
161
|
+
else:
|
|
162
|
+
result[key] = over_val
|
|
163
|
+
return result
|
|
164
|
+
if isinstance(base, list) and isinstance(override, list):
|
|
165
|
+
return _merge_arrays(base, override)
|
|
166
|
+
return override
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def extract_key(data, dotted_key: str):
|
|
170
|
+
parts = dotted_key.split(".")
|
|
171
|
+
current = data
|
|
172
|
+
for part in parts:
|
|
173
|
+
if isinstance(current, dict) and part in current:
|
|
174
|
+
current = current[part]
|
|
175
|
+
else:
|
|
176
|
+
return _MISSING
|
|
177
|
+
return current
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def main():
|
|
181
|
+
parser = argparse.ArgumentParser(
|
|
182
|
+
description="Resolve customization for a BMad skill using three-layer TOML merge.",
|
|
183
|
+
add_help=True,
|
|
184
|
+
)
|
|
185
|
+
parser.add_argument(
|
|
186
|
+
"--skill", "-s", required=True,
|
|
187
|
+
help="Absolute path to the skill directory (must contain customize.toml)",
|
|
188
|
+
)
|
|
189
|
+
parser.add_argument(
|
|
190
|
+
"--key", "-k", action="append", default=[],
|
|
191
|
+
help="Dotted field path to resolve (repeatable). Omit for full dump.",
|
|
192
|
+
)
|
|
193
|
+
args = parser.parse_args()
|
|
194
|
+
|
|
195
|
+
skill_dir = Path(args.skill).resolve()
|
|
196
|
+
skill_name = skill_dir.name
|
|
197
|
+
defaults_path = skill_dir / "customize.toml"
|
|
198
|
+
|
|
199
|
+
defaults = load_toml(defaults_path, required=True)
|
|
200
|
+
|
|
201
|
+
# Prefer the project that contains this skill. Only fall back to cwd if
|
|
202
|
+
# the skill isn't inside a recognizable project tree (unusual but possible
|
|
203
|
+
# for standalone skills invoked directly). Using cwd first is unsafe when
|
|
204
|
+
# an ancestor of cwd happens to have a stray _bmad/ from another project.
|
|
205
|
+
project_root = find_project_root(skill_dir) or find_project_root(Path.cwd())
|
|
206
|
+
|
|
207
|
+
team = {}
|
|
208
|
+
user = {}
|
|
209
|
+
if project_root:
|
|
210
|
+
custom_dir = project_root / "_bmad" / "custom"
|
|
211
|
+
team = load_toml(custom_dir / f"{skill_name}.toml")
|
|
212
|
+
user = load_toml(custom_dir / f"{skill_name}.user.toml")
|
|
213
|
+
|
|
214
|
+
merged = deep_merge(defaults, team)
|
|
215
|
+
merged = deep_merge(merged, user)
|
|
216
|
+
|
|
217
|
+
if args.key:
|
|
218
|
+
output = {}
|
|
219
|
+
for key in args.key:
|
|
220
|
+
value = extract_key(merged, key)
|
|
221
|
+
if value is not _MISSING:
|
|
222
|
+
output[key] = value
|
|
223
|
+
else:
|
|
224
|
+
output = merged
|
|
225
|
+
|
|
226
|
+
sys.stdout.write(json.dumps(output, indent=2, ensure_ascii=False) + "\n")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
main()
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sa-wds-visual-proposals
|
|
3
|
+
description: 'Toma los artefactos de planning ya hechos (PRD, épicas/historias, UX spec, arquitectura) como base y dirige el módulo WDS (Freya) para generar propuestas visuales — escenarios UX, page-specs y prototipos renderizados con siesa-ui-kit — ayudando a los diseñadores. Úsalo cuando el usuario diga "generar propuestas visuales", "wds visual proposals", "diseñar pantallas desde el planning" o quiera convertir el planning en mockups con siesa-ui-kit.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: FIRST load the FULL @_siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/workflow_ext.md and apply its mandatory Siesa rules. THEN load the FULL @_siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/workflow.md, READ its entire contents and follow its directions exactly!
|
package/package.json
CHANGED
package/siesa-agents/bmm/workflows/3-solutioning/wds-visual-proposals/data/component-mapping.csv
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
ui_need,siesa_uikit_component,level,notes
|
|
2
|
+
Botón de acción / CTA,Button,atom,"variantes Default/Outline/Plain, soporta icono"
|
|
3
|
+
Grupo de botones tipo toggle,ButtonGroup,atom,selección estilo radio
|
|
4
|
+
Contenedor de contenido,Card,atom,"subcomponentes Header/Title/Content/Footer"
|
|
5
|
+
Etiqueta / estado / categoría,Badge,atom,variantes de color
|
|
6
|
+
Diálogo modal / confirmación,Alert Dialog,atom,alertas y diálogos del sistema
|
|
7
|
+
Imagen de perfil de usuario,Avatar,atom,
|
|
8
|
+
Casilla de verificación,Checkbox,atom,
|
|
9
|
+
Selección única en grupo,Radio,atom,"RadioGroup, RadioGroupItem"
|
|
10
|
+
Interruptor on/off,Switch,atom,
|
|
11
|
+
Campo de texto,Input,atom,
|
|
12
|
+
Campo numérico,InputNumber,atom,
|
|
13
|
+
Área de texto multilínea,Textarea,atom,
|
|
14
|
+
Selector desplegable,Select,atom,navegación por teclado
|
|
15
|
+
Menú de opciones,Dropdown,atom,"items, headings, dividers"
|
|
16
|
+
Navegación por pestañas,Tabs,atom,soporta icono/badge
|
|
17
|
+
Tabla de datos,Table,atom,"ordenamiento, variantes visuales"
|
|
18
|
+
Separador de contenido,Divider,atom,
|
|
19
|
+
Paginación,Pagination,atom,
|
|
20
|
+
Selección jerárquica con checkboxes,Tree,atom,cascada
|
|
21
|
+
Mensaje informativo / banner,Info,atom,
|
|
22
|
+
Notificación temporal,Toast,atom,sistema de notificaciones
|
|
23
|
+
Contador de alertas,Notification,atom,badge con contador
|
|
24
|
+
Navegación lateral,NavigationRail,navigation,"con NavigationRailGroup/Item/Panel"
|
|
25
|
+
Navegación inferior móvil,NavigationBar,navigation,3-5 destinos
|
|
26
|
+
Carga de archivos,FileUploader,file,"drag-and-drop, progreso, validación"
|
|
27
|
+
Galería de archivos,FileUploaderGallery,file,
|
|
28
|
+
Búsqueda de entidad relacionada,LookupField,form,relación entre entidades
|
|
29
|
+
Lista clave-valor,DescriptionList,form,
|
|
30
|
+
Guardar/restaurar filtros,FormCacheSelector,form,
|
|
31
|
+
Gestión CRUD de entidad,MasterCrud,enterprise,"listados+formularios+acciones; modos Modal/Sidebar/Page; consultar skill MasterCrud"
|
|
32
|
+
Contenedor de formulario CRUD,MasterPatternView,enterprise,
|
|
33
|
+
Gestión documental,MasterDocument,enterprise,"InstallmentsPanel, WithholdingsPanel, etc."
|
|
34
|
+
Auditoría (historial + detalle),AuditHistoryPanel,audit,"timeline + diff campo a campo"
|
|
35
|
+
Pantalla de login,LoginView,view,vista completa de inicio de sesión
|
|
36
|
+
Pantalla de registro,SignUpView,view,con aceptación de términos
|
|
37
|
+
Recuperar contraseña,RecoverPasswordView,view,
|
|
38
|
+
Layout comercial (rail + navbar),LayoutBase,view,
|
|
39
|
+
Contenedor principal con toolbar,LayoutContent,view,
|
|
40
|
+
Vista de lista genérica,ListView,view,
|
|
41
|
+
Tablero / dashboard,Dashboard,view,
|
|
42
|
+
Selección de productos POS,ProductsView,view,categorías/grid/carrito
|
|
43
|
+
Gestión de mesas POS,TableLayoutView,view,
|
|
44
|
+
Gestión de contactos,ContactManager,view,CRUD completo de contactos
|
|
45
|
+
Chat de soporte,ChatWidget,view,flotante
|
|
46
|
+
Edición de parámetros del sistema,ParameterEditor,config,Server-Driven UI
|
|
47
|
+
Administración de entidades dinámicas,Dynamic Entities/Admin,dynamic,no-code
|