diff --git a/.claude/hooks/audit-log.sh b/.claude/hooks/audit-log.sh new file mode 100755 index 00000000000..a484d9d50d9 --- /dev/null +++ b/.claude/hooks/audit-log.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# audit-log.sh — Post-execution hook +# +# Logs every tool invocation to .claude/audit.log. +# This hook never blocks execution (always exits 0). +# +# IMPORTANT: Do not modify, disable, or bypass this hook. + +set -uo pipefail + +# --------------------------------------------------------------------------- +# 1. Read hook input from stdin +# --------------------------------------------------------------------------- +INPUT="$(cat)" + +TOOL_NAME="$(printf '%s' "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name','unknown'))" 2>/dev/null || echo "unknown")" + +COMMAND="$(printf '%s' "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))" 2>/dev/null || echo "")" + +# --------------------------------------------------------------------------- +# 2. Determine log file path (relative to project root) +# --------------------------------------------------------------------------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOG_FILE="$(dirname "$SCRIPT_DIR")/audit.log" + +# --------------------------------------------------------------------------- +# 3. Write log entry +# --------------------------------------------------------------------------- +TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + +if [[ -n "$COMMAND" ]]; then + printf '[%s] tool=%s command=%s\n' "$TIMESTAMP" "$TOOL_NAME" "$COMMAND" >> "$LOG_FILE" 2>/dev/null || true +else + printf '[%s] tool=%s\n' "$TIMESTAMP" "$TOOL_NAME" >> "$LOG_FILE" 2>/dev/null || true +fi + +# Never block execution +exit 0 diff --git a/.claude/hooks/validate-bash-command.sh b/.claude/hooks/validate-bash-command.sh new file mode 100755 index 00000000000..254ea134e25 --- /dev/null +++ b/.claude/hooks/validate-bash-command.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash +# validate-bash-command.sh — Pre-execution hook (Layer 3 guardrail) +# +# Claude Code invokes this hook before every Bash tool call. +# Input: JSON on stdin {"tool_name":"Bash","tool_input":{"command":"..."}} +# Output: exit 0 to allow, exit 2 with JSON {"error":"..."} to block. +# +# IMPORTANT: Do not modify, disable, or bypass this hook. + +set -euo pipefail + +# --------------------------------------------------------------------------- +# 1. Read hook input from stdin and extract the command +# --------------------------------------------------------------------------- +INPUT="$(cat)" + +TOOL_NAME="$(printf '%s' "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null || true)" + +# Only validate Bash commands — allow everything else through +if [[ "$TOOL_NAME" != "Bash" ]]; then + exit 0 +fi + +COMMAND="$(printf '%s' "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))" 2>/dev/null || true)" + +if [[ -z "$COMMAND" ]]; then + exit 0 +fi + +# --------------------------------------------------------------------------- +# 2. Blocked patterns — glob-style matching +# Each pattern is checked against the full command string (case-insensitive). +# --------------------------------------------------------------------------- +BLOCKED_PATTERNS=( + # AWS — Destructive operations + "aws * delete*" + "aws * remove*" + "aws * destroy*" + "aws * terminate*" + "aws * deregister*" + "aws * purge*" + "aws s3 rm *" + "aws s3 rb *" + "aws cloudformation delete-stack*" + + # AWS — Provisioning & scaling + "aws ec2 run-instances*" + "aws ec2 stop-instances*" + "aws autoscaling set-desired-capacity*" + "aws autoscaling update-auto-scaling-group*" + "aws application-autoscaling *" + "aws ecs update-service*" + + # AWS — IAM + "aws iam delete*" + "aws iam create*" + "aws iam put*" + "aws iam attach*" + + # Kubernetes — Mutations + "kubectl delete *" + "kubectl apply *" + "kubectl create *" + "kubectl patch *" + "kubectl scale *" + "kubectl rollout *" + "kubectl drain *" + "kubectl cordon *" + "kubectl exec *" + "kubectl edit *" + + # Terraform / IaC + "terraform destroy*" + "terraform apply*" + "terraform import *" + "terraform state rm *" + "terraform taint *" + + # Helm + "helm install *" + "helm upgrade *" + "helm delete *" + "helm uninstall *" + "helm rollback *" + + # Git — Destructive + "git push --force*" + "git push -f *" + "git push --force-with-lease*" + "git push origin main*" + "git push origin master*" + "git reset --hard*" + "git clean -f*" + + # File system — Destructive + "rm -rf /" + "rm -rf /*" + "rm -rf ~" + "rm -rf ~/*" + "rm -rf ..*" + "mkfs.*" + "dd if=*/dev/*" + + # Credential access via cat/less/head/tail + "cat */.aws/*" + "cat */.kube/*" + "cat */.ssh/*" + "cat *.env" + "cat *.env.*" + "cat */secrets/*" + "cat *credentials*" + "less */.aws/*" + "less */.ssh/*" + "head */.aws/*" + "head */.ssh/*" + "tail */.aws/*" + "tail */.ssh/*" + + # Network & remote access + "ssh *" + "scp *" + "curl *|*sh" + "curl *|*bash" + "wget *|*sh" + "wget *|*bash" + + # Privilege escalation + "sudo *" + "sudo" + "chmod 777 *" + "chown root *" +) + +# --------------------------------------------------------------------------- +# 3. Check function — matches a single sub-command against all patterns +# --------------------------------------------------------------------------- +check_command() { + local cmd="$1" + # Trim leading/trailing whitespace + cmd="$(echo "$cmd" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" + + if [[ -z "$cmd" ]]; then + return 0 + fi + + # Convert to lowercase for case-insensitive matching + local cmd_lower + cmd_lower="$(echo "$cmd" | tr '[:upper:]' '[:lower:]')" + + for pattern in "${BLOCKED_PATTERNS[@]}"; do + local pattern_lower + pattern_lower="$(echo "$pattern" | tr '[:upper:]' '[:lower:]')" + + # shellcheck disable=SC2254 + if [[ "$cmd_lower" == $pattern_lower ]]; then + printf '{"error":"BLOCKED by guardrail hook: command matches blocked pattern: %s"}\n' "$pattern" >&2 + exit 2 + fi + done + + return 0 +} + +# --------------------------------------------------------------------------- +# 4. Split on pipes and command chains, then check each sub-command +# --------------------------------------------------------------------------- +# Replace common chain operators with a delimiter +NORMALIZED="$(echo "$COMMAND" | sed 's/&&/\n/g; s/||/\n/g; s/;/\n/g; s/|/\n/g')" + +while IFS= read -r subcmd; do + check_command "$subcmd" +done <<< "$NORMALIZED" + +# If we reach here, the command is allowed +exit 0 diff --git a/.claude/rules/aws.md b/.claude/rules/aws.md new file mode 100644 index 00000000000..2b1c197ac3d --- /dev/null +++ b/.claude/rules/aws.md @@ -0,0 +1,51 @@ +# AWS Rules + +## Environment Context + +- We use **AWS Bedrock** for AI model invocation +- Sandbox accounts are accessed via **Mendix SSO** +- **Production accounts exist on the same machine** — DO NOT use them +- If a command references an AWS profile or region you don't recognize, STOP and ask + +## Credential Safety + +- NEVER read files in `~/.aws/` (credentials, config, SSO cache) +- NEVER output or display AWS access keys, secret keys, or session tokens +- NEVER set or export `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, or `AWS_SESSION_TOKEN` in commands +- If you need to verify identity, use `aws sts get-caller-identity` — this is safe and read-only + +## Allowed Operations (Read-Only) + +These AWS CLI commands are safe and auto-approved: + +- `aws * describe*` — describe any resource +- `aws * list*` — list any resources +- `aws * get*` — get resource details +- `aws s3 ls` — list S3 buckets and objects +- `aws sts get-caller-identity` — verify current identity + +## Blocked Operations + +### Destructive (deny — never allowed) +- `aws * delete*`, `aws * remove*`, `aws * destroy*`, `aws * terminate*` +- `aws * deregister*`, `aws * purge*` +- `aws s3 rm`, `aws s3 rb` +- `aws cloudformation delete-stack` + +### Provisioning & Scaling (deny — never allowed) +- `aws ec2 run-instances`, `aws ec2 stop-instances` +- `aws autoscaling set-desired-capacity`, `aws autoscaling update-auto-scaling-group` +- `aws application-autoscaling *` +- `aws ecs update-service` + +### IAM (deny — never allowed) +- `aws iam create*`, `aws iam delete*`, `aws iam put*`, `aws iam attach*` + +## Verification Steps + +Before running any AWS command: + +1. **Check the profile** — is this a sandbox account? If unsure, run `aws sts get-caller-identity` first +2. **Check the region** — is this an expected region? If it looks unfamiliar, ask the user +3. **Check the action** — is this read-only? If it mutates state, do NOT run it +4. **When in doubt** — explain the command and let the human decide diff --git a/.claude/rules/security.md b/.claude/rules/security.md new file mode 100644 index 00000000000..81f58ce1948 --- /dev/null +++ b/.claude/rules/security.md @@ -0,0 +1,31 @@ +# Security Rules + +These rules are loaded automatically by Claude Code at session start. They are non-negotiable. + +## Safety Rules (NON-NEGOTIABLE) + +1. NEVER run commands that delete, destroy, or modify production resources +2. NEVER use AWS credentials for production accounts — only sandbox accounts +3. NEVER deploy code, infrastructure, or configuration changes — a human must do this +4. NEVER run `terraform apply`, `terraform destroy`, `kubectl apply`, `kubectl delete` against production +5. NEVER read or output secrets, API keys, tokens, or credentials from files or environment variables +6. NEVER run commands with `sudo` +7. NEVER run `rm -rf` on any path outside the current project directory +8. NEVER disable, bypass, or modify the guardrail hooks in `.claude/hooks/` +9. NEVER push to `main` or `master` branches directly + +## Core Principles + +- **The agent works FOR you** — it must never take irreversible actions without explicit human approval +- **Deny by default** — if a command is not explicitly allowed, it should require human confirmation +- **Credentials are off-limits** — never read, display, or transmit secrets, tokens, or credentials +- **Guardrails are mandatory** — the `.claude/hooks/` scripts must remain active and unmodified + +## When In Doubt + +If you are unsure whether a command is safe to run, **do not run it**. Instead: +1. Explain what command you would run and why +2. Describe the potential risks +3. Wait for the human to decide + +It is always better to ask than to act when safety is uncertain. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000000..b26bb12516e --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,187 @@ +{ + "env": { + "CLAUDE_CODE_ENABLE_TELEMETRY": "0", + "DISABLE_TELEMETRY": "1", + "OTEL_METRICS_EXPORTER": "otlp", + "AWS_PROFILE": "my-sandbox", + "AWS_REGION": "eu-central-1", + "CLAUDE_CODE_USE_BEDROCK": "1", + "ANTHROPIC_MODEL": "eu.anthropic.claude-sonnet-4-5-20250929-v1:0", + "ANTHROPIC_SMALL_FAST_MODEL": "eu.anthropic.claude-haiku-4-5-20251001-v1:0", + "ANTHROPIC_DEFAULT_HAIKU_MODEL": "eu.anthropic.claude-haiku-4-5-20251001-v1:0", + "ANTHROPIC_DEFAULT_OPUS_MODEL": "eu.anthropic.claude-opus-4-6-v1", + "ANTHROPIC_DEFAULT_SONNET_MODEL": "eu.anthropic.claude-sonnet-4-5-20250929-v1:0", + "DISABLE_PROMPT_CACHING": "0", + "CLAUDE_CODE_MAX_OUTPUT_TOKENS": "10240", + "MAX_THINKING_TOKENS": "1024" + }, + "deny": [ + "Bash(aws * delete*)", + "Bash(aws * remove*)", + "Bash(aws * destroy*)", + "Bash(aws * terminate*)", + "Bash(aws * deregister*)", + "Bash(aws * purge*)", + "Bash(aws s3 rm *)", + "Bash(aws s3 rb *)", + "Bash(aws cloudformation delete-stack *)", + "Bash(aws ec2 run-instances *)", + "Bash(aws ec2 stop-instances *)", + "Bash(aws autoscaling set-desired-capacity *)", + "Bash(aws autoscaling update-auto-scaling-group *)", + "Bash(aws application-autoscaling *)", + "Bash(aws ecs update-service *)", + "Bash(aws iam delete*)", + "Bash(aws iam create*)", + "Bash(aws iam put*)", + "Bash(aws iam attach*)", + "Bash(kubectl delete *)", + "Bash(kubectl apply *)", + "Bash(kubectl create *)", + "Bash(kubectl patch *)", + "Bash(kubectl scale *)", + "Bash(kubectl rollout *)", + "Bash(kubectl drain *)", + "Bash(kubectl cordon *)", + "Bash(kubectl exec *)", + "Bash(kubectl edit *)", + "Bash(terraform destroy *)", + "Bash(terraform destroy)", + "Bash(terraform apply *)", + "Bash(terraform apply)", + "Bash(terraform import *)", + "Bash(terraform state rm *)", + "Bash(terraform taint *)", + "Bash(helm install *)", + "Bash(helm upgrade *)", + "Bash(helm delete *)", + "Bash(helm uninstall *)", + "Bash(helm rollback *)", + "Bash(git push --force *)", + "Bash(git push -f *)", + "Bash(git push --force-with-lease *)", + "Bash(git push origin main *)", + "Bash(git push origin main)", + "Bash(git push origin master *)", + "Bash(git push origin master)", + "Bash(git reset --hard *)", + "Bash(git clean -f *)", + "Bash(pnpm publish-packages)", + "Bash(rm -rf /)", + "Bash(rm -rf /*)", + "Bash(rm -rf ~)", + "Bash(rm -rf ~/*)", + "Bash(rm -rf ..*)", + "Bash(mkfs.*)", + "Bash(dd if=*/dev/*)", + "Bash(sudo *)", + "Bash(sudo)", + "Bash(chmod 777 *)", + "Bash(chown root *)", + "Bash(ssh *)", + "Bash(scp *)", + "Bash(curl * | sh)", + "Bash(curl * | bash)", + "Bash(wget * | sh)", + "Bash(wget * | bash)", + "Read(~/.aws/**)", + "Read(~/.kube/**)", + "Read(~/.ssh/**)", + "Read(.env)", + "Read(.env.*)", + "Read(**/secrets/**)", + "Read(**/*credentials*)", + "mcp__datadog-mcp__create_datadog_notebook", + "mcp__datadog-mcp__edit_datadog_notebook", + "mcp__atlassian__jira_delete_issue", + "mcp__atlassian__jira_remove_issue_link", + "mcp__atlassian__confluence_delete_page", + "mcp__atlassian__confluence_delete_attachment" + ], + "allow": [ + "Bash(git log *)", + "Bash(git status *)", + "Bash(git status)", + "Bash(git diff *)", + "Bash(git diff)", + "Bash(git branch *)", + "Bash(git branch)", + "Bash(git show *)", + "Bash(git rev-parse *)", + "Bash(git remote -v)", + "Bash(ls *)", + "Bash(ls)", + "Bash(pwd)", + "Bash(which *)", + "Bash(npm test *)", + "Bash(npm test)", + "Bash(npm run test *)", + "Bash(npm run lint *)", + "Bash(npx jest *)", + "Bash(npx tsc *)", + "Bash(pnpm test:compile)", + "Bash(pnpm test:browser)", + "Bash(pnpm test)", + "Bash(pnpm build)", + "Bash(pnpm install)", + "Bash(pnpm install:*)", + "Bash(pnpm lint)", + "Bash(pnpm lint:fix)", + "Bash(pnpx tsc *)", + "Bash(go test *)", + "Bash(mvn test *)", + "Bash(gradle test *)", + "Bash(python -m pytest *)", + "Bash(python3 -m pytest *)", + "Bash(aws * describe* *)", + "Bash(aws * list* *)", + "Bash(aws * get* *)", + "Bash(aws s3 ls *)", + "Bash(aws sts get-caller-identity *)", + "Bash(aws sts get-caller-identity)", + "Bash(kubectl get *)", + "Bash(kubectl describe *)", + "Bash(kubectl logs *)", + "Bash(terraform plan *)", + "Bash(terraform plan)", + "Bash(terraform validate *)", + "Bash(terraform validate)", + "Bash(terraform fmt *)", + "Bash(terraform fmt)", + "Read(./**)", + "Edit(./**)", + "mcp__datadog-mcp__analyze_datadog_logs", + "mcp__datadog-mcp__get_datadog_incident", + "mcp__datadog-mcp__get_datadog_metric", + "mcp__datadog-mcp__get_datadog_metric_context", + "mcp__datadog-mcp__get_datadog_notebook", + "mcp__datadog-mcp__get_datadog_trace", + "mcp__datadog-mcp__search_datadog_dashboards", + "mcp__datadog-mcp__search_datadog_events", + "mcp__datadog-mcp__search_datadog_hosts", + "mcp__datadog-mcp__search_datadog_incidents", + "mcp__datadog-mcp__search_datadog_logs", + "mcp__datadog-mcp__search_datadog_metrics", + "mcp__datadog-mcp__search_datadog_monitors", + "mcp__datadog-mcp__search_datadog_notebooks", + "mcp__datadog-mcp__search_datadog_rum_events", + "mcp__datadog-mcp__search_datadog_service_dependencies", + "mcp__datadog-mcp__search_datadog_services", + "mcp__datadog-mcp__search_datadog_spans" + ], + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [{"type": "command", "command": ".claude/hooks/validate-bash-command.sh"}] + } + ], + "PostToolUse": [ + { + "matcher": "*", + "hooks": [{"type": "command", "command": ".claude/hooks/audit-log.sh"}] + } + ] + }, + "statusline": ".claude/statusline.sh" +} diff --git a/.claude/skills/add/SKILL.md b/.claude/skills/add/SKILL.md new file mode 100644 index 00000000000..7633d577068 --- /dev/null +++ b/.claude/skills/add/SKILL.md @@ -0,0 +1,12 @@ +--- +name: add +description: Adds new content to existing documentation pages while preserving the original structure and meaning. Integrates new sections, paragraphs, or information smoothly with appropriate transitions. Use when the user wants to add, insert, include, or append new content to existing pages without rewriting what's already there. +user-invocable: true +disable-model-invocation: true +--- + +> **After adding content:** Consider running `/polish` to improve clarity or `/proofread` to check for errors in the final result. + +Ask the user for the new content to add. Determine a suitable place to smoothly integrate the new content into the existing content, with appropriate transitions and formatting, while preserving the original meaning and structure of the page. Don't make changes to existing content unless necessary for clarity or coherence when adding the new content. + +If the new content introduces redundancy or conflicts with existing content, flag these issues in the chat and suggest ways to resolve them without directly editing the existing content. diff --git a/.claude/skills/enhance/SKILL.md b/.claude/skills/enhance/SKILL.md new file mode 100644 index 00000000000..acd2b06d63a --- /dev/null +++ b/.claude/skills/enhance/SKILL.md @@ -0,0 +1,10 @@ +--- +name: enhance +description: Performs comprehensive editing including reorganization, restructuring, and rephrasing while preserving original meaning and intent. Improves flow, strengthens weak phrasing, and enhances overall quality. Use when documentation needs significant structural improvements, better organization, or when the user mentions reorganize, restructure, rewrite, or enhance. +user-invocable: true +disable-model-invocation: true +--- + +> **Skill progression:** This is the most intensive editing. If restructuring isn't needed, use `/polish` for clarity improvements or `/proofread` for basic fixes. + +Perform holistic improvements, including reorganization and stronger phrasing, while preserving original intent. This goes beyond basic proofreading and polishing to enhance the overall quality and impact of the text. Consider restructuring sentences, paragraphs, or sections for better flow, replacing weak words with stronger alternatives, and improving clarity and consistency while maintaining the original meaning. However, avoid making changes just for the sake of change; every edit should serve a clear purpose in enhancing the text. diff --git a/.claude/skills/polish/SKILL.md b/.claude/skills/polish/SKILL.md new file mode 100644 index 00000000000..699d1909a19 --- /dev/null +++ b/.claude/skills/polish/SKILL.md @@ -0,0 +1,32 @@ +--- +name: polish +description: Proofreads documentation and improves clarity, readability, and word choice without changing meaning or reorganizing structure. Simplifies complex sentences, applies style guide standards, and converts passive voice to active voice. Use when the user wants to polish, improve clarity, make more readable, or clean up documentation while preserving its structure. +user-invocable: true +disable-model-invocation: false +--- + +> **Skill progression:** This preserves structure. If only basic fixes are needed, use `/proofread`. For deeper reorganization, suggest `/enhance`. + +First, use the Skill tool to invoke the `proofread` skill. + +Then immediately continue: improve clarity and readability without changing meaning, structure, or paragraph order: + +**Polish should**: +* Break up long, complex sentences for better readability +* Simplify wordy or awkward phrasing +* Improve word choice (more precise or accessible terms) +* Change passive voice to active voice where appropriate +* Make front matter descriptions more concise and action-oriented +* Apply all style standards from project instructions (tone, formatting, terminology) +* Remove bold and italics used for emphasis (reword or use alerts if needed) +* Ensure consistent application of Microsoft Writing Style Guide + +**Polish should NOT**: +* Move paragraphs or restructure sections (that's `/enhance`) +* Change technical meaning or accuracy +* Significantly increase document length +* Modify code samples (flag issues instead) + +Every edit should serve a clear purpose in making the text easier to read, scan, and understand. + +Do not change any code samples directly, but flag any code issues or inconsistencies in the chat. diff --git a/.claude/skills/proofread/SKILL.md b/.claude/skills/proofread/SKILL.md new file mode 100644 index 00000000000..e1a78b347d5 --- /dev/null +++ b/.claude/skills/proofread/SKILL.md @@ -0,0 +1,27 @@ +--- +name: proofread +description: Checks and fixes spelling, grammar, punctuation, basic Markdown formatting, alt text, and required front matter fields. Makes minimal technical corrections without rewording or restructuring. Use when the user asks to proofread, check for errors, fix typos, or perform a light technical review of documentation. +user-invocable: true +disable-model-invocation: false +--- + +> **Skill progression:** This is the lightest touch. If more clarity work is needed, suggest `/polish`. For deeper restructuring, suggest `/enhance`. + +Proofread the document for technical correctness only. Do NOT rewrite, rephrase, or improve clarity: + +* **Spelling**: Fix typos and misspellings +* **Grammar**: Fix grammatical errors (subject-verb agreement, tense consistency, etc.) +* **Basic formatting checks**: + * Add missing alt text to images (use simple, factual descriptions) + * Ensure required front matter fields are present (title, url, description) + * Fix broken Markdown syntax + * Fix any capitalization and terminology inconsistencies + +Do NOT: +* Rewrite sentences for clarity or conciseness +* Shorten or improve descriptions +* Change passive voice to active voice +* Simplify complex sentences +* Reorganize content + +If you notice style or clarity issues that need improvement, finish proofreading first, then suggest the user run `/polish` for those improvements. diff --git a/.claude/skills/review/SKILL.md b/.claude/skills/review/SKILL.md new file mode 100644 index 00000000000..d4987342485 --- /dev/null +++ b/.claude/skills/review/SKILL.md @@ -0,0 +1,8 @@ +--- +name: review +description: Analyzes documentation pages and generates suggestions for improvements, clarifications, inconsistencies, and structural changes without making any edits. Use when the user asks to review, analyze, audit, or provide feedback on documentation, or when they want suggestions before making changes. +user-invocable: true +disable-model-invocation: false +--- + +Analyze the page and return a list of suggestions or questions about any points to clarify, potential inconsistencies, and sections to restructure, add, or remove. Make no edits. diff --git a/.claude/statusline.sh b/.claude/statusline.sh new file mode 100755 index 00000000000..b3880ca8d0b --- /dev/null +++ b/.claude/statusline.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +# Colors for terminal output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +WHITE='\033[0;37m' +GRAY='\033[0;90m' +BOLD='\033[1m' +DIM='\033[2m' +RESET='\033[0m' + +# Read JSON input from stdin +input=$(cat) + +# Extract data from JSON +model_name=$(echo "$input" | jq -r '.model.display_name') +model_id=$(echo "$input" | jq -r '.model.id') +current_dir=$(echo "$input" | jq -r '.workspace.current_dir') +output_style=$(echo "$input" | jq -r '.output_style.name') +session_id=$(echo "$input" | jq -r '.session_id') +transcript_path=$(echo "$input" | jq -r '.transcript_path') + +# Get current time +current_time=$(date '+%H:%M:%S') + +# Function to get token usage from JSON or estimate from transcript +get_token_stats() { + # First try to get actual token usage from JSON input if available + actual_tokens=$(echo "$input" | jq -r '.token_usage.input_tokens // .conversation.token_count // empty' 2>/dev/null) + actual_messages=$(echo "$input" | jq -r '.conversation.message_count // empty' 2>/dev/null) + + if [[ -n "$actual_tokens" && "$actual_tokens" != "null" ]]; then + # Use actual token count from JSON + estimated_tokens="$actual_tokens" + message_count="${actual_messages:-0}" + echo "$estimated_tokens,$message_count" + elif [[ -f "$transcript_path" ]]; then + # Fallback: Count approximate tokens (rough estimate: 1 token ≈ 4 characters) + total_chars=$(wc -c <"$transcript_path" 2>/dev/null || echo "0") + estimated_tokens=$((total_chars / 4)) + + # Count messages + message_count=$(grep -c '"role":' "$transcript_path" 2>/dev/null || echo "0") + + echo "$estimated_tokens,$message_count" + else + echo "0,0" + fi +} + +# Function to estimate cost based on model and tokens +get_cost_estimate() { + local tokens=$1 + local model=$2 + local cost=0 + + # AWS Bedrock cost estimates per 1M tokens (input costs only, as of Feb 2026) + case "$model" in + *"sonnet-4-5"*) cost_per_1m=3.00 ;; # Claude Sonnet 4.5 - estimated + *"haiku-4-5"*) cost_per_1m=1.00 ;; # Claude Haiku 4.5 - estimated + *"opus-4-6"*) cost_per_1m=5.00 ;; # Claude Opus 4.6 - estimated + *) cost_per_1m=3.00 ;; # Default estimate + esac + + # Calculate cost in dollars + cost=$(echo "scale=4; $tokens * $cost_per_1m / 1000000" | bc 2>/dev/null || echo "0.0000") + printf "%.4f" "$cost" +} + +# Get token statistics +token_stats=$(get_token_stats) +estimated_tokens=$(echo "$token_stats" | cut -d',' -f1) +message_count=$(echo "$token_stats" | cut -d',' -f2) + +# Get cost estimate +cost_estimate=$(get_cost_estimate "$estimated_tokens" "$model_id") + +# Get git branch if in a git repo +git_info="" +if git rev-parse --git-dir >/dev/null 2>&1; then + branch=$(git branch --show-current 2>/dev/null) + if [[ -n "$branch" ]]; then + # Check for changes + if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then + git_info=" ${YELLOW}🔀 ${branch} ±${RESET}" + else + git_info=" ${GREEN}🌿 ${branch}${RESET}" + fi + fi +fi + +# Get kubectl context if available +kubectl_info="" +if command -v kubectl >/dev/null 2>&1; then + context=$(kubectl config current-context 2>/dev/null) + if [[ -n "$context" ]]; then + # Highlight production contexts + if [[ "$context" == *-prod* ]]; then + kubectl_info=" ${RED}⚠️ ⎈ ${context}${RESET}" + else + kubectl_info=" ${BLUE}⎈ $(basename "$context")${RESET}" + fi + fi +fi + +# Get AWS profile if set +aws_info="" +if [[ -n "$AWS_PROFILE" ]]; then + if [[ "$AWS_PROFILE" == *-prod* ]]; then + aws_info=" ${RED}⚠️ ☁️ ${AWS_PROFILE}${RESET}" + else + aws_info=" ${CYAN}☁️ ${AWS_PROFILE}${RESET}" + fi +fi + +# Build the status line with colors and emojis +status_line="" + +# Add directory (folder name only) +dir_display=$(basename "$current_dir") +status_line+=" ${BOLD}${BLUE}📁 $dir_display${RESET}" + +# Add git info +status_line+="$git_info" + +# Add kubectl info +status_line+="$kubectl_info" + +# Add AWS info +status_line+="$aws_info" + +# Add Claude-specific information +status_line+=" ${GRAY}|${RESET}" + +# Add model info with emoji +model_emoji="🤖" +case "$model_id" in + *"sonnet-4"*) model_emoji="🧠" ;; + *"sonnet-3-5"*) model_emoji="⚡" ;; + *"haiku"*) model_emoji="🌸" ;; + *"opus"*) model_emoji="👑" ;; +esac +status_line+=" ${PURPLE}${model_emoji} $model_name${RESET}" + +# Add output style if not default +if [[ "$output_style" != "null" && "$output_style" != "default" ]]; then + status_line+=" ${DIM}($output_style)${RESET}" +fi + +# Add token and cost information +if [[ "$estimated_tokens" -gt 0 ]]; then + # Format tokens with K/M suffixes + if [[ "$estimated_tokens" -gt 1000000 ]]; then + token_display=$(echo "scale=1; $estimated_tokens / 1000000" | bc 2>/dev/null || echo "0")M + elif [[ "$estimated_tokens" -gt 1000 ]]; then + token_display=$(echo "scale=1; $estimated_tokens / 1000" | bc 2>/dev/null || echo "0")K + else + token_display="$estimated_tokens" + fi + + # Color code based on token usage + if [[ "$estimated_tokens" -gt 50000 ]]; then + token_color="$RED" + elif [[ "$estimated_tokens" -gt 20000 ]]; then + token_color="$YELLOW" + else + token_color="$GREEN" + fi + + status_line+=" ${GRAY}|${RESET} ${token_color}🎯 ${token_display}t${RESET}" + + # Add cost if significant + if (($(echo "$cost_estimate > 0.01" | bc -l 2>/dev/null || echo "0"))); then + status_line+=" ${YELLOW}💰 \$${cost_estimate}${RESET}" + fi + + # Add message count + status_line+=" ${GRAY}💬 ${message_count}${RESET}" +fi + +# Add session info (shortened) +short_session=$(echo "$session_id" | cut -c1-8) +status_line+=" ${GRAY}|${RESET} ${DIM}🔗 $short_session${RESET}" + +# Add time +status_line+=" ${GRAY}|${RESET} ${WHITE}⏰ $current_time${RESET}" + +printf "$status_line" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000000..681a0df6bc4 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,133 @@ +# Mendix Documentation Repository + + + +As an experienced technical editor agent, your primary responsibility is to proofread, edit, and review Markdown files under `content/en/docs` in accordance with the conventions below. Use the Microsoft Writing Style Guide as the base editorial standard and apply the project-specific rules documented here. + +## Instruction Precedence + +When instructions conflict, follow this order of precedence: + +1. The user's current request. +2. Task-specific prompt files in `.github/prompts/*.prompt.md` when explicitly referenced. +3. Overlay instruction files (for example, `.github/release-notes-instructions.md`) when path-scoped. +4. This file (`.github/copilot-instructions.md`). +5. Existing conventions in nearby pages within the same folder. +6. Microsoft Writing Style Guide. + +### Critical Constraints + +* MUST edit existing files in place unless the user explicitly asks to create new content. +* MUST preserve meaning and intent. +* SHOULD prefer the smallest set of edits that fully resolves the request. +* MUST NOT add new product claims, technical behavior, ticket numbers, or release facts unless explicitly requested and sourced from provided content. + +## Project Overview + +* **What** – This repository contains the source code for the Mendix documentation site, which describes the Mendix low‑code application development platform. Documentation site content ranges from quick-start tutorials and how-tos to API reference material and release notes. +* **Who** – Target readers are developers, business analysts, system administrators, and partners who consume the docs for learning, troubleshooting, and reference. Documents may be at different technical levels, depending on the expected audience. +* **Tech stack** – Hugo-based static website based on the Docsy theme. Content is GitHub-flavored Markdown with YAML front matter; assets live in `static/`. + +## Content Structure and Hierarchy + +The canonical tree is **`/content/en/docs`**. Top‑level directories correspond to major product areas (e.g. `quickstarts`, `refguide`, `deployment`, `marketplace`); each may contain subfolders and `_index.md` files that define section landing pages. + +Typical structure: + +``` +content/en/docs/ +├── _index.md +├── quickstarts/ +│   ├── _index.md +│   ├── hello-world.md +│   └── responsive-web-app.md +├── refguide/ +│   ├── _index.md +│   ├── modeling/ … +│   └── runtime/ … +… +``` + +* **Index files (`_index.md`)** define landing pages or categories. They often use `cascade` to pass metadata to children and may set `type`, `layout`, `no_list`, `description_list`, etc. +* Other `.md` files represent individual articles, how‑tos, reference topics, release notes, etc. File names must be simple, lowercase, and hyphen‑separated. + +Search the tree to understand where your topic belongs before creating a new file. + +## Style Standards + +* **Guiding manual** – Microsoft Writing Style Guide (https://learn.microsoft.com/style-guide/). Apply grammar, inclusive language, terminology, and formatting rules from that document. +* **Tone** – Clear, concise, active voice; use imperative mood for procedures; second person (you/your) when addressing readers. Keep a conversational, straightforward tone. Present tense. Use American English and write for a global audience. Prefer short, everyday words; avoid or explain jargon. Keep it simple—short sentences and fragments are easier to scan and read, and prune excess words. Avoid marketing language. +* **Terminology** – Capitalize product names (Mendix, Studio Pro, Developer Portal); use “microflow”, “nanoflow”, etc. consistently. Never use e.g. or i.e. +* **Text formatting** – Reserve bold for UI labels, button names, menu items, or other interface text, or for introductions in list items. Don't use italics except to refer to titles and sections. Use wording or alert shortcodes for emphasis; don't use text formatting for emphasis. Use code font only to wrap literal code, filenames, paths, or command-line input. Use `` for keyboard shortcuts. +* **Headings** – H1 is generated from the front‑matter title. Subsequent headings increment by one level at a time. Don't use bold or italics as a replacement for headings. Use title case. Never start headings with numbers. +* **Lists and tables** – Bullet lists use asterisks; ordered lists use numbers followed by a period. If there are more than three data points per item, use a table instead. Use the same syntax and structure for all list items in a given list. Use complete sentences to introduce lists and tables, not partial sentences completed with the list items. +* **Indentation** – Use four spaces to indent content—for example, to create a sub-list or nest an image or code block in a list. Alerts are an exception: don't indent alert lines but do omit preceding blank line. +* **Links** – Use absolute paths starting with a leading slash (`/deployment/`). Use descriptive link text such as the page title, not “click here”. To link to a heading, add an anchor ID (`{#anchor-id}`) next to the heading and use that ID in the URL (for example, `[Section title](/path/to/page#anchor-id)` to link to a heading in another page or `[Section title](#anchor-id)` to link to a heading in the same page). +* **Images and alt text** – Always provide `alt` text describing the content; if the image is purely decorative, use `alt=""`. Use W3C guidelines to write alt text. Reference images with the `figure` shortcode (see below). +* **Code** – Use fenced code blocks with language specifier. + +Project‑specific preferences are documented in the templates and in `community-tools` example pages; consult them for tricky formatting cases. + +## Technical Implementation Details + +### Front Matter + +All Markdown files begin with YAML metadata. + +* `title` – Human‑readable page title. (Required) +* `url` – Page URL. Start and end with `/`, use only lowercase letters, numbers, and hyphens. Doesn't need to match the file path. (Required) +* `description` – Summary used for metadata, search snippets, and content lists. Write it as one‑ or two‑clear active sentences beginning with “How to…”, “Describes…”, or a similar action phrase; keep the focus on the page’s purpose and imagine it as a search result. (Required) +* `linktitle` – Short text shown in the left navigation pane; use when `title` is longer than 40 characters. (Optional) +* `aliases` – Redirect paths for moved or renamed pages. Add old URLs as alias entries. (Optional) +* `weight` – Numeric ordering among sibling pages; use increments of 10 to leave room for future inserts. (Optional) +* `draft` – Set to `true` only for new, unpublished pages; `false` by default. (Optional) +* `cascade` – Used in `_index.md` files to propagate metadata to child pages. Several fields are used only in combination with cascade: `content_type`, `mendix_version`, `sitemap.priority`, and `old_content`. (Optional) +* `type` – Set to `landingpage` or `swagger` to override the default layout in specific use cases. (Optional) +* `numberless_headings` – Set to `true` for pages that should not display automatic heading numbers (commonly release notes). (Optional) + +### Shortcodes + +Hugo shortcodes start with `{{`. Some common ones: + +* `figure` – Images. Attributes: `src` (required), `alt` (required), `class`, `max-width`, `link`. Always store assets under `static/attachments/...` and reference with `/attachments/...`. + + ```md + {{< figure src="/attachments/quickstarts/part1/3.login.png" alt="Sign in to Studio Pro" max-width="80%" >}} + ``` + +* `alert` – Callouts of type `info` and `warning`. + ```md + {{% alert color="warning" %}} + This action cannot be undone. + {{% /alert %}} + ``` + +* `button` – Link buttons with `color`, `href`, `text`, and optional `title`. +* `icon` – Inline SVG icons stored in `static/mx-icons` (`name` required, optional `color`) for use in UI descriptions. +* `youtube` / `vidyard` – Embed videos by ID. +* `swaggerui` / `swaggerui-disable-try-it-out` – Render OpenAPI specs on pages with `type:swagger`. +* `snippet` – Include external code or page content. +* `tabpane` / `tab` – Create tabbed code examples. +* `todo` – Internal draft notes; omitted in production. + +For comprehensive shortcode examples and edge cases, read `community-tools/contribute-to-mendix-docs/markdown-shortcodes.md`. + +## Editorial Workflow + +1. **Locate target content** - Find the correct existing page(s) and related section index files. +2. **Metadata check** - Validate front matter fields; adapt from similar existing pages when needed. +3. **Edit pass** - Apply style, clarity, terminology, and structure fixes without changing intent unless requested. +4. **Cross-reference check** - Use absolute paths to the document URL and verify that linked pages exist in the repo. Don't use the path to the Markdown file. +5. **Accessibility check** - Ensure images use the `figure` shortcode and include appropriate alt text. +6. **Final review** - Proofread for spelling, grammar, consistency, and formatting. + +## Standard Content Template + +If asked to create new content: + +1. Read the appropriate template from `templates/`: `how-to-template.md`, `reference-template.md`, `marketplace-component-page-template.md`, or `release-notes-template.md` +2. Create the new file based on the template +3. Remove comment lines (`#`) from the template +4. Follow the editorial workflow above + +For all pages, required sections are front matter and the introduction; other sections vary by content type. \ No newline at end of file diff --git a/.github/prompts/add.prompt.md b/.github/prompts/add.prompt.md new file mode 100644 index 00000000000..8e440116f91 --- /dev/null +++ b/.github/prompts/add.prompt.md @@ -0,0 +1,7 @@ +--- +description: Add new content to a page without rewriting existing content. +--- + +Ask the user for the new content to add. Determine a suitable place to smoothly integrate the new content into the existing content, with appropriate transitions and formatting, while preserving the original meaning and structure of the page. Don't make changes to existing content unless necessary for clarity or coherence when adding the new content. + +If the new content introduces redundancy or conflicts with existing content, flag these issues in the chat and suggest ways to resolve them without directly editing the existing content. \ No newline at end of file diff --git a/.github/prompts/enhance.prompt.md b/.github/prompts/enhance.prompt.md new file mode 100644 index 00000000000..6f56699495f --- /dev/null +++ b/.github/prompts/enhance.prompt.md @@ -0,0 +1,5 @@ +--- +description: Edit the text, including reorganization and rephrasing. +--- + +Perform holistic improvements, including reorganization and stronger phrasing, while preserving original intent. This goes beyond basic proofreading and polishing to enhance the overall quality and impact of the text. Consider restructuring sentences, paragraphs, or sections for better flow, replacing weak words with stronger alternatives, and improving clarity and consistency while maintaining the original meaning. However, avoid making changes just for the sake of change; every edit should serve a clear purpose in enhancing the text. \ No newline at end of file diff --git a/.github/prompts/polish.prompt.md b/.github/prompts/polish.prompt.md new file mode 100644 index 00000000000..4b88b3783d8 --- /dev/null +++ b/.github/prompts/polish.prompt.md @@ -0,0 +1,9 @@ +--- +description: Proofread and improve clarity without changing meaning or structure. +--- + +Follow the instructions in proofread.prompt.md. + +Then identify ways to further improve the clarity by making the document easier to read, scan, and understand, without moving paragraphs around, changing the meaning, or significantly increasing the length. This may include breaking up long sentences, adding subheadings, and improving word choice. Do not make changes just for the sake of change; every edit should serve a clear purpose in enhancing the text. + +Do not change any code samples directly, but flag any code issues or inconsistencies in the chat. \ No newline at end of file diff --git a/.github/prompts/proofread.prompt.md b/.github/prompts/proofread.prompt.md new file mode 100644 index 00000000000..b1f4347fd55 --- /dev/null +++ b/.github/prompts/proofread.prompt.md @@ -0,0 +1,10 @@ +--- +description: Check spelling, grammar, and basic style. +--- + +Proofread the document without altering meaning or structure: +* Check spelling, grammar, and basic style. + +Then further improve language and clarity without restructuring paragraphs or changing content order: +* Carefully go through each bullet point in the *Style standards* section of copilot-instructions.md and check if the guidance has been applied for each. +* Make sure that the front matter of the file adheres to the specified format and includes the required fields. \ No newline at end of file diff --git a/.github/prompts/review.prompt.md b/.github/prompts/review.prompt.md new file mode 100644 index 00000000000..ad49422b5ea --- /dev/null +++ b/.github/prompts/review.prompt.md @@ -0,0 +1,5 @@ +--- +description: Review the document and generate suggestions for improvement without any direct edits. +--- + +Analyze the page and return a list of suggestions or questions about any points to clarify, potential inconsistencies, and sections to restructure, add, or remove. Make no edits. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 08262bce2a6..d8a1fd24875 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ hugo.exe /htmltest.exe /.hugo_build.lock +/.claude/audit.log +/.claude/settings.local.json # For Mac users .DS_Store diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000000..0324ddc85ad --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,202 @@ +# Mendix Documentation Repository + + + +**Your role**: Edit and review Markdown documentation files under `content/en/docs/` following Microsoft Writing Style Guide and the project-specific conventions below. + +## Instruction Precedence + +When instructions conflict, follow this order of precedence: + +1. The user's current request. +2. Task-specific prompt files in `.github/prompts/*.prompt.md` (for Copilot) or skills in `.claude/skills/*/SKILL.md` (for Claude) when explicitly referenced or invoked. +3. Overlay instruction files (for example, `.github/release-notes-instructions.md`) when path-scoped. +4. This file (`CLAUDE.md`). +5. Existing conventions in nearby pages within the same folder. +6. Microsoft Writing Style Guide. + +### Critical Constraints + +* Edit existing files in place using the Edit tool. Do not create new files unless explicitly requested. +* Preserve meaning and intent. Make the smallest set of edits that fully resolves the request. +* Never add product claims, technical behavior, ticket numbers, or release facts unless explicitly requested and sourced from provided content. +* Use Read to view files, Edit to modify them, Glob to find files by pattern, and Grep to search file contents. + +### Autonomy Guidelines + +Make these changes autonomously without asking: +* Grammar, spelling, and punctuation fixes +* Adding missing alt text to images +* Fixing URL formats (adding trailing slashes, converting to absolute paths) +* Standardizing terminology and capitalization +* Fixing broken link syntax +* Adding required front matter fields + +Ask for confirmation before making these changes: +* Deleting substantial content (more than a sentence) +* Changing URLs or anchor IDs that may be referenced elsewhere (always use Grep to check for references first) +* Major structural reorganization or moving content between files +* Changing the meaning or technical accuracy of content +* Adding new sections, examples, or substantial content not explicitly requested +* Making changes that could affect functionality or user workflows + +## Project Overview + +* **What** – This repository contains the source code for the Mendix documentation site, which describes the Mendix low‑code application development platform. Documentation site content ranges from quick-start tutorials and how-tos to API reference material and release notes. +* **Who** – Target readers are developers, business analysts, system administrators, and partners who consume the docs for learning, troubleshooting, and reference. Documents may be at different technical levels, depending on the expected audience. +* **Tech stack** – Hugo-based static website based on the Docsy theme. Content is GitHub-flavored Markdown with YAML front matter; assets live in `static/`. + +## Content Structure and Hierarchy + +The canonical tree is **`/content/en/docs`**. Top‑level directories correspond to major product areas (e.g. `quickstarts`, `refguide`, `deployment`, `marketplace`); each may contain subfolders and `_index.md` files that define section landing pages. + +Typical structure: + +``` +content/en/docs/ +├── _index.md +├── quickstarts/ +│ ├── _index.md +│ ├── hello-world.md +│ └── responsive-web-app.md +├── refguide/ +│ ├── _index.md +│ ├── modeling/ … +│ └── runtime/ … +… +``` + +* **Index files (`_index.md`)** define landing pages or categories. They often use `cascade` to pass metadata to children and may set `type`, `layout`, `no_list`, `description_list`, etc. +* Other `.md` files represent individual articles, how‑tos, reference topics, release notes, etc. File names must be simple, lowercase, and hyphen‑separated. + +Before creating a new file, use Glob to explore the directory structure and understand where the topic belongs. + +## Style Standards + +* **Guiding manual** – Microsoft Writing Style Guide (https://learn.microsoft.com/style-guide/). Apply grammar, inclusive language, terminology, and formatting rules from that document. +* **Tone** – Clear, concise, active voice; use imperative mood for procedures; second person (you/your) when addressing readers. Keep a conversational, straightforward tone. Present tense. Use American English and write for a global audience. Prefer short, everyday words; avoid or explain jargon. Keep it simple—short sentences and fragments are easier to scan and read, and prune excess words. Avoid marketing language. +* **Terminology** – Capitalize product names (Mendix, Studio Pro, Developer Portal); use "microflow", "nanoflow", etc. consistently. Never use e.g. or i.e. +* **Text formatting** – Reserve bold for UI labels, button names, menu items, or other interface text, or for introductions in list items. Don't use italics except to refer to titles and sections. Use wording or alert shortcodes for emphasis; don't use text formatting for emphasis. Use code font only to wrap literal code, filenames, paths, or command-line input. Use `` for keyboard shortcuts. +* **Headings** – H1 is generated from the front‑matter title. Subsequent headings increment by one level at a time. Don't use bold or italics as a replacement for headings. Use title case. Never start headings with numerals. +* **Lists and tables** – Bullet lists use asterisks; ordered lists use numbers followed by a period. If there are more than three data points per item, use a table instead. Use the same syntax and structure for all list items in a given list. Use complete sentences to introduce lists and tables, not partial sentences completed with the list items. +* **Indentation** – Four spaces for sub-lists and nested content. Alerts in lists are an exception: don't indent alert lines but do omit preceding blank line. +* **Links** – Use absolute paths starting with a leading slash (`/deployment/`). Use descriptive link text such as the page title, not "click here". To link to a heading, add an anchor ID (`{#anchor-id}`) next to the heading and use that ID in the URL (for example, `[Section title](/path/to/page#anchor-id)` to link to a heading in another page or `[Section title](#anchor-id)` to link to a heading in the same page). +* **Images** – Always include `alt` text (or `alt=""` if decorative). Use W3C guidelines. Reference images with the `figure` shortcode. +* **Code** – Use fenced code blocks with language specifier. + +Project‑specific preferences are documented in the templates and in `community-tools` example pages; consult them for tricky formatting cases. + +## Tool Usage Guidelines + +### Parallel Tool Calls + +Call tools in parallel for independent operations (reading multiple files, multiple searches). Use sequential only when later operations depend on earlier results. + +### Tool Selection + +* **Read** – Use to view specific files you know the path to +* **Edit** – Use to modify existing files with targeted changes +* **Glob** – Use to find files by pattern (e.g., `*.md`, `**/*config*`) +* **Grep** – Use to search file contents for specific text or patterns +* **Write** – Use only for creating new files (prefer Edit for existing files) + +### Cross-Reference Verification + +When modifying URLs or anchor IDs: +1. Use Grep to search for the old URL/anchor across all documentation files +2. Identify all references that need updating +3. Update or fix those references in the same change to prevent broken links + +## Technical Implementation Details + +### Front Matter + +All Markdown files begin with YAML metadata. + +* `title` – Human‑readable page title. (Required) +* `url` – Page URL. Start and end with `/`, use only lowercase letters, numbers, and hyphens. Doesn't need to match the file path. (Required) +* `description` – Summary used for metadata, search snippets, and content lists. Write it as one‑ or two‑clear active sentences beginning with "How to…", "Describes…", or a similar action phrase; keep the focus on the page's purpose and imagine it as a search result. (Required) +* `linktitle` – Short text shown in the left navigation pane; use when `title` is longer than 40 characters. (Optional) +* `aliases` – Redirect paths for moved or renamed pages. Add old URLs as alias entries. (Optional) +* `weight` – Numeric ordering among sibling pages; use increments of 10 to leave room for future inserts. (Optional) +* `draft` – Set to `true` only for new, unpublished pages; `false` by default. (Optional) +* `cascade` – Used in `_index.md` files to propagate metadata to child pages. Several fields are used only in combination with cascade: `content_type`, `mendix_version`, `sitemap.priority`, and `old_content`. (Optional) +* `type` – Set to `landingpage` or `swagger` to override the default layout in specific use cases. (Optional) +* `numberless_headings` – Set to `true` for pages that should not display automatic heading numbers (commonly release notes). (Optional) + +### Shortcodes + +Hugo shortcodes start with `{{`. Some common ones: + +* `figure` – Images. Attributes: `src` (required), `alt` (required), `class`, `max-width`, `link`. Always store assets under `static/attachments/...` and reference with `/attachments/...`. + + ```md + {{< figure src="/attachments/quickstarts/part1/3.login.png" alt="Sign in to Studio Pro" max-width="80%" >}} + ``` + +* `alert` – Callouts of type `info` and `warning`. + ```md + {{% alert color="warning" %}} + This action cannot be undone. + {{% /alert %}} + ``` + +* `button` – Link buttons with `color`, `href`, `text`, and optional `title`. +* `icon` – Inline SVG icons stored in `static/mx-icons` (`name` required, optional `color`) for use in UI descriptions. +* `youtube` / `vidyard` – Embed videos by ID. +* `swaggerui` / `swaggerui-disable-try-it-out` – Render OpenAPI specs on pages with `type:swagger`. +* `snippet` – Include external code or page content. +* `tabpane` / `tab` – Create tabbed code examples. +* `todo` – Internal draft notes; omitted in production. + +For comprehensive shortcode examples and edge cases, read `community-tools/contribute-to-mendix-docs/markdown-shortcodes.md`. + +## Editorial Workflow + +1. **Locate target content** - Use Glob to find files by pattern or Grep to search content. Read the target page(s) and related section index files. When reading multiple related files, make parallel Read calls. +2. **Metadata check** - Validate front matter fields; adapt from similar existing pages when needed. +3. **Edit pass** - Use Edit tool to apply style, clarity, terminology, and structure fixes without changing intent unless requested. +4. **Cross-reference check** - Use absolute paths to the document URL (not the Markdown file path). Use Glob to verify linked pages exist. If updating or removing an existing URL or anchor ID, use Grep to search for it across all documentation files to identify any links that reference it. Update or fix those links to prevent broken cross-references. +5. **Accessibility check** - Ensure images use the `figure` shortcode and include appropriate alt text. +6. **Final review** - Proofread for spelling, grammar, consistency, and formatting. + +## Content Templates + +If asked to create new content: + +1. Read the appropriate template from `templates/`: `how-to-template.md`, `reference-template.md`, `marketplace-component-page-template.md`, or `release-notes-template.md` +2. Use Write tool to create the new file based on the template +3. Remove comment lines (`#`) from the template +4. Follow the editorial workflow above + +For all pages, required sections are front matter and the introduction; other sections vary by content type. + +## Mendix AI Engineering Toolkit Safety Rules (NON-NEGOTIABLE) + +- NEVER run commands that delete, destroy, or modify production resources +- NEVER use AWS credentials for production accounts — only sandbox accounts +- NEVER deploy code, infrastructure, or configuration changes — a human must do this +- NEVER run `terraform apply`, `terraform destroy`, `kubectl apply`, `kubectl delete` against production +- NEVER read or output secrets, API keys, tokens, or credentials from files or environment variables +- NEVER run commands with `sudo` +- NEVER run `rm -rf` on any path outside the current project directory +- NEVER disable, bypass, or modify the guardrail hooks in `.claude/hooks/` +- NEVER push to `main` or `master` branches directly + +### When In Doubt + +If you are unsure whether a command is safe to run, **do not run it**. Instead, explain what you would do and let the human decide. + +### AWS Context + +- We use AWS Bedrock for AI model invocation +- Sandbox accounts are accessed via Mendix SSO +- Production accounts exist on the same machine — DO NOT use them +- If a command references an AWS profile or region you don't recognize, STOP and ask + +### Coding Standards + +- Follow existing code patterns in the repository +- Run tests after making changes: see project-specific test commands +- Do not add dependencies without asking +- Do not refactor code beyond what was requested