@the-bearded-bear/claude-craft 8.23.0 → 8.23.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/Dev/i18n/base/Common/templates/AGENTS.md.template +92 -0
- package/Dev/i18n/de/Common/templates/settings.json.template +2 -11
- package/Dev/i18n/de/Workflow/commands/auto-sprint.md +1 -1
- package/Dev/i18n/de/Workflow/commands/start.md +40 -1
- package/Dev/i18n/en/Common/templates/settings.json.template +2 -11
- package/Dev/i18n/en/Workflow/commands/auto-sprint.md +1 -1
- package/Dev/i18n/en/Workflow/commands/start.md +40 -1
- package/Dev/i18n/es/Common/templates/settings.json.template +2 -11
- package/Dev/i18n/es/Workflow/commands/auto-sprint.md +1 -1
- package/Dev/i18n/es/Workflow/commands/start.md +40 -1
- package/Dev/i18n/fr/Common/templates/settings.json.template +2 -11
- package/Dev/i18n/fr/Workflow/commands/auto-sprint.md +1 -1
- package/Dev/i18n/fr/Workflow/commands/start.md +40 -1
- package/Dev/i18n/pt/Common/templates/settings.json.template +2 -11
- package/Dev/i18n/pt/Workflow/commands/auto-sprint.md +1 -1
- package/Dev/i18n/pt/Workflow/commands/start.md +40 -1
- package/Dev/scripts/check-config.sh +59 -65
- package/Dev/scripts/install-common-rules.sh +47 -3
- package/Dev/scripts/install-from-config.sh +12 -1
- package/Dev/scripts/lib/install-tech-common.sh +6 -1
- package/Dev/scripts/lib/stack-profiles.sh +74 -0
- package/Dev/stack-profiles/README.md +15 -0
- package/Dev/stack-profiles/angular/permissions.txt +5 -0
- package/Dev/stack-profiles/angular/quality.md +3 -0
- package/Dev/stack-profiles/angular/stack.txt +2 -0
- package/Dev/stack-profiles/ansible/permissions.txt +2 -0
- package/Dev/stack-profiles/ansible/quality.md +2 -0
- package/Dev/stack-profiles/ansible/stack.txt +2 -0
- package/Dev/stack-profiles/coolify/stack.txt +2 -0
- package/Dev/stack-profiles/csharp/permissions.txt +1 -0
- package/Dev/stack-profiles/csharp/quality.md +3 -0
- package/Dev/stack-profiles/csharp/stack.txt +2 -0
- package/Dev/stack-profiles/docker/permissions.txt +1 -0
- package/Dev/stack-profiles/docker/quality.md +2 -0
- package/Dev/stack-profiles/docker/stack.txt +2 -0
- package/Dev/stack-profiles/flutter/permissions.txt +2 -0
- package/Dev/stack-profiles/flutter/quality.md +3 -0
- package/Dev/stack-profiles/flutter/stack.txt +2 -0
- package/Dev/stack-profiles/frankenphp/stack.txt +2 -0
- package/Dev/stack-profiles/hcloud/stack.txt +2 -0
- package/Dev/stack-profiles/kubernetes/permissions.txt +3 -0
- package/Dev/stack-profiles/kubernetes/quality.md +2 -0
- package/Dev/stack-profiles/kubernetes/stack.txt +2 -0
- package/Dev/stack-profiles/laravel/permissions.txt +2 -0
- package/Dev/stack-profiles/laravel/quality.md +3 -0
- package/Dev/stack-profiles/laravel/stack.txt +2 -0
- package/Dev/stack-profiles/opentofu/permissions.txt +3 -0
- package/Dev/stack-profiles/opentofu/quality.md +3 -0
- package/Dev/stack-profiles/opentofu/stack.txt +2 -0
- package/Dev/stack-profiles/paperclip/permissions.txt +4 -0
- package/Dev/stack-profiles/paperclip/quality.md +2 -0
- package/Dev/stack-profiles/paperclip/stack.txt +2 -0
- package/Dev/stack-profiles/pgbouncer/stack.txt +2 -0
- package/Dev/stack-profiles/php/permissions.txt +1 -0
- package/Dev/stack-profiles/php/quality.md +3 -0
- package/Dev/stack-profiles/php/stack.txt +2 -0
- package/Dev/stack-profiles/python/permissions.txt +4 -0
- package/Dev/stack-profiles/python/quality.md +3 -0
- package/Dev/stack-profiles/python/stack.txt +2 -0
- package/Dev/stack-profiles/react/permissions.txt +4 -0
- package/Dev/stack-profiles/react/quality.md +3 -0
- package/Dev/stack-profiles/react/stack.txt +2 -0
- package/Dev/stack-profiles/reactnative/permissions.txt +5 -0
- package/Dev/stack-profiles/reactnative/quality.md +3 -0
- package/Dev/stack-profiles/reactnative/stack.txt +2 -0
- package/Dev/stack-profiles/symfony/permissions.txt +2 -0
- package/Dev/stack-profiles/symfony/quality.md +4 -0
- package/Dev/stack-profiles/symfony/stack.txt +2 -0
- package/Dev/stack-profiles/vercel/permissions.txt +5 -0
- package/Dev/stack-profiles/vercel/quality.md +2 -0
- package/Dev/stack-profiles/vercel/stack.txt +2 -0
- package/Dev/stack-profiles/vite/permissions.txt +4 -0
- package/Dev/stack-profiles/vite/quality.md +2 -0
- package/Dev/stack-profiles/vite/stack.txt +2 -0
- package/Dev/stack-profiles/vuejs/permissions.txt +4 -0
- package/Dev/stack-profiles/vuejs/quality.md +3 -0
- package/Dev/stack-profiles/vuejs/stack.txt +2 -0
- package/Project/i18n/de/Gate/commands/validate-sprint.md +14 -5
- package/Project/i18n/de/agents/tech-lead.md +62 -67
- package/Project/i18n/de/scaffold/CLAUDE.md +5 -25
- package/Project/i18n/en/Gate/commands/validate-sprint.md +14 -5
- package/Project/i18n/en/agents/tech-lead.md +60 -65
- package/Project/i18n/en/scaffold/CLAUDE.md +5 -25
- package/Project/i18n/es/Gate/commands/validate-sprint.md +14 -5
- package/Project/i18n/es/agents/tech-lead.md +60 -65
- package/Project/i18n/es/scaffold/CLAUDE.md +5 -25
- package/Project/i18n/fr/Gate/commands/validate-sprint.md +14 -5
- package/Project/i18n/fr/agents/tech-lead.md +60 -65
- package/Project/i18n/fr/scaffold/CLAUDE.md +5 -25
- package/Project/i18n/pt/Gate/commands/validate-sprint.md +14 -5
- package/Project/i18n/pt/agents/tech-lead.md +60 -65
- package/Project/i18n/pt/scaffold/CLAUDE.md +5 -25
- package/Project/install-project-commands.sh +45 -10
- package/README.md +8 -0
- package/bundles/cursor/.cursorrules +1 -1
- package/bundles/windsurf/.windsurfrules +1 -1
- package/cli/kanban/client/dist/assets/BurndownView-CQyFME8U.js +3 -0
- package/cli/kanban/client/dist/assets/{DepsView-A7Xe41FE.js → DepsView-DEAS0a20.js} +1 -1
- package/cli/kanban/client/dist/assets/{DocsView-DFXULSIu.js → DocsView-BsXYPJAu.js} +1 -1
- package/cli/kanban/client/dist/assets/{SprintsView-DZ3KdjDw.js → SprintsView-Bo2p1NbV.js} +1 -1
- package/cli/kanban/client/dist/assets/cytoscape-dagre-8BvEs68F.js +2 -0
- package/cli/kanban/client/dist/assets/cytoscape.esm-BiK1LiYw.js +321 -0
- package/cli/kanban/client/dist/assets/index-CI2O6JO9.js +4 -0
- package/cli/kanban/client/dist/assets/{marked.esm-BFjXurK6.js → marked.esm-CYIZq5lG.js} +4 -4
- package/cli/kanban/client/dist/assets/purify.es-ChwZkWde.js +3 -0
- package/cli/kanban/client/dist/index.html +1 -1
- package/cli/kanban/server/app.js +6 -3
- package/cli/kanban/server/services/frontmatter.js +10 -4
- package/cli/kanban/server/services/markdown-metadata.js +150 -0
- package/cli/kanban/server/services/repository.js +29 -7
- package/cli/lib/installer.js +9 -2
- package/package.json +9 -9
- package/cli/kanban/client/dist/assets/BurndownView-BrheHgEo.js +0 -10
- package/cli/kanban/client/dist/assets/cytoscape-dagre-YDByNmIW.js +0 -2
- package/cli/kanban/client/dist/assets/cytoscape.esm-Dd3Wh3PR.js +0 -321
- package/cli/kanban/client/dist/assets/index-TQv7sDCT.js +0 -4
- package/cli/kanban/client/dist/assets/purify.es-DuRL7t6i.js +0 -3
|
@@ -235,91 +235,80 @@ check_common_installation() {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
238
|
-
#
|
|
239
|
-
# Format: tech_name:cmd_namespace:min_rules:min_commands:min_templates:min_checklists
|
|
238
|
+
# Techs connues (namespace de commandes = clé de la techno)
|
|
240
239
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
240
|
+
DEV_TECHS=" symfony flutter react reactnative angular csharp laravel vuejs php python vite vercel paperclip "
|
|
241
|
+
INFRA_TECHS=" docker coolify kubernetes opentofu ansible hcloud pgbouncer frankenphp "
|
|
242
|
+
|
|
243
|
+
# Vérifie la présence d'agents d'un préfixe donné (agents infra : <tech>-*.md)
|
|
244
|
+
check_agents_prefix() {
|
|
245
|
+
local dir="$1" prefix="$2" count
|
|
246
|
+
count=$(find "$dir" -maxdepth 1 -name "${prefix}-*.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
247
|
+
if [[ $count -lt 1 ]]; then
|
|
248
|
+
log_error "agents ${prefix}-*: non trouvé"
|
|
249
|
+
return 1
|
|
250
|
+
fi
|
|
251
|
+
log_ok "agents ${prefix}-*: $count fichiers"
|
|
252
|
+
}
|
|
253
253
|
|
|
254
254
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
255
|
-
#
|
|
255
|
+
# Vérifie l'installation d'une techno dans un module
|
|
256
256
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
257
257
|
check_tech_installation() {
|
|
258
258
|
local path="$1"
|
|
259
259
|
local tech="$2"
|
|
260
260
|
local issues=0
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
262
|
+
if [[ "$DEV_TECHS" == *" $tech "* ]]; then
|
|
263
|
+
check_dir_count "$path/.claude/commands/$tech" "commands/$tech" 1 || ((issues++)) || true
|
|
264
|
+
# Layout actuel : references/<tech> ; installations anciennes : rules/
|
|
265
|
+
if [[ -d "$path/.claude/references/$tech" ]]; then
|
|
266
|
+
check_dir_count "$path/.claude/references/$tech" "references/$tech" 1 || ((issues++)) || true
|
|
267
|
+
else
|
|
268
|
+
check_dir_count "$path/.claude/rules" "rules" 1 || ((issues++)) || true
|
|
269
269
|
fi
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
270
|
+
check_file_exists "$path/.claude/CLAUDE.md" "CLAUDE.md" || ((issues++)) || true
|
|
271
|
+
check_dir_count "$path/.claude/agents" "agents" 1 || ((issues++)) || true
|
|
272
|
+
elif [[ "$INFRA_TECHS" == *" $tech "* ]]; then
|
|
273
|
+
check_dir_count "$path/.claude/commands/$tech" "commands/$tech" 1 || ((issues++)) || true
|
|
274
|
+
check_agents_prefix "$path/.claude/agents" "$tech" || ((issues++)) || true
|
|
275
|
+
elif [[ "$tech" == "project" ]]; then
|
|
276
|
+
local ns
|
|
277
|
+
for ns in project sprint gate; do
|
|
278
|
+
check_dir_count "$path/.claude/commands/$ns" "commands/$ns" 1 || ((issues++)) || true
|
|
279
|
+
done
|
|
280
|
+
check_file_exists "$path/.claude/agents/tech-lead.md" "agents/tech-lead" || ((issues++)) || true
|
|
281
|
+
check_file_exists "$path/.claude/agents/product-owner.md" "agents/product-owner" || ((issues++)) || true
|
|
282
|
+
else
|
|
273
283
|
log_warn "Technologie inconnue: $tech"
|
|
274
284
|
return 1
|
|
275
285
|
fi
|
|
276
286
|
|
|
277
|
-
# Parse registry entry
|
|
278
|
-
IFS=':' read -r _ cmd_ns min_rules min_cmds min_templates min_checklists <<< "$entry"
|
|
279
|
-
|
|
280
|
-
if [[ ! -d "$path/.claude" ]]; then
|
|
281
|
-
log_error ".claude/: non trouvé"
|
|
282
|
-
return 1
|
|
283
|
-
fi
|
|
284
|
-
|
|
285
|
-
# Rules (generic + tech-specific)
|
|
286
|
-
check_dir_count "$path/.claude/rules" "rules" "$min_rules" || ((issues++)) || true
|
|
287
|
-
|
|
288
|
-
# Commands (tech namespace)
|
|
289
|
-
check_dir_count "$path/.claude/commands/${cmd_ns}" "commands/${cmd_ns}" "$min_cmds" || ((issues++)) || true
|
|
290
|
-
|
|
291
|
-
# Templates
|
|
292
|
-
check_dir_count "$path/.claude/templates" "templates" "$min_templates" || ((issues++)) || true
|
|
293
|
-
|
|
294
|
-
# Checklists
|
|
295
|
-
check_dir_count "$path/.claude/checklists" "checklists" "$min_checklists" || ((issues++)) || true
|
|
296
|
-
|
|
297
|
-
# CLAUDE.md
|
|
298
|
-
check_file_exists "$path/.claude/CLAUDE.md" "CLAUDE.md" || ((issues++)) || true
|
|
299
|
-
|
|
300
|
-
# Agents
|
|
301
|
-
check_dir_count "$path/.claude/agents" "agents" 1 || ((issues++)) || true
|
|
302
|
-
|
|
303
|
-
# Optional directories
|
|
304
|
-
check_dir_optional "$path/.claude/adr" "adr"
|
|
305
|
-
check_dir_optional "$path/.claude/examples" "examples"
|
|
306
|
-
|
|
307
287
|
return $issues
|
|
308
288
|
}
|
|
309
289
|
|
|
310
290
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
311
|
-
# Dispatcher - vérifie un module
|
|
291
|
+
# Dispatcher - vérifie un module pour chacune de ses technologies
|
|
292
|
+
# Args: $1=path, $2=label, $3..=techs
|
|
312
293
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
313
294
|
check_module() {
|
|
314
295
|
local path="$1"
|
|
315
|
-
local
|
|
316
|
-
|
|
317
|
-
local issues=0
|
|
296
|
+
local label="$2"
|
|
297
|
+
shift 2
|
|
298
|
+
local issues=0 tech tech_issues
|
|
318
299
|
|
|
319
300
|
echo -e " ${BOLD}$label:${NC}"
|
|
320
301
|
|
|
321
|
-
|
|
322
|
-
|
|
302
|
+
if [[ ! -d "$path/.claude" ]]; then
|
|
303
|
+
log_error ".claude/: non trouvé"
|
|
304
|
+
return 1
|
|
305
|
+
fi
|
|
306
|
+
|
|
307
|
+
for tech in "$@"; do
|
|
308
|
+
tech_issues=0
|
|
309
|
+
check_tech_installation "$path" "$tech" || tech_issues=$?
|
|
310
|
+
issues=$((issues + tech_issues))
|
|
311
|
+
done
|
|
323
312
|
|
|
324
313
|
return $issues
|
|
325
314
|
}
|
|
@@ -365,9 +354,11 @@ check_project() {
|
|
|
365
354
|
|
|
366
355
|
# Vérifier chaque module
|
|
367
356
|
for ((j=0; j<module_count; j++)); do
|
|
368
|
-
local path tech
|
|
357
|
+
local path tech techs
|
|
369
358
|
path=$(yq e ".projects[$project_index].modules[$j].path" "$config_file")
|
|
370
|
-
tech
|
|
359
|
+
# tech : string ou tableau YAML
|
|
360
|
+
mapfile -t techs < <(yq e ".projects[$project_index].modules[$j].tech | [.] | flatten | .[]" "$config_file")
|
|
361
|
+
tech=$(IFS=,; echo "${techs[*]}")
|
|
371
362
|
|
|
372
363
|
local target_path
|
|
373
364
|
if [[ "$path" == "." ]]; then
|
|
@@ -394,7 +385,7 @@ check_project() {
|
|
|
394
385
|
fi
|
|
395
386
|
|
|
396
387
|
local module_issues=0
|
|
397
|
-
check_module "$target_path" "$
|
|
388
|
+
check_module "$target_path" "$module_label" "${techs[@]}" || module_issues=$?
|
|
398
389
|
if [[ $module_issues -gt 0 ]]; then
|
|
399
390
|
issues_list+=("$name:$tech:$target_path")
|
|
400
391
|
((total_issues += module_issues)) || true
|
|
@@ -540,4 +531,7 @@ main() {
|
|
|
540
531
|
exit 0
|
|
541
532
|
}
|
|
542
533
|
|
|
543
|
-
|
|
534
|
+
# Exécuté directement (pas quand le script est sourcé, ex. par les tests)
|
|
535
|
+
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
536
|
+
main "$@"
|
|
537
|
+
fi
|
|
@@ -46,6 +46,7 @@ VERSION=$(get_claude_craft_version)
|
|
|
46
46
|
# Shared UI (colors + logging)
|
|
47
47
|
# shellcheck source=lib/shell-ui.sh
|
|
48
48
|
source "${SCRIPT_DIR}/lib/shell-ui.sh"
|
|
49
|
+
source "${SCRIPT_DIR}/lib/stack-profiles.sh"
|
|
49
50
|
|
|
50
51
|
# Default options
|
|
51
52
|
action="install"
|
|
@@ -61,6 +62,7 @@ templates_only=false
|
|
|
61
62
|
checklists_only=false
|
|
62
63
|
target_dir=""
|
|
63
64
|
lang="en"
|
|
65
|
+
tech_arg=""
|
|
64
66
|
|
|
65
67
|
#-------------------------------------------------------------------------------
|
|
66
68
|
# Load i18n messages
|
|
@@ -165,6 +167,7 @@ ${MSG_HELP_OPTIONS}
|
|
|
165
167
|
--backup ${MSG_HELP_BACKUP}
|
|
166
168
|
--interactive ${MSG_HELP_INTERACTIVE}
|
|
167
169
|
--lang=XX ${MSG_HELP_LANG}
|
|
170
|
+
--tech=a,b Project stack: scopes AGENTS.md reviewers and settings.json permissions
|
|
168
171
|
--agents-only Install agents only
|
|
169
172
|
--commands-only Install commands only
|
|
170
173
|
--templates-only Install templates only
|
|
@@ -218,6 +221,10 @@ parse_args() {
|
|
|
218
221
|
lang="${1#--lang=}"
|
|
219
222
|
shift
|
|
220
223
|
;;
|
|
224
|
+
--tech=*)
|
|
225
|
+
tech_arg="${1#--tech=}"
|
|
226
|
+
shift
|
|
227
|
+
;;
|
|
221
228
|
--agents-only)
|
|
222
229
|
agents_only=true
|
|
223
230
|
shift
|
|
@@ -558,6 +565,43 @@ install_checklists() {
|
|
|
558
565
|
fi
|
|
559
566
|
}
|
|
560
567
|
|
|
568
|
+
# Selected stack (--tech) or, without it, every profiled stack
|
|
569
|
+
selected_techs() {
|
|
570
|
+
if [[ -n "$tech_arg" ]]; then
|
|
571
|
+
parse_tech_list "$tech_arg"
|
|
572
|
+
else
|
|
573
|
+
all_profile_techs
|
|
574
|
+
fi
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
# Replace the __STACK_PERMISSIONS__ marker line with the stacks' permission rules
|
|
578
|
+
render_settings_json() {
|
|
579
|
+
local techs line
|
|
580
|
+
IFS=' ' read -ra techs <<< "$(selected_techs)"
|
|
581
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
582
|
+
if [[ "$line" == *'"__STACK_PERMISSIONS__"'* ]]; then
|
|
583
|
+
if [[ ${#techs[@]} -gt 0 ]]; then render_permission_lines "${techs[@]}"; fi
|
|
584
|
+
else
|
|
585
|
+
printf '%s\n' "$line"
|
|
586
|
+
fi
|
|
587
|
+
done < "$1"
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
# With --tech, drop the "- `@<tech>-reviewer`" lines of stacks not selected
|
|
591
|
+
render_agents_md() {
|
|
592
|
+
if [[ -z "$tech_arg" ]]; then
|
|
593
|
+
cat "$1"
|
|
594
|
+
return
|
|
595
|
+
fi
|
|
596
|
+
awk -v keep=" $(parse_tech_list "$tech_arg") " '
|
|
597
|
+
match($0, /^- `@[a-z]+-reviewer`/) {
|
|
598
|
+
tech = substr($0, 5, RLENGTH - 14)
|
|
599
|
+
if (index(keep, " " tech " ") == 0) next
|
|
600
|
+
}
|
|
601
|
+
{ print }
|
|
602
|
+
' "$1"
|
|
603
|
+
}
|
|
604
|
+
|
|
561
605
|
install_config() {
|
|
562
606
|
log_info "${MSG_INSTALLING_CONFIG:-Installing configuration files...}"
|
|
563
607
|
|
|
@@ -587,7 +631,7 @@ install_config() {
|
|
|
587
631
|
log_dry_run "${MSG_CREATING:-Creating} .claude/settings.json"
|
|
588
632
|
else
|
|
589
633
|
mkdir -p "$(dirname "$settings_dest")"
|
|
590
|
-
|
|
634
|
+
render_settings_json "$settings_src" > "$settings_dest"
|
|
591
635
|
log_success "${MSG_CREATING:-Creating} .claude/settings.json"
|
|
592
636
|
fi
|
|
593
637
|
((++files_created))
|
|
@@ -873,13 +917,13 @@ main() {
|
|
|
873
917
|
|
|
874
918
|
# Copy AGENTS.md template to target root (idempotent — won't overwrite existing)
|
|
875
919
|
local agents_template
|
|
876
|
-
agents_template="$
|
|
920
|
+
agents_template="$I18N_DIR/base/Common/templates/AGENTS.md.template"
|
|
877
921
|
local agents_target="$target_dir/AGENTS.md"
|
|
878
922
|
if [[ -f "$agents_template" && ! -f "$agents_target" ]]; then
|
|
879
923
|
if $dry_run; then
|
|
880
924
|
log_dry_run "Would create $agents_target from AGENTS.md.template"
|
|
881
925
|
else
|
|
882
|
-
|
|
926
|
+
render_agents_md "$agents_template" > "$agents_target"
|
|
883
927
|
log_success "[install-common-rules] Created $agents_target from template"
|
|
884
928
|
((++files_created))
|
|
885
929
|
fi
|
|
@@ -46,6 +46,7 @@ list_only=false
|
|
|
46
46
|
force_mode=false
|
|
47
47
|
preserve_config=false
|
|
48
48
|
backup_mode=false
|
|
49
|
+
project_techs=""
|
|
49
50
|
default_lang="en"
|
|
50
51
|
|
|
51
52
|
# Compteurs
|
|
@@ -502,7 +503,8 @@ install_module() {
|
|
|
502
503
|
fi
|
|
503
504
|
|
|
504
505
|
# Construire les options selon les capacités de chaque script
|
|
505
|
-
# - "project" : --lang, --
|
|
506
|
+
# - "project" : --lang, --force, --tech
|
|
507
|
+
# - "common" : options standard + --tech (stack du projet pour AGENTS.md / settings.json)
|
|
506
508
|
# - infra (docker, coolify, kubernetes, opentofu, ansible, hcloud, pgbouncer, frankenphp) :
|
|
507
509
|
# --install, --force, --backup, --lang (pas --preserve-config ni --skip-common)
|
|
508
510
|
# - autres : --install, --force, --preserve-config, --backup, --lang, --skip-common
|
|
@@ -523,9 +525,15 @@ install_module() {
|
|
|
523
525
|
if [[ "$backup_mode" == "true" ]]; then
|
|
524
526
|
opts+=("--backup")
|
|
525
527
|
fi
|
|
528
|
+
elif [[ "$force_mode" == "true" ]]; then
|
|
529
|
+
opts=("--force")
|
|
526
530
|
fi
|
|
527
531
|
# Ajouter la langue
|
|
528
532
|
opts+=("--lang=$lang")
|
|
533
|
+
# Stack du projet (tous modules) : common et project tournent avant les modules
|
|
534
|
+
if [[ ( "$tech" == "common" || "$tech" == "project" ) && -n "$project_techs" ]]; then
|
|
535
|
+
opts+=("--tech=$project_techs")
|
|
536
|
+
fi
|
|
529
537
|
# Skip common si multi-tech (2ème+ technologie) - pas supporté par project et infra
|
|
530
538
|
if [[ -n "$skip_common" && "$tech" != "project" && "$is_infra" == "false" ]]; then
|
|
531
539
|
opts+=("$skip_common")
|
|
@@ -611,6 +619,9 @@ install_project() {
|
|
|
611
619
|
total_steps=$((total_steps + 1))
|
|
612
620
|
fi
|
|
613
621
|
|
|
622
|
+
# Stack complète du projet, transmise à common et project (rendu CLAUDE.md, AGENTS.md, settings.json)
|
|
623
|
+
project_techs=$(yq e ".projects[$project_index].modules[].tech | [.] | flatten | .[]" "$config_file" | paste -sd, -)
|
|
624
|
+
|
|
614
625
|
# Installer les règles communes si demandé
|
|
615
626
|
if [[ "$common" == "true" ]]; then
|
|
616
627
|
print_section "[$step/$total_steps] Installation des règles communes"
|
|
@@ -525,7 +525,12 @@ main() {
|
|
|
525
525
|
|
|
526
526
|
load_messages
|
|
527
527
|
|
|
528
|
-
|
|
528
|
+
# Never fall back to $(pwd) for a missing target: it would install into the caller's cwd
|
|
529
|
+
if [[ ! -d "$target_dir" ]]; then
|
|
530
|
+
log_error "Directory does not exist: $target_dir"
|
|
531
|
+
exit 1
|
|
532
|
+
fi
|
|
533
|
+
target_dir="$(cd "${target_dir}" && pwd)"
|
|
529
534
|
|
|
530
535
|
echo ""
|
|
531
536
|
echo "Installing Claude Code rules - ${TECH_DISPLAY_NAME} (TCL)"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
# Stack profiles — render stack-aware snippets from Dev/stack-profiles/<tech>/.
|
|
4
|
+
# Pure bash (no yq/jq): sourced by install-common-rules.sh and install-project-commands.sh.
|
|
5
|
+
|
|
6
|
+
STACK_PROFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../stack-profiles" && pwd)"
|
|
7
|
+
|
|
8
|
+
# "project, python,react,python" -> "python react" (deduped, order kept, unknown techs dropped)
|
|
9
|
+
parse_tech_list() {
|
|
10
|
+
local IFS=$', \t\n' tech result=" "
|
|
11
|
+
for tech in $1; do
|
|
12
|
+
[[ "$tech" == "project" || "$tech" == "common" ]] && continue
|
|
13
|
+
[[ "$result" == *" $tech "* ]] && continue
|
|
14
|
+
if [[ ! -f "$STACK_PROFILES_DIR/$tech/stack.txt" ]]; then
|
|
15
|
+
echo "Warning: no stack profile for '$tech' (skipped)" >&2
|
|
16
|
+
continue
|
|
17
|
+
fi
|
|
18
|
+
result+="$tech "
|
|
19
|
+
done
|
|
20
|
+
result="${result# }"
|
|
21
|
+
echo "${result% }"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
all_profile_techs() {
|
|
25
|
+
local dir
|
|
26
|
+
for dir in "$STACK_PROFILES_DIR"/*/; do
|
|
27
|
+
[[ -f "$dir/stack.txt" ]] && basename "$dir"
|
|
28
|
+
done | tr '\n' ' '
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_profile_line() { sed -n "${2}p" "$STACK_PROFILES_DIR/$1/stack.txt"; }
|
|
32
|
+
|
|
33
|
+
# $1 = separator, rest = techs -> "Python, React"
|
|
34
|
+
stack_display_names() {
|
|
35
|
+
local sep="$1" out="" tech
|
|
36
|
+
shift
|
|
37
|
+
for tech in "$@"; do
|
|
38
|
+
out+="${out:+$sep}$(_profile_line "$tech" 1)"
|
|
39
|
+
done
|
|
40
|
+
echo "$out"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# "python: FastAPI, ..." per tech (body of the CLAUDE.md yaml block)
|
|
44
|
+
render_stack_block() {
|
|
45
|
+
local tech
|
|
46
|
+
for tech in "$@"; do
|
|
47
|
+
echo "$tech: $(_profile_line "$tech" 2)"
|
|
48
|
+
done
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# "### Python" + quality bullets per tech having a quality.md
|
|
52
|
+
render_quality_block() {
|
|
53
|
+
local tech first=true
|
|
54
|
+
for tech in "$@"; do
|
|
55
|
+
[[ -f "$STACK_PROFILES_DIR/$tech/quality.md" ]] || continue
|
|
56
|
+
$first || echo ""
|
|
57
|
+
first=false
|
|
58
|
+
echo "### $(_profile_line "$tech" 1)"
|
|
59
|
+
cat "$STACK_PROFILES_DIR/$tech/quality.md"
|
|
60
|
+
done
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# JSON array entries (' "Bash(x)",') for the settings.json allow list, deduped
|
|
64
|
+
render_permission_lines() {
|
|
65
|
+
local tech rule seen=$'\n'
|
|
66
|
+
for tech in "$@"; do
|
|
67
|
+
[[ -f "$STACK_PROFILES_DIR/$tech/permissions.txt" ]] || continue
|
|
68
|
+
while IFS= read -r rule; do
|
|
69
|
+
[[ -z "$rule" || "$seen" == *$'\n'"$rule"$'\n'* ]] && continue
|
|
70
|
+
seen+="$rule"$'\n'
|
|
71
|
+
echo " \"$rule\","
|
|
72
|
+
done < "$STACK_PROFILES_DIR/$tech/permissions.txt"
|
|
73
|
+
done
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Stack profiles
|
|
2
|
+
|
|
3
|
+
Language-agnostic per-technology data used by the installers to render
|
|
4
|
+
stack-aware root files (`CLAUDE.md`, `AGENTS.md`, `.claude/settings.json`)
|
|
5
|
+
from the `--tech=a,b,c` list. Read by `Dev/scripts/lib/stack-profiles.sh`.
|
|
6
|
+
|
|
7
|
+
One directory per tech key (same keys as `cli/lib/tech-registry.js` plus infra techs):
|
|
8
|
+
|
|
9
|
+
| File | Required | Format |
|
|
10
|
+
|------|----------|--------|
|
|
11
|
+
| `stack.txt` | yes | Line 1: display name. Line 2: main components (comma-separated) |
|
|
12
|
+
| `quality.md` | no | Markdown bullets, tool names only (no prose — shared by all languages) |
|
|
13
|
+
| `permissions.txt` | no | One Claude Code permission rule per line, e.g. `Bash(pytest:*)` |
|
|
14
|
+
|
|
15
|
+
Adding a tech: create its directory here; `tests/content/stack-profiles.test.mjs` checks every registry tech has one.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Bash(dotnet:*)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Bash(hadolint:*)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Bash(composer:*)
|