baldart 3.27.1 → 3.28.1
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/CHANGELOG.md +44 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/codebase-architect.md +11 -0
- package/framework/.claude/hooks/capture-detect.sh +121 -0
- package/framework/.claude/skills/bug/SKILL.md +12 -0
- package/framework/.claude/skills/prd/SKILL.md +11 -2
- package/framework/.claude/skills/prd/assets/state-template.md +10 -3
- package/framework/.claude/skills/prd/references/discovery-phase.md +180 -11
- package/framework/docs/MCP-INTEGRATION.md +119 -0
- package/package.json +1 -1
- package/src/commands/add.js +54 -13
- package/src/commands/update.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,50 @@ All notable changes to BALDART will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.28.1] - 2026-05-28
|
|
9
|
+
|
|
10
|
+
Patch su tre drift segnalati dal curator dopo v3.28.0 install in `mayo`:
|
|
11
|
+
(1) `--yes` non si propaga da `update --reset` al child `baldart add`,
|
|
12
|
+
(2) errore "Configuring alias is not permitted without enabling allowUnsafeAlias" stampato come install-failed mentre l'install era OK,
|
|
13
|
+
(3) due template `ui-guidelines.template.md` + `brand-guidelines.md` lasciati untracked senza istruzioni chiare all'utente. Tutti e tre cosmetici/UX, nessuno affecta la correctness del framework installato — ma confondono l'utente durante il post-install.
|
|
14
|
+
|
|
15
|
+
### Fixed — `baldart add` honors `--yes` from parent caller
|
|
16
|
+
|
|
17
|
+
- **[src/commands/add.js](src/commands/add.js)** + **[src/commands/update.js:237](src/commands/update.js)**: `add(repo, options)` ora legge `options.yes` e auto-conferma i prompt non-distruttivi (`Install framework?`, `Configure git aliases?`, `Configure project context now?`). Il prompt distruttivo `Remove and reinstall?` resta interattivo anche con `--yes` (safety). `update --reset` ora invoca correttamente `addCmd(undefined, { yes: true })` — prima passava `{ yes: true }` come **primo argomento** (cioè `repo`), facendo `options` undefined e ogni prompt scattava.
|
|
18
|
+
|
|
19
|
+
### Fixed — Git alias config failure non più mascherato da install-failure
|
|
20
|
+
|
|
21
|
+
- **[src/commands/add.js](src/commands/add.js)**: la configurazione degli alias `fw-version`/`fw-update`/`fw-push` passa da `git.git.addConfig()` (simple-git, che rifiuta i bang-alias senza `allowUnsafeAlias`) a `spawnSync('git', ['config', key, value])` diretto. Il bypass del check simple-git è esplicito qui: l'utente sta opt-in agli alias durante l'install. Failure isolato per alias (non bubble-up al catch globale), reported come WARNING se non-zero count, install continua. Il messaggio "✗ Installation failed: Configuring alias is not permitted…" non appare più.
|
|
22
|
+
|
|
23
|
+
### Fixed — Template editable post-install: istruzioni chiare
|
|
24
|
+
|
|
25
|
+
- **[src/commands/add.js](src/commands/add.js)** NEXT STEPS box: i due template `docs/references/ui-guidelines.template.md` e `docs/references/brand-guidelines.md`, copiati incondizionatamente durante `copyCustomizableFiles()`, ora sono elencati esplicitamente con cosa farne (rename / edit / delete) e con il punto chiave: "Commit them to track your project's design language, or add them to .gitignore if you don't need them." Evita la confusione del curator durante v3.28.0 install ("non chiari se debbano essere scelti/scartati dall'utente o committati. Non c'è prompt che lo chieda").
|
|
26
|
+
|
|
27
|
+
## [3.28.0] - 2026-05-28
|
|
28
|
+
|
|
29
|
+
Tre additions indipendenti accumulate nel working tree e pronte per il rilascio: convenzione testuale per le dipendenze MCP, supporto `.zip` per il mockup intake del PRD, e nuovo hook `capture-detect` come parte del proactive mode dello skill `/capture` (registrazione opt-in, non auto-attivata). Tre temi distinti ma raggruppati in un'unica release di accumulo perché tutti additive e zero-schema-change.
|
|
30
|
+
|
|
31
|
+
### Added — Convenzione MCP integration
|
|
32
|
+
|
|
33
|
+
- **[framework/docs/MCP-INTEGRATION.md](framework/docs/MCP-INTEGRATION.md)**: nuovo documento centralizzato. Spiega quando un agent/skill deve appoggiarsi a un MCP server, fornisce un catalogo di MCP raccomandati per i casi d'uso comuni (doc-rag, playwright, firestore/db, LSP, …), e definisce la convenzione testuale "MCP dependencies" per dichiarare le dipendenze nel body dell'agent/skill. Zero nuove chiavi config in `baldart.config.yml` — la convenzione resta testuale finché una skill concreta non dovrà gate-arne il comportamento (regola di schema-change propagation: niente layer drift).
|
|
34
|
+
- **[framework/.claude/agents/codebase-architect.md](framework/.claude/agents/codebase-architect.md)**: aggiunta sezione `## MCP dependencies` con classificazione Required (`doc-rag` come primo step dell'Investigation Protocol) vs Optional (LSP find-references, DB MCP per inspect runtime). Documentato il degrade path quando l'MCP non è disponibile.
|
|
35
|
+
- **[framework/.claude/skills/bug/SKILL.md](framework/.claude/skills/bug/SKILL.md)**: aggiunta sezione `## MCP dependencies` con Required (`playwright` per Phase 1 reproduction di UI/Client bug — senza è impossibile catturare stato deterministico) e Optional (`doc-rag` per known patterns, DB MCP per Data bugs, `codebase-architect` agent).
|
|
36
|
+
|
|
37
|
+
### Added — PRD mockup intake da archivio `.zip`
|
|
38
|
+
|
|
39
|
+
- **[framework/.claude/skills/prd/SKILL.md](framework/.claude/skills/prd/SKILL.md)** Step 1.6: nuovo formato `local-archive` accettato accanto a `chat-images` / `local-paths` / `mixed`. Caso d'uso: export "Download as .zip" da Claude Design (o qualsiasi altro tool che produce bundle di mockup) già scaricato sul disco dell'utente.
|
|
40
|
+
- **[framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md)** § Mockup Intake: Step 1.6.4b descrive l'intero flow per `.zip` — `unzip` in scratch dir `mockups/_archive/`, enumerazione candidati visivi, scoring di rilevanza contro lo scope del Kickoff, selezione auto-proposta, STOP per conferma, materializzazione del sottoinsieme confermato in `${paths.prd_dir}/<slug>/mockups/`. Evita di copiare PNG irrilevanti nell'asset directory definitiva.
|
|
41
|
+
- **[framework/.claude/skills/prd/assets/state-template.md](framework/.claude/skills/prd/assets/state-template.md)**: aggiornato `mockups.format` enum per includere `local-archive`.
|
|
42
|
+
|
|
43
|
+
### Added — Hook `capture-detect` (proactive mode, opt-in)
|
|
44
|
+
|
|
45
|
+
- **[framework/.claude/hooks/capture-detect.sh](framework/.claude/hooks/capture-detect.sh)**: nuovo Stop hook che drop una candidate JSON in `.claude/capture-queue/` quando rileva ragionamento cross-document nella sessione appena chiusa. La distillazione vera in synthesis page wiki resta sempre una human-approved manual step via lo skill `/capture`. Failure-isolated (exit 0 sempre, non blocca lo Stop event).
|
|
46
|
+
- **Registrazione opt-in (NOT auto-attivata)**: la entry corrispondente in [src/utils/hooks.js](src/utils/hooks.js) resta commentata (linee 90-97). Lo skill `/capture` funziona già in modalità manual senza il hook; il proactive mode è una feature opzionale. Per attivarlo nel proprio consumer: scommentare la entry e re-installare via `npx baldart update`. Una futura release potrà rendere il proactive il default.
|
|
47
|
+
|
|
48
|
+
### Added — Smoke test del hooks registry
|
|
49
|
+
|
|
50
|
+
- **[scripts/test-hooks.sh](scripts/test-hooks.sh)**: nuovo smoke test per `src/utils/hooks.js` (multi-hook registry introdotto v3.18.0). Verifica register/unregister/isRegistered/merge idempotente con fixture in tmpdir. Dev tooling, non user-visible.
|
|
51
|
+
|
|
8
52
|
## [3.27.1] - 2026-05-28
|
|
9
53
|
|
|
10
54
|
Patch follow-up alla v3.27.0 dopo l'incidente reale in `mayo`: l'utente aveva CLI globale v3.24.0 e ha eseguito `/baldart-update` per aggiornarsi a v3.27.0. La skill ha rilanciato `npx baldart update`, che ha aggiornato il framework payload da v3.24 a v3.27, ma `update.js` in esecuzione era il binario v3.24.0 — quello che precede sia il meccanismo di auto-relaunch (introdotto v3.26.0) sia la logica di symlink-indirection (v3.27.0). Risultato: i 6 agent overlay-merged sono stati rigenerati con la **vecchia logica** (file regolari direttamente in `.claude/agents/`), e quindi il fix v3.27.0 NON si è attivato — `npx baldart doctor` ha riportato "tutto healthy" ma in realtà gli agent erano ancora invisibili a Claude Code (bug #20931). Chicken-and-egg: il CLI vecchio non sa rilanciare il nuovo, il nuovo non è ancora in esecuzione.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.28.1
|
|
@@ -37,6 +37,17 @@ This codebase follows strict protocols defined in AGENTS.md. Key architectural r
|
|
|
37
37
|
- `/docs/references/project-status.md` - Current system state and active work
|
|
38
38
|
- `agents/coding-standards.md` - Terminology and coding conventions
|
|
39
39
|
|
|
40
|
+
## MCP dependencies
|
|
41
|
+
|
|
42
|
+
See [framework/docs/MCP-INTEGRATION.md](../../docs/MCP-INTEGRATION.md) for the BALDART MCP integration contract and the rationale behind this section.
|
|
43
|
+
|
|
44
|
+
**Required** (this agent's primary investigation protocol assumes them; degraded operation only):
|
|
45
|
+
- `mcp__doc-rag__search_docs` — semantic + knowledge-graph search across project docs. This is the **first** call in the Investigation Protocol; without it the agent falls back to broad `rg` sweeps that blow the token budget and miss canonical sources. If the MCP is unavailable the agent must announce the degrade explicitly and switch to targeted `rg` over `docs/`, `backlog/`, and `.claude/agents/` (see § Investigation Protocol step 1).
|
|
46
|
+
|
|
47
|
+
**Optional** (the agent benefits if present, has a documented fallback):
|
|
48
|
+
- LSP find-references / go-to-definition (whichever LSP MCP / plugin is wired by [features.has_lsp_layer](../../templates/baldart.config.template.yml)) — preferred over `rg` for symbol queries (cap: 3 LSP calls per task, then escalate to direct file reads). Fallback: silent degrade to Grep, per [code-search-protocol.md](../../agents/code-search-protocol.md).
|
|
49
|
+
- `mcp__plugin_firebase_firebase__firestore_*` (or equivalent DB MCP) — only when the architectural analysis needs to inspect runtime DB state (rare for an architect agent). Fallback: read schema docs in `${paths.references_dir}` and rely on declared structure.
|
|
50
|
+
|
|
40
51
|
## Linking Protocol Consumption (MUST)
|
|
41
52
|
|
|
42
53
|
You consume Linking Protocol v1 in read-only mode to find the right facts faster before
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# capture-detect.sh — BALDART proactive capture hook (event: Stop)
|
|
4
|
+
#
|
|
5
|
+
# Runs at the end of every Claude Code session. When the just-finished
|
|
6
|
+
# session contains cross-document reasoning (the user has been weaving
|
|
7
|
+
# together facts from multiple docs/references files), this hook drops a
|
|
8
|
+
# *candidate* file into `.claude/capture-queue/` so the next `/capture`
|
|
9
|
+
# invocation can surface it and offer to distill the synthesis into a
|
|
10
|
+
# durable wiki page.
|
|
11
|
+
#
|
|
12
|
+
# This hook NEVER spawns Claude itself — it only writes a small JSON
|
|
13
|
+
# candidate. The actual synthesis is always a human-approved manual step
|
|
14
|
+
# via the `capture` skill.
|
|
15
|
+
#
|
|
16
|
+
# Stdin: Claude Code passes a JSON envelope; we read `transcript_path`,
|
|
17
|
+
# `session_id`, `cwd` (best-effort — falls back if jq is unavailable).
|
|
18
|
+
#
|
|
19
|
+
# Exit: always 0. Failure isolation — a non-zero exit on a Stop hook can
|
|
20
|
+
# be ignored by the runtime, but as a matter of hygiene we never
|
|
21
|
+
# propagate errors out of an instrumentation hook.
|
|
22
|
+
|
|
23
|
+
set -u
|
|
24
|
+
exec 2>/dev/null # silence stderr; we are not user-visible
|
|
25
|
+
|
|
26
|
+
# --- read envelope --------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
INPUT=""
|
|
29
|
+
if [ ! -t 0 ]; then
|
|
30
|
+
INPUT="$(cat)"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Try jq first, fall back to grep/sed extraction.
|
|
34
|
+
get_field() {
|
|
35
|
+
local field="$1"
|
|
36
|
+
if command -v jq >/dev/null 2>&1; then
|
|
37
|
+
printf '%s' "$INPUT" | jq -r ".$field // empty" 2>/dev/null
|
|
38
|
+
else
|
|
39
|
+
printf '%s' "$INPUT" | sed -n "s/.*\"$field\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p" | head -1
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
TRANSCRIPT_PATH="$(get_field transcript_path)"
|
|
44
|
+
SESSION_ID="$(get_field session_id)"
|
|
45
|
+
CWD_FROM_ENV="$(get_field cwd)"
|
|
46
|
+
CWD="${CWD_FROM_ENV:-$PWD}"
|
|
47
|
+
|
|
48
|
+
[ -n "$TRANSCRIPT_PATH" ] || exit 0
|
|
49
|
+
[ -f "$TRANSCRIPT_PATH" ] || exit 0
|
|
50
|
+
|
|
51
|
+
cd "$CWD" 2>/dev/null || exit 0
|
|
52
|
+
|
|
53
|
+
# --- gate on features.has_wiki_overlay -----------------------------------
|
|
54
|
+
|
|
55
|
+
CONFIG="baldart.config.yml"
|
|
56
|
+
[ -f "$CONFIG" ] || exit 0
|
|
57
|
+
# Coarse check: look for `has_wiki_overlay: true` (whitespace-tolerant).
|
|
58
|
+
if ! grep -E '^\s*has_wiki_overlay\s*:\s*true\b' "$CONFIG" >/dev/null 2>&1; then
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# --- gates: kill switch + anti-spam --------------------------------------
|
|
63
|
+
|
|
64
|
+
QUEUE_DIR=".claude/capture-queue"
|
|
65
|
+
mkdir -p "$QUEUE_DIR" || exit 0
|
|
66
|
+
|
|
67
|
+
[ -f "$QUEUE_DIR/.disabled" ] && exit 0
|
|
68
|
+
|
|
69
|
+
# Anti-spam: refuse when ≥10 unprocessed candidates already queued.
|
|
70
|
+
EXISTING="$(find "$QUEUE_DIR" -maxdepth 1 -type f -name '*.json' 2>/dev/null | wc -l | tr -d ' ')"
|
|
71
|
+
[ "${EXISTING:-0}" -ge 10 ] && exit 0
|
|
72
|
+
|
|
73
|
+
# --- heuristic: is this session worth flagging? --------------------------
|
|
74
|
+
#
|
|
75
|
+
# We treat "≥3 distinct docs/references-style paths mentioned across the
|
|
76
|
+
# session" as a weak signal of cross-document reasoning. False positives
|
|
77
|
+
# are acceptable here — the user reviews every candidate in /capture and
|
|
78
|
+
# can reject. False negatives are also fine — the user can always invoke
|
|
79
|
+
# /capture manually.
|
|
80
|
+
|
|
81
|
+
REFS="$(grep -ohE '(\./|/|\b)((docs|wiki|references|backlog|prd)/[A-Za-z0-9._/-]+\.(md|yml|yaml|json))' "$TRANSCRIPT_PATH" 2>/dev/null \
|
|
82
|
+
| sort -u | head -10)"
|
|
83
|
+
|
|
84
|
+
REF_COUNT="$(printf '%s\n' "$REFS" | grep -c . || true)"
|
|
85
|
+
[ "${REF_COUNT:-0}" -lt 3 ] && exit 0
|
|
86
|
+
|
|
87
|
+
# --- write candidate ------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
TS_FILE="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
90
|
+
TS_HUMAN="$(date -u +'%Y-%m-%d %H:%M UTC')"
|
|
91
|
+
OUT="$QUEUE_DIR/${TS_FILE}-${SESSION_ID:-unknown}.json"
|
|
92
|
+
|
|
93
|
+
# JSON-escape with awk (no jq required for emit either).
|
|
94
|
+
escape_json() {
|
|
95
|
+
printf '%s' "$1" | awk 'BEGIN{ORS=""} {gsub(/\\/,"\\\\"); gsub(/"/,"\\\""); gsub(/\r/,""); gsub(/\n/,"\\n"); print}'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
REFS_JSON="["
|
|
99
|
+
first=1
|
|
100
|
+
while IFS= read -r r; do
|
|
101
|
+
[ -z "$r" ] && continue
|
|
102
|
+
if [ $first -eq 1 ]; then first=0; else REFS_JSON="$REFS_JSON,"; fi
|
|
103
|
+
REFS_JSON="$REFS_JSON\"$(escape_json "$r")\""
|
|
104
|
+
done <<EOF
|
|
105
|
+
$REFS
|
|
106
|
+
EOF
|
|
107
|
+
REFS_JSON="$REFS_JSON]"
|
|
108
|
+
|
|
109
|
+
cat > "$OUT" <<JSON
|
|
110
|
+
{
|
|
111
|
+
"trigger": "cross_doc_refs",
|
|
112
|
+
"detected_at": "$TS_HUMAN",
|
|
113
|
+
"session_id": "$(escape_json "${SESSION_ID:-unknown}")",
|
|
114
|
+
"transcript_path": "$(escape_json "$TRANSCRIPT_PATH")",
|
|
115
|
+
"refs_mentioned": $REFS_JSON,
|
|
116
|
+
"excerpt": "Session referenced ${REF_COUNT} distinct doc paths — possible cross-document synthesis worth capturing.",
|
|
117
|
+
"hint": "Run /capture to review this candidate."
|
|
118
|
+
}
|
|
119
|
+
JSON
|
|
120
|
+
|
|
121
|
+
exit 0
|
|
@@ -21,6 +21,18 @@ Argument: optional bug description (e.g., `/bug feature X is not saving`).
|
|
|
21
21
|
**Overlay:** loads `.baldart/overlays/bug.md` if present — project-specific debug entry points (e.g. SWR debug switches, env summary helpers, error-code modules). The base skill stays generic; project-specific code paths live in the overlay.
|
|
22
22
|
**On missing/empty keys:** ask the user; do not assume defaults. See `framework/agents/project-context.md` § 3.
|
|
23
23
|
|
|
24
|
+
## MCP dependencies
|
|
25
|
+
|
|
26
|
+
See [framework/docs/MCP-INTEGRATION.md](../../../docs/MCP-INTEGRATION.md) for the BALDART MCP integration contract and the rationale behind this section.
|
|
27
|
+
|
|
28
|
+
**Required** (skill cannot complete its task without these MCPs for the relevant bug class):
|
|
29
|
+
- `mcp__playwright__browser_*` (`browser_navigate`, `browser_take_screenshot`, `browser_console_messages`, `browser_network_requests`, `browser_evaluate`) — Phase 1 reproduction for **UI/Client** bugs. Without it the skill cannot capture deterministic state and Phase 1 degrades to "ask the user to reproduce manually and paste console logs". Phase 2's client-side `window.fetch` interception is impossible without `browser_evaluate`.
|
|
30
|
+
|
|
31
|
+
**Optional** (the skill benefits if present, has a documented fallback):
|
|
32
|
+
- `mcp__doc-rag__search_docs` — Phase 0 lookup for known patterns and error codes. Fallback: targeted `rg` over the project's error-code module (path listed in `.baldart/overlays/bug.md`) and `docs/wiki/`.
|
|
33
|
+
- `mcp__plugin_firebase_firebase__firestore_*` (or the project's DB MCP, when `stack.database.primary` is set) — Phase 1 inspection of runtime data state for **Data** bugs. Fallback: ask the user for a document export, or read the relevant code path and infer.
|
|
34
|
+
- `codebase-architect` agent (always available, listed for completeness) — Phase 0 code-path mapping. Not an MCP per se but is treated as a required dependency by this skill.
|
|
35
|
+
|
|
24
36
|
## ANTI-PATTERNS (NEVER DO)
|
|
25
37
|
|
|
26
38
|
- NEVER change code before reproducing the bug
|
|
@@ -92,8 +92,17 @@ message. You ask questions, wait for answers, and iterate.
|
|
|
92
92
|
structure and `assets/card-template.yml` for child structure.
|
|
93
93
|
16. **Mockup Intake (MANDATORY).** Subito dopo Kickoff (Step 1) e prima di entrare in
|
|
94
94
|
Discovery (Step 2), esegui Step 1.6 — chiedi all'utente se ha mockup a disposizione.
|
|
95
|
-
Se **sì**: chiedi formato (immagini in chat / path locali
|
|
96
|
-
|
|
95
|
+
Se **sì**: chiedi formato (immagini in chat / path locali — singoli file **o
|
|
96
|
+
archivi `.zip`** — / misti), **STOP**, attendi. Sull'arrivo:
|
|
97
|
+
- **chat-images** / file singoli in **local-paths**: copia in `${paths.prd_dir}/<slug>/mockups/`,
|
|
98
|
+
passa subito all'analisi.
|
|
99
|
+
- **`.zip` in local-paths** (es. export "Download as .zip" da Claude Design già
|
|
100
|
+
sul disco): esegui Step 1.6.4b — `unzip` in scratch dir sotto `mockups/_archive/`,
|
|
101
|
+
enumera i candidati visivi, calcola uno score di rilevanza contro lo scope
|
|
102
|
+
del Kickoff, presenta la selezione auto-proposta, **STOP**, attendi conferma,
|
|
103
|
+
poi materializza solo il sottoinsieme confermato in `${paths.prd_dir}/<slug>/mockups/`.
|
|
104
|
+
|
|
105
|
+
Quindi analizza in dettaglio (vedi
|
|
97
106
|
[discovery-phase.md](references/discovery-phase.md) § "Mockup analysis schema"), popola
|
|
98
107
|
`## UI Design` nello state, poi entra in Discovery. Se **no**: marca
|
|
99
108
|
`mockups.status: none` e procedi col flow standard. Il decision tree di Step 3 (UI Design)
|
|
@@ -74,11 +74,18 @@ Scenarios: pending
|
|
|
74
74
|
|
|
75
75
|
## UI Design
|
|
76
76
|
|
|
77
|
-
mockups.status: pending # none | requested | provided | partial
|
|
78
|
-
mockups.format: pending # chat-images | local-paths | mixed
|
|
79
|
-
mockups.original_paths: [] # user-provided paths
|
|
77
|
+
mockups.status: pending # none | requested | provided | partial | pending_external
|
|
78
|
+
mockups.format: pending # chat-images | local-paths | local-archive | mixed
|
|
79
|
+
mockups.original_paths: [] # user-provided paths, chat://image-N, or archive://<rel-path>
|
|
80
80
|
mockups.canonical_paths: [] # mockups/<file> after copy
|
|
81
81
|
|
|
82
|
+
mockups.archive: # populated only when format includes local-archive
|
|
83
|
+
local_zip_path: pending # abs path of the .zip the user gave us
|
|
84
|
+
kind: pending # zip
|
|
85
|
+
extracted_dir: pending # abs path of _archive/extracted/
|
|
86
|
+
truncated: false # true when candidate list capped at 200
|
|
87
|
+
candidates: [] # see discovery-phase.md § 1.6.4b step b-c
|
|
88
|
+
|
|
82
89
|
mockup_analysis.screens: [] # see discovery-phase.md § Mockup analysis schema
|
|
83
90
|
mockup_analysis.user_flow: []
|
|
84
91
|
mockup_analysis.design_system_alignment:
|
|
@@ -172,9 +172,12 @@ Append this follow-up to the SAME message:
|
|
|
172
172
|
Perfetto. In che forma me li passi?
|
|
173
173
|
|
|
174
174
|
- **Immagini in chat** — incollale direttamente nel prossimo messaggio.
|
|
175
|
-
- **Path locali** — incolla i percorsi (assoluti o relativi al repo)
|
|
176
|
-
in `${paths.prd_dir}/<slug>/mockups/`.
|
|
177
|
-
- **
|
|
175
|
+
- **Path locali** — incolla i percorsi (assoluti o relativi al repo). Funzionano:
|
|
176
|
+
- file singoli (PNG, HTML, SVG, …) → li copio in `${paths.prd_dir}/<slug>/mockups/`.
|
|
177
|
+
- **archivi `.zip`** (es. export "Download as .zip" da Claude Design già
|
|
178
|
+
scaricato sul tuo disco) → lo unzippo io, analizzo TUTTI i mockup dentro
|
|
179
|
+
e seleziono automaticamente quelli rilevanti per questa feature.
|
|
180
|
+
- **Misti** — combinazioni delle modalità sopra.
|
|
178
181
|
```
|
|
179
182
|
|
|
180
183
|
- Update state file `## UI Design`: `mockups.status: requested`, `mockups.format: pending`.
|
|
@@ -184,19 +187,170 @@ Perfetto. In che forma me li passi?
|
|
|
184
187
|
|
|
185
188
|
When the user replies with the mockups:
|
|
186
189
|
|
|
187
|
-
1. **Detect format** and update `mockups.format` ∈ {`chat-images`, `local-paths`, `mixed`}.
|
|
190
|
+
1. **Detect format** and update `mockups.format` ∈ {`chat-images`, `local-paths`, `local-archive`, `mixed`}.
|
|
191
|
+
- `local-archive` applies when at least one of the provided local paths is a
|
|
192
|
+
`.zip` (case-insensitive) — also if mixed with other regular files.
|
|
188
193
|
2. **For each local path provided:**
|
|
189
194
|
- Resolve to absolute path. If file does not exist: ask the user to confirm/correct
|
|
190
195
|
(do not silently skip).
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
|
|
196
|
+
- **If the path is a `.zip`** (extension match OR `file <path>` reports a Zip
|
|
197
|
+
archive): route it to Step 1.6.4b and DO NOT copy the zip itself into
|
|
198
|
+
`${paths.prd_dir}/<slug>/mockups/`. Only the user-confirmed subset extracted
|
|
199
|
+
from it ends up there.
|
|
200
|
+
- **Otherwise** (regular mockup file): ensure `${paths.prd_dir}/<slug>/mockups/`
|
|
201
|
+
exists (create if missing), then copy the file into that directory,
|
|
202
|
+
preserving filename. On collision (file with same name already there):
|
|
203
|
+
append numeric suffix (`<name>-2.png`).
|
|
194
204
|
- Record both paths in state: `mockups.original_paths[]` and `mockups.canonical_paths[]`.
|
|
195
205
|
3. **For chat images:** record in state `mockups.original_paths[]` as `chat://image-N`
|
|
196
206
|
(the images remain in the conversation context window).
|
|
197
|
-
4.
|
|
207
|
+
4. **For zip archives:** execute Step 1.6.4b BEFORE marking `status: provided`. The
|
|
208
|
+
archive flow has its own scan + selection + confirmation gate; only the
|
|
209
|
+
user-confirmed subset is copied into `${paths.prd_dir}/<slug>/mockups/`.
|
|
210
|
+
5. Update `mockups.status: provided` (or `partial` only if the user explicitly says
|
|
198
211
|
"ho solo questi 2 ma servono anche altri").
|
|
199
212
|
|
|
213
|
+
### 1.6.4b — Archive ingestion & relevance selection (when `mockups.format` includes `local-archive`)
|
|
214
|
+
|
|
215
|
+
Triggered when the user hands a local `.zip` path (typically a Claude Design
|
|
216
|
+
"Download as .zip" export already on disk). The flow scans every mockup inside,
|
|
217
|
+
scores each against the feature scope from Kickoff, and asks the user to confirm
|
|
218
|
+
the auto-selected subset before analysis.
|
|
219
|
+
|
|
220
|
+
#### Step a — Detect & unpack
|
|
221
|
+
|
|
222
|
+
For each zip path provided:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
file "<user-zip-path>"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
- If `file` does NOT report a Zip archive, treat the path as a regular file and
|
|
229
|
+
go back to step 1.6.4 point 2's "Otherwise" branch — no special handling.
|
|
230
|
+
- If it IS a zip, record in state:
|
|
231
|
+
- `mockups.archive.local_zip_path: <user-zip-path>` (absolute)
|
|
232
|
+
- `mockups.archive.kind: zip`
|
|
233
|
+
- Unpack into a scratch directory under the PRD's mockup folder:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
mkdir -p "$WORKTREE_PATH/${paths.prd_dir}/<slug>/mockups/_archive"
|
|
237
|
+
unzip -q "<user-zip-path>" \
|
|
238
|
+
-d "$WORKTREE_PATH/${paths.prd_dir}/<slug>/mockups/_archive/extracted"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
- Record `mockups.archive.extracted_dir`.
|
|
242
|
+
- If `unzip` fails (corrupted/encrypted): STOP, surface the exit code, ask the
|
|
243
|
+
user to verify the zip or provide an alternative.
|
|
244
|
+
|
|
245
|
+
#### Step b — Enumerate candidates
|
|
246
|
+
|
|
247
|
+
Scan the extracted tree for mockup-shaped files. The candidate filter is:
|
|
248
|
+
|
|
249
|
+
- Extensions: `.html`, `.htm`, `.png`, `.jpg`, `.jpeg`, `.svg`, `.webp`, `.gif`, `.pdf`.
|
|
250
|
+
- Exclude: `node_modules/`, `.git/`, anything under a directory named `assets/`
|
|
251
|
+
whose parent is itself excluded, `*.min.*`, `thumbs.db`, `.DS_Store`.
|
|
252
|
+
- Size sanity: skip files > 50 MB (likely video/binary blobs, never a mockup).
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
find "$WORKTREE_PATH/${paths.prd_dir}/<slug>/mockups/_archive/extracted" \
|
|
256
|
+
-type f \
|
|
257
|
+
\( -iname '*.html' -o -iname '*.htm' -o -iname '*.png' -o -iname '*.jpg' \
|
|
258
|
+
-o -iname '*.jpeg' -o -iname '*.svg' -o -iname '*.webp' -o -iname '*.gif' \
|
|
259
|
+
-o -iname '*.pdf' \) \
|
|
260
|
+
-size -50M \
|
|
261
|
+
-not -path '*/node_modules/*' -not -path '*/.git/*' \
|
|
262
|
+
-not -name '*.min.*' -not -name 'thumbs.db' -not -name '.DS_Store'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
For each candidate, build a lightweight index entry:
|
|
266
|
+
- `path` (relative to `extracted/`)
|
|
267
|
+
- `filename`
|
|
268
|
+
- `ext`
|
|
269
|
+
- `size_kb`
|
|
270
|
+
- For HTML: `<title>` content + first `<h1>` (use `grep -oE` or a single Read of
|
|
271
|
+
the first ~200 lines; do NOT load the full file — they can be massive).
|
|
272
|
+
- For images: nothing extra at this stage (filename is the only cheap signal).
|
|
273
|
+
|
|
274
|
+
Cap the indexed list at 200 entries. If the archive contains more, sort by
|
|
275
|
+
`size_kb DESC` (larger files are typically the rendered screens) and keep the
|
|
276
|
+
top 200, recording `mockups.archive.truncated: true`.
|
|
277
|
+
|
|
278
|
+
Record the full index in state under `mockups.archive.candidates[]`.
|
|
279
|
+
|
|
280
|
+
#### Step c — Score against feature scope
|
|
281
|
+
|
|
282
|
+
Build the scope vector from the Kickoff state (Step 1):
|
|
283
|
+
- `feature_title` (from `## Feature Description`).
|
|
284
|
+
- `slug`.
|
|
285
|
+
- ISA touchpoints (if Discovery dimension 9 already ran).
|
|
286
|
+
- Verbatim screen names the user mentioned in the initial description.
|
|
287
|
+
- Keywords from `feature_objective_one_sentence` (strip stopwords).
|
|
288
|
+
|
|
289
|
+
For each candidate, compute a relevance score 0-100:
|
|
290
|
+
- `+40` if any scope keyword appears in the filename (case-insensitive,
|
|
291
|
+
whole-word; for kebab/snake/camelCase, split before matching).
|
|
292
|
+
- `+30` if any scope keyword appears in the HTML `<title>` or `<h1>`.
|
|
293
|
+
- `+15` if the file path contains a directory name matching a scope keyword.
|
|
294
|
+
- `+10` if the filename matches typical screen patterns (`screen`, `page`,
|
|
295
|
+
`view`, `flow`, the user's domain entity names).
|
|
296
|
+
- `-20` if the filename matches typical non-screen patterns (`icon`, `logo`,
|
|
297
|
+
`favicon`, `thumbnail`, `og-image`, `sitemap`, `manifest`).
|
|
298
|
+
|
|
299
|
+
Selection threshold: keep candidates with `score ≥ 30` as the auto-selected set.
|
|
300
|
+
If fewer than 3 candidates clear the threshold, lower to `≥ 20` and surface the
|
|
301
|
+
fact. If zero candidates clear `≥ 20`, surface "selezione non automatizzabile —
|
|
302
|
+
ti chiedo di indicarmi a mano quali sono rilevanti" and present the full
|
|
303
|
+
candidate list.
|
|
304
|
+
|
|
305
|
+
Record per-candidate: `score`, `matched_keywords[]`, `selected: bool`.
|
|
306
|
+
|
|
307
|
+
#### Step d — Confirmation gate (STOP)
|
|
308
|
+
|
|
309
|
+
Present a compact table to the user — selected candidates first, then up to 10
|
|
310
|
+
discarded with the highest scores, then a footer count for "altri N scartati":
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
Bundle scaricato e analizzato: <N> file candidati, <K> selezionati come rilevanti.
|
|
314
|
+
|
|
315
|
+
**Selezionati** (score ≥ 30 vs. feature scope):
|
|
316
|
+
| # | File | Score | Match |
|
|
317
|
+
|---|-------------------------------|-------|------------------------|
|
|
318
|
+
| 1 | screens/lista-fornitori.html | 75 | "fornitori", "lista" |
|
|
319
|
+
| 2 | screens/dettaglio-ordine.html | 55 | "ordine" |
|
|
320
|
+
…
|
|
321
|
+
|
|
322
|
+
**Scartati ad alto score** (per trasparenza):
|
|
323
|
+
| # | File | Score | Motivo |
|
|
324
|
+
|---|-------------------------------|-------|------------------------|
|
|
325
|
+
| 1 | screens/landing-marketing.html| 22 | nessun keyword match |
|
|
326
|
+
…
|
|
327
|
+
|
|
328
|
+
Altri <M> file scartati (score < 20 o pattern non-schermata).
|
|
329
|
+
|
|
330
|
+
Procedo all'analisi visiva dei <K> selezionati? Oppure indicami modifiche
|
|
331
|
+
(es. "aggiungi il #3 degli scartati", "togli il #2 dei selezionati").
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**STOP.** Wait for explicit confirmation or an adjustment list. On adjustment,
|
|
335
|
+
recompute `mockups.archive.candidates[].selected`, then re-present and STOP again
|
|
336
|
+
until the user confirms.
|
|
337
|
+
|
|
338
|
+
#### Step e — Materialize the confirmed subset
|
|
339
|
+
|
|
340
|
+
Copy ONLY the confirmed selection into `${paths.prd_dir}/<slug>/mockups/`,
|
|
341
|
+
preserving relative directory structure under the extracted root so that
|
|
342
|
+
relative asset references (CSS, images) keep working. On filename collision,
|
|
343
|
+
use the `<name>-2.<ext>` rule from 1.6.4 point 2.
|
|
344
|
+
|
|
345
|
+
Record `mockups.original_paths[]` as `archive://<relative-path-in-zip>` and
|
|
346
|
+
`mockups.canonical_paths[]` as the new path under `mockups/`. The scratch
|
|
347
|
+
`_archive/extracted/` directory is kept for the duration of the PRD session
|
|
348
|
+
(may be needed to resolve `<link>` / `<img src>` references during analysis)
|
|
349
|
+
and cleaned up at Step 7 (Commit & Merge) — add a `.gitignore` entry for
|
|
350
|
+
`mockups/_archive/` if not already present.
|
|
351
|
+
|
|
352
|
+
Then continue to Step 1.6.5 with the selected subset.
|
|
353
|
+
|
|
200
354
|
### 1.6.5 — Mockup analysis (MANDATORY before Discovery)
|
|
201
355
|
|
|
202
356
|
Analyze ALL provided mockups (visual analysis for chat images, Read for copied files
|
|
@@ -561,11 +715,26 @@ structure. Be specific — vague analysis defeats the purpose of skipping Step 3
|
|
|
561
715
|
```yaml
|
|
562
716
|
mockups:
|
|
563
717
|
status: provided | partial | none | requested
|
|
564
|
-
format: chat-images | local-paths | mixed
|
|
718
|
+
format: chat-images | local-paths | local-archive | mixed
|
|
565
719
|
original_paths:
|
|
566
|
-
- <user-provided path
|
|
720
|
+
- <user-provided path, chat://image-N, or archive://<rel-path-in-zip>>
|
|
567
721
|
canonical_paths:
|
|
568
|
-
- mockups/<file>.png # only for local-paths
|
|
722
|
+
- mockups/<file>.png # only for local-paths and local-archive
|
|
723
|
+
archive: # only when format includes local-archive
|
|
724
|
+
local_zip_path: <abs path to the user-provided .zip>
|
|
725
|
+
kind: zip
|
|
726
|
+
extracted_dir: <abs path to _archive/extracted/>
|
|
727
|
+
truncated: false # true when candidate list capped at 200
|
|
728
|
+
candidates: # full enumerated list (post-filter)
|
|
729
|
+
- path: <rel path under extracted/>
|
|
730
|
+
filename: <basename>
|
|
731
|
+
ext: html | png | jpg | svg | …
|
|
732
|
+
size_kb: <int>
|
|
733
|
+
html_title: <optional, HTML only>
|
|
734
|
+
html_h1: <optional, HTML only>
|
|
735
|
+
score: <0-100>
|
|
736
|
+
matched_keywords: [<keyword>, …]
|
|
737
|
+
selected: <bool> # true = part of the confirmed subset
|
|
569
738
|
mockup_analysis:
|
|
570
739
|
screens:
|
|
571
740
|
- name: <inferred name, e.g. "Lista ordini">
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# MCP Integration — Guida BALDART per i consumer
|
|
2
|
+
|
|
3
|
+
Questo documento spiega **quando** un agent/skill BALDART deve appoggiarsi a un Model Context Protocol (MCP) server, **quali** MCP sono raccomandati per i casi d'uso più comuni, e **come** dichiarare la dipendenza MCP nel body dell'agent in modo che il consumer sappia subito cosa configurare.
|
|
4
|
+
|
|
5
|
+
> **Scope di questa release**: convenzione testuale, **zero nuove chiavi config** in `baldart.config.yml`. Le chiavi `mcp.*` (es. `mcp.required: []` / `mcp.optional: []`) entreranno solo se e quando una skill concreta dovrà gatearne il comportamento, in una release dedicata con propagazione end-to-end completa (regola di [schema-change propagation](../docs/PROJECT-CONFIGURATION.md)).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Quando usare un MCP
|
|
10
|
+
|
|
11
|
+
Tre opzioni per integrare un sistema esterno in un agent BALDART. Scegli il più semplice che risolve il problema:
|
|
12
|
+
|
|
13
|
+
| Opzione | Quando ha senso | Costi/limiti |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| **MCP server** | Il sistema è **bidirezionale**, ha molte operazioni discrete (search, get, mutate), serve a **molti agent diversi**, o richiede **stato di sessione** (browser, DB). | Setup nel consumer (configurazione MCP), dipendenza esplicita, esposizione dei dati al modello. |
|
|
16
|
+
| **Script CLI / Bash** | È un'azione **one-shot** o **idempotente** (build, test, git, lint, deploy), output testuale ben definito, niente stato di sessione. | Niente — è la baseline. Preferibile quando funziona. |
|
|
17
|
+
| **API call diretta (fetch/curl)** | Serve **un'unica chiamata** verso un endpoint REST/GraphQL pubblico o autenticato via env var, **non serve a più agent**. | Risposta opaca al framework (non recuperabile per altri agent), parsing manuale, niente cache strutturata. |
|
|
18
|
+
|
|
19
|
+
**Regola pratica**: se la stessa integrazione tornerà utile a **2+ agent o skill**, è un MCP. Se è un'esecuzione una-tantum da una singola skill, è uno script CLI o un fetch.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. Catalogo MCP raccomandati per i casi d'uso comuni
|
|
24
|
+
|
|
25
|
+
Non è un'imposizione: BALDART non installa MCP, non li valida, non li richiede. È una lista curata di MCP che hanno senso nei deployment dove BALDART è già in uso.
|
|
26
|
+
|
|
27
|
+
### Browser automation
|
|
28
|
+
- **Playwright MCP** (`@modelcontextprotocol/server-playwright`) — usato da [bug](../.claude/skills/bug/SKILL.md) e [webapp-testing](../.claude/skills/webapp-testing/SKILL.md) per cattura visiva, network, console.
|
|
29
|
+
|
|
30
|
+
### Documentation retrieval (RAG)
|
|
31
|
+
- **doc-rag MCP** (interno o `@modelcontextprotocol/server-everything-search` come stand-in) — usato da [codebase-architect](../.claude/agents/codebase-architect.md) e [code-search-protocol.md](../agents/code-search-protocol.md) per ricerca semantica nei doc + knowledge graph.
|
|
32
|
+
|
|
33
|
+
### Database
|
|
34
|
+
- **Firebase MCP** (`@modelcontextprotocol/server-firebase` — già integrato come plugin BALDART quando `stack.database.primary` è Firestore) — ispezione documenti, query collection, transazioni.
|
|
35
|
+
- **Postgres MCP** (`@modelcontextprotocol/server-postgres`) — per stack SQL.
|
|
36
|
+
|
|
37
|
+
### Issue tracker / project management
|
|
38
|
+
- **GitHub MCP** (`@modelcontextprotocol/server-github`) o **`gh` CLI** — issue triage, PR review, gist creation. Per BALDART consigliamo `gh` (è una CLI già universale), MCP solo se servono molte mutazioni in pipeline.
|
|
39
|
+
- **Linear MCP**, **Jira MCP** — disponibili nella registry ufficiale Anthropic per chi usa quei ticketing system.
|
|
40
|
+
|
|
41
|
+
### Design tool
|
|
42
|
+
- **Figma MCP** — usato da agent di design / UI per estrarre token, screenshot, asset.
|
|
43
|
+
|
|
44
|
+
### Observability
|
|
45
|
+
- **Sentry MCP** — già disponibile in BALDART come [sentry plugin](../../CLAUDE.md). Per analisi error → root cause.
|
|
46
|
+
|
|
47
|
+
### Communication
|
|
48
|
+
- **Slack MCP**, **Gmail MCP** — disponibili nel marketplace MCP. Usali solo se l'agent deve davvero comunicare verso umani (es. post-mortem auto-pubblicato).
|
|
49
|
+
|
|
50
|
+
**Anti-pattern**: NON installare MCP "perché esistono". Ogni MCP aggiunge tool al system prompt del modello, consuma context, e crea dipendenze infrastrutturali nel consumer. Il pattern BALDART è "tanti agent specializzati, pochi MCP universalmente utili".
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 3. La convenzione `## MCP dependencies` (per author di agent/skill BALDART)
|
|
55
|
+
|
|
56
|
+
Ogni agent o skill BALDART che usa MCP deve dichiararlo esplicitamente nel body, in una sezione dedicata. Questo permette:
|
|
57
|
+
- al **consumer** di sapere cosa configurare (e cosa succede se non lo configura);
|
|
58
|
+
- al `baldart doctor` futuro di leggere queste sezioni e verificare gli MCP `required`;
|
|
59
|
+
- ad altri agent di sapere se invocare questo agent è "free" o richiede setup.
|
|
60
|
+
|
|
61
|
+
### Struttura
|
|
62
|
+
|
|
63
|
+
Subito dopo la sezione `## Project Context` (o, in mancanza, subito dopo il frontmatter e l'intro):
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
## MCP dependencies
|
|
67
|
+
|
|
68
|
+
**Required** (skill/agent rifiuta o degrada visibilmente senza questi MCP):
|
|
69
|
+
- `mcp__<server>__<tool>` — cosa serve, perché.
|
|
70
|
+
|
|
71
|
+
**Optional** (l'agent ne approfitta se disponibile, ma ha un fallback):
|
|
72
|
+
- `mcp__<server>__<tool>` — cosa offre in più, qual è il fallback.
|
|
73
|
+
|
|
74
|
+
**None** (per skill senza MCP — utile dichiararlo esplicitamente):
|
|
75
|
+
- This skill uses no MCP servers. <breve nota se rilevante>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Regole
|
|
79
|
+
|
|
80
|
+
1. **Sii specifico**: cita il prefisso del tool (`mcp__playwright__browser_navigate`), non il "concetto" (`Playwright MCP`). Aiuta il consumer a fare grep.
|
|
81
|
+
2. **Required vs Optional**: required = la skill non può completare il proprio task senza il MCP (o degrada gravemente). Optional = la skill ha un fallback funzionante.
|
|
82
|
+
3. **Fallback espliciti**: per ogni `Optional`, descrivi il fallback in una frase ("se MCP unavailable, usa `rg` su `docs/` per trovare pattern noti").
|
|
83
|
+
4. **Niente nuovo schema in `baldart.config.yml`**: non aggiungere `mcp.required` o `mcp.optional` nel config — è solo convenzione testuale finché non c'è una skill che ha bisogno di gatearne il comportamento a runtime.
|
|
84
|
+
5. **Aggiorna la dichiarazione quando la dipendenza cambia**: se rimuovi un MCP dall'agent, rimuovi la riga; se aggiungi un fallback Grep e l'MCP diventa optional, sposta la riga.
|
|
85
|
+
|
|
86
|
+
### Esempi nel framework corrente
|
|
87
|
+
|
|
88
|
+
Vedi le seguenti dichiarazioni per pattern di riferimento:
|
|
89
|
+
- [framework/.claude/agents/codebase-architect.md](../.claude/agents/codebase-architect.md) — `## MCP dependencies` con doc-rag required + LSP-related optional.
|
|
90
|
+
- [framework/.claude/skills/bug/SKILL.md](../.claude/skills/bug/SKILL.md) — Playwright required per UI bug, doc-rag + Firestore optional.
|
|
91
|
+
- [framework/.claude/skills/playwright-skill/SKILL.md](../.claude/skills/playwright-skill/SKILL.md) — esempio di sezione "None" (la skill usa Playwright Test CLI, non MCP).
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. FAQ per il consumer
|
|
96
|
+
|
|
97
|
+
**D: BALDART installa gli MCP per me?**
|
|
98
|
+
R: No. BALDART distribuisce agent e skill che eventualmente li **usano**. L'installazione e configurazione MCP è responsabilità del consumer (di solito via `.mcp.json` o `.claude/settings.json`). Vedi la [documentazione Claude Code](https://docs.claude.com) per il setup MCP.
|
|
99
|
+
|
|
100
|
+
**D: Cosa succede se invoco un agent che richiede un MCP non configurato?**
|
|
101
|
+
R: Dipende da come l'agent è stato scritto. Gli agent BALDART che seguono il pattern raccomandato fanno **graceful degrade** (riportano il missing MCP e provano un fallback documentato). Quelli che dichiarano un MCP come **Required** dovrebbero rifiutare visibilmente di proseguire — ma oggi BALDART non enforza questa policy in modo automatico. Il `baldart doctor` futuro potrà controllarla.
|
|
102
|
+
|
|
103
|
+
**D: Posso aggiungere un MCP custom non nella lista del § 2?**
|
|
104
|
+
R: Sì, e se diventa utile a più agent valuta una PR upstream a BALDART per aggiungerlo al catalogo. Vedi [MAINTAINING.md](../../MAINTAINING.md) per il workflow di contribuzione.
|
|
105
|
+
|
|
106
|
+
**D: La mia organizzazione ha un sistema interno (ticketing, docs, monitoring) — devo per forza esporlo via MCP?**
|
|
107
|
+
R: Non per forza. Se l'integrazione serve a **uno** script una tantum, una semplice fetch è meglio. Se serve a 2+ agent BALDART o se vuoi che gli agent possano "scoprire" dati senza che tu glieli passi manualmente, allora vale la pena un MCP custom.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 5. Cosa cambia per BALDART nelle prossime release
|
|
112
|
+
|
|
113
|
+
Roadmap (vedi piano [gap-analysis vs. large codebases](../../.claude/plans/voglio-che-studi-questo-fluttering-nova.md)):
|
|
114
|
+
|
|
115
|
+
- **Adesso** (questa release): convenzione testuale `## MCP dependencies`, doc + 3 agent/skill aggiornati come reference.
|
|
116
|
+
- **Prossima release MINOR** (se serve): introduzione di una skill che richiede gating runtime su MCP → in quella release sarà propagata la chiave `mcp.required/optional` end-to-end (template + configure + doctor + CHANGELOG), seguendo la regola di schema-change propagation.
|
|
117
|
+
- **Routine `mcp-check`** (opzionale, T-level): controllo settimanale che ogni MCP `Required` dichiarato nel framework abbia un endpoint sano nel consumer.
|
|
118
|
+
|
|
119
|
+
Finché la chiave config non esiste, la convenzione testuale **è** il contratto.
|
package/package.json
CHANGED
package/src/commands/add.js
CHANGED
|
@@ -7,6 +7,13 @@ const Hooks = require('../utils/hooks');
|
|
|
7
7
|
async function add(repo, options) {
|
|
8
8
|
const git = new GitUtils();
|
|
9
9
|
const symlinks = new SymlinkUtils();
|
|
10
|
+
// Non-interactive flag honored on non-destructive prompts only. The
|
|
11
|
+
// "Remove and reinstall?" prompt (line 40) stays interactive even with
|
|
12
|
+
// --yes — that path requires explicit user intent, not flag inheritance.
|
|
13
|
+
// Callers that have already established intent (e.g. `update --reset`)
|
|
14
|
+
// rm -rf `.framework/` themselves, so `git.frameworkExists()` is false
|
|
15
|
+
// here and the destructive prompt is never reached.
|
|
16
|
+
const nonInteractive = options && options.yes === true;
|
|
10
17
|
|
|
11
18
|
try {
|
|
12
19
|
// Step 1: Verify environment
|
|
@@ -70,7 +77,9 @@ async function add(repo, options) {
|
|
|
70
77
|
'Templates copied for customization'
|
|
71
78
|
]);
|
|
72
79
|
|
|
73
|
-
const proceed =
|
|
80
|
+
const proceed = nonInteractive
|
|
81
|
+
? true
|
|
82
|
+
: await UI.confirm('Install framework?', true);
|
|
74
83
|
if (!proceed) {
|
|
75
84
|
UI.info('Installation cancelled');
|
|
76
85
|
process.exit(0);
|
|
@@ -157,13 +166,39 @@ async function add(repo, options) {
|
|
|
157
166
|
// Configure Git aliases
|
|
158
167
|
UI.section('Configuring Git Aliases');
|
|
159
168
|
|
|
160
|
-
const configureAliases =
|
|
169
|
+
const configureAliases = nonInteractive
|
|
170
|
+
? true
|
|
171
|
+
: await UI.confirm('Configure git aliases (fw-version, fw-update, fw-push)?', true);
|
|
161
172
|
|
|
162
173
|
if (configureAliases) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
174
|
+
// simple-git >=3.21 rejects shell-command aliases (prefix `!`) unless
|
|
175
|
+
// `allowUnsafeAlias` is set in its constructor — and even that is
|
|
176
|
+
// version-gated. Spawning `git config` directly bypasses the safety
|
|
177
|
+
// check (which is a simple-git policy, not a git policy: the user is
|
|
178
|
+
// explicitly opting in to these aliases here). Any failure here is
|
|
179
|
+
// cosmetic (the framework is fully installed without aliases), so we
|
|
180
|
+
// warn and continue instead of bubbling up to the global catch — that
|
|
181
|
+
// surfaced as "✗ Installation failed: Configuring alias is not
|
|
182
|
+
// permitted without enabling allowUnsafeAlias" while the install was
|
|
183
|
+
// actually fine.
|
|
184
|
+
const { spawnSync } = require('child_process');
|
|
185
|
+
const aliases = [
|
|
186
|
+
['alias.fw-version', '!cat .framework/VERSION'],
|
|
187
|
+
['alias.fw-update', '!npx baldart update'],
|
|
188
|
+
['alias.fw-push', '!npx baldart push'],
|
|
189
|
+
];
|
|
190
|
+
let aliasFailures = 0;
|
|
191
|
+
for (const [key, value] of aliases) {
|
|
192
|
+
const r = spawnSync('git', ['config', key, value], { stdio: 'pipe' });
|
|
193
|
+
if (r.status !== 0) {
|
|
194
|
+
aliasFailures += 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (aliasFailures === 0) {
|
|
198
|
+
UI.success('Git aliases configured');
|
|
199
|
+
} else {
|
|
200
|
+
UI.warning(`${aliasFailures}/${aliases.length} git alias(es) could not be configured (non-blocking — install continues).`);
|
|
201
|
+
}
|
|
167
202
|
}
|
|
168
203
|
|
|
169
204
|
// BALDART hooks (multi-hook registry since v3.18.0)
|
|
@@ -201,10 +236,12 @@ async function add(repo, options) {
|
|
|
201
236
|
// Skills now resolve project-specific facts from baldart.config.yml
|
|
202
237
|
// instead of hard-coding paths. Configure prompts for these on install.
|
|
203
238
|
UI.newline();
|
|
204
|
-
const runConfigure =
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
239
|
+
const runConfigure = nonInteractive
|
|
240
|
+
? true
|
|
241
|
+
: await UI.confirm(
|
|
242
|
+
'Configure project context now (paths, identity, stack, feature flags)?',
|
|
243
|
+
true
|
|
244
|
+
);
|
|
208
245
|
if (runConfigure) {
|
|
209
246
|
try {
|
|
210
247
|
const configureCmd = require('./configure');
|
|
@@ -226,9 +263,13 @@ async function add(repo, options) {
|
|
|
226
263
|
' • Rename to lint-before-commit.sh',
|
|
227
264
|
' • Make executable: chmod +x .claude/hooks/lint-before-commit.sh',
|
|
228
265
|
'',
|
|
229
|
-
'2.
|
|
230
|
-
' •
|
|
231
|
-
'
|
|
266
|
+
'2. Two editable templates landed at docs/references/ (untracked):',
|
|
267
|
+
' • ui-guidelines.template.md — UI design language template.',
|
|
268
|
+
' Edit and rename to ui-guidelines.md if you adopt it.',
|
|
269
|
+
' • brand-guidelines.md — Brand voice & visual identity.',
|
|
270
|
+
' Edit to taste, or delete if your project does not need one.',
|
|
271
|
+
' These are starting points. Commit them to track your project\'s',
|
|
272
|
+
' design language, or add them to .gitignore if you don\'t need them.',
|
|
232
273
|
'',
|
|
233
274
|
'3. Create backlog cards:',
|
|
234
275
|
' • Copy templates/feature-card.template.yml',
|
package/src/commands/update.js
CHANGED
|
@@ -234,7 +234,12 @@ async function runReset(git, options, autoYes) {
|
|
|
234
234
|
UI.newline();
|
|
235
235
|
UI.info('Re-installing framework via `baldart add`…');
|
|
236
236
|
const addCmd = require('./add');
|
|
237
|
-
|
|
237
|
+
// `add(repo, options)` — first arg is the repo URL (undefined → use default
|
|
238
|
+
// from package.json). Pre-v3.28.1 we incorrectly passed `{ yes: true }` as
|
|
239
|
+
// the first arg, so `options` was undefined and every interactive prompt
|
|
240
|
+
// ("Install framework?", "Configure git aliases?", …) fired despite the
|
|
241
|
+
// parent `update --reset --yes --i-know` having already established intent.
|
|
242
|
+
await addCmd(undefined, { yes: true });
|
|
238
243
|
|
|
239
244
|
// Post-restore sanity check — confirm nothing user-owned got clobbered.
|
|
240
245
|
const stillPresent = {
|