- nomgap-client: add electrolyte_reminder + extended_fast_warning to PushTriggerType; rename scheduledAt → scheduledFor to match backend schema; fix startedAt type string → number (backend stores epoch ms) - nomgap-tools: rename scheduledAt → scheduledFor in nomgap.push.fire tool schema + execute call - safety-monitor-pipeline: fix FastStateResult.startedAt type number; use epoch ms directly instead of new Date(string) - sync-diagnostics-pipeline: remove peakpulseGetStats (returns aggregate stats not sync queue); derive queueDepth from recentFailureCount telemetry; add lastSuccessfulSync derivation from events
548 lines
20 KiB
Bash
Executable File
548 lines
20 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# scripts/update-agent-docs.sh
|
|
#
|
|
# Regenerates AI agent config files across all repos listed in repos.txt.
|
|
#
|
|
# Files always regenerated (overwritten):
|
|
# .cursorrules, .windsurfrules, .clinerules, .aider.conf.yml,
|
|
# .editorconfig, .github/copilot-instructions.md
|
|
#
|
|
# Files created only if missing (never overwritten):
|
|
# CLAUDE.md — hand-crafted summary; script creates a placeholder if absent
|
|
#
|
|
# Files never touched:
|
|
# AGENTS.md — canonical source of truth; must be maintained manually
|
|
#
|
|
# Usage:
|
|
# ./scripts/update-agent-docs.sh # regenerate + commit
|
|
# ./scripts/update-agent-docs.sh --dry-run # show what would change, no writes
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPOS_TXT="${SCRIPT_DIR}/../.windsurf/workflows/repos.txt"
|
|
BASE_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
DRY_RUN=false
|
|
CHANGED_REPOS=()
|
|
|
|
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
|
|
|
# ── colours ────────────────────────────────────────────────────────────────
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
|
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
header(){ echo -e "\n${CYAN}══ $* ══${NC}"; }
|
|
|
|
# ── per-repo single-line metadata ──────────────────────────────────────────
|
|
set_meta() {
|
|
NAME="" ID="" TAGLINE="" STACK="" BUILD_VFY="" LINT1="" LINT2="" LINT3="" AIDER_READ2="README.md"
|
|
case "$1" in
|
|
learning_ai_common_plat)
|
|
NAME="@bytelyst Common Platform"
|
|
ID="(product-agnostic)"
|
|
TAGLINE="Shared packages + microservices for the ByteLyst ecosystem"
|
|
STACK="TypeScript, ESM, pnpm workspace, Fastify 5, Vitest, Azure Cosmos DB"
|
|
BUILD_VFY="pnpm build && pnpm test && pnpm typecheck"
|
|
LINT1="pnpm build 2>&1 | tail -10"
|
|
LINT2="pnpm test 2>&1 | tail -10"
|
|
LINT3="pnpm typecheck 2>&1 | tail -10"
|
|
AIDER_READ2="README.md"
|
|
;;
|
|
learning_voice_ai_agent)
|
|
NAME="LysnrAI"
|
|
ID="lysnrai"
|
|
TAGLINE="Cross-platform voice-to-text dictation platform"
|
|
STACK="Python 3.12 (desktop/backend) + Next.js 16 (dashboards) + Fastify 5 (microservices in sibling repo)"
|
|
BUILD_VFY="python -m pytest tests/ -v --tb=short"
|
|
LINT1="cd user-dashboard-web && npx tsc --noEmit 2>&1 | tail -10"
|
|
LINT2="python -m pytest tests/ -x --tb=short 2>&1 | tail -10"
|
|
AIDER_READ2="README_MONO_REPO.md"
|
|
;;
|
|
learning_multimodal_memory_agents)
|
|
NAME="MindLyst"
|
|
ID="mindlyst"
|
|
TAGLINE="Role-Based Life OS — AI-powered multimodal second brain"
|
|
STACK="KMP (shared) + SwiftUI (iOS) + Jetpack Compose (Android) + Next.js 16 (web)"
|
|
BUILD_VFY="./gradlew :shared:compileKotlinIosSimulatorArm64"
|
|
LINT1="cd mindlyst-native && ./gradlew :shared:compileKotlinIosSimulatorArm64 2>&1 | tail -5"
|
|
LINT2="cd mindlyst-native/web && npx next build 2>&1 | tail -10"
|
|
AIDER_READ2="ARCHITECTURE.md"
|
|
;;
|
|
learning_ai_clock)
|
|
NAME="ChronoMind"
|
|
ID="chronomind"
|
|
TAGLINE="AI-Powered Contextual Clock & Timer"
|
|
STACK="Next.js 16 (web) + SwiftUI (iOS/Watch/Mac) + Jetpack Compose (Android) + Fastify 5 (backend)"
|
|
BUILD_VFY="cd web && npm test && npm run typecheck && npm run build"
|
|
LINT1="cd web && npm test 2>&1 | tail -10"
|
|
LINT2="cd web && npm run typecheck 2>&1 | tail -10"
|
|
AIDER_READ2="docs/PRD.md"
|
|
;;
|
|
learning_ai_fastgap)
|
|
NAME="NomGap"
|
|
ID="nomgap"
|
|
TAGLINE="Fasting visualization and coaching app"
|
|
STACK="React Native (Expo SDK 55) + TypeScript + Fastify 5 (backend)"
|
|
BUILD_VFY="npm test && npm run typecheck"
|
|
LINT1="npm test 2>&1 | tail -10"
|
|
LINT2="npm run typecheck 2>&1 | tail -10"
|
|
AIDER_READ2="docs/PRD.md"
|
|
;;
|
|
learning_ai_jarvis_jr)
|
|
NAME="JarvisJr"
|
|
ID="jarvisjr"
|
|
TAGLINE="Voice-first multi-agent coaching platform"
|
|
STACK="SwiftUI (iOS/Watch/Mac) + Next.js 16 (web) + Jetpack Compose (Android) + Fastify 5 (backend)"
|
|
BUILD_VFY="cd web && npm test && npm run typecheck && npm run build"
|
|
LINT1="cd web && npm test 2>&1 | tail -10"
|
|
LINT2="cd web && npm run typecheck 2>&1 | tail -10"
|
|
AIDER_READ2="docs/ENHANCED_IDEA_v2.md"
|
|
;;
|
|
learning_ai_peakpulse)
|
|
NAME="PeakPulse"
|
|
ID="peakpulse"
|
|
TAGLINE="Sensor-driven adventure tracker for hikers and skiers"
|
|
STACK="SwiftUI (iOS 17+), SwiftData, MapKit, WeatherKit, ActivityKit, WidgetKit, App Intents"
|
|
BUILD_VFY="cd ios && xcodegen generate && xcodebuild -scheme PeakPulse -sdk iphonesimulator build"
|
|
LINT1="cd ios && xcodebuild -scheme PeakPulse -sdk iphonesimulator build 2>&1 | tail -20"
|
|
AIDER_READ2="docs/PRD.md"
|
|
;;
|
|
*)
|
|
warn "Unknown repo: $1 — skipping"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ── per-repo multi-line content ─────────────────────────────────────────────
|
|
repo_rules() {
|
|
case "$1" in
|
|
learning_ai_common_plat)
|
|
echo "- Package manager: pnpm — NEVER use npm"
|
|
echo "- ESM everywhere: \"type\": \"module\", .js extensions in imports"
|
|
echo "- Fastify module pattern: types.ts → repository.ts → routes.ts"
|
|
echo "- Use req.log / app.log — never console.log"
|
|
echo "- Every Cosmos document MUST include a productId field"
|
|
echo "- peerDependencies for heavy deps; workspace:* for inter-package deps"
|
|
echo "- Services re-export @bytelyst/* in src/lib/ for clean internal imports"
|
|
;;
|
|
learning_voice_ai_agent)
|
|
echo "- Python: structlog (never print), ruff lint, type hints required, pydantic-settings"
|
|
echo "- TypeScript: App Router (not Pages), @bytelyst/api-client for service clients"
|
|
echo "- All Cosmos documents MUST include productId field"
|
|
echo "- Use PRODUCT_ID from @bytelyst/config — never hardcode \"lysnrai\""
|
|
echo "- Dashboards: TailwindCSS v4, shadcn/ui, Recharts"
|
|
echo "- Desktop build requires --webpack flag for Next.js"
|
|
;;
|
|
learning_multimodal_memory_agents)
|
|
echo "- ALL business logic in shared/src/commonMain/ — NEVER in platform UI code"
|
|
echo "- Android/iOS/Web are thin UI shells consuming shared repositories via StateFlow"
|
|
echo "- Koin for DI — register all new deps in SharedModule.kt"
|
|
echo "- MindLystTokens.kt is the single source of design tokens"
|
|
echo "- Web: Pages Router, vanilla CSS with --ml-* props, NO Tailwind"
|
|
echo "- Use compilerOptions {} (not deprecated kotlinOptions {})"
|
|
echo "- Use StateFlow for observable state, never LiveData"
|
|
;;
|
|
learning_ai_clock)
|
|
echo "- Web engine logic in web/src/lib/ — pure TS, no React imports"
|
|
echo "- Components in web/src/components/ — React UI only"
|
|
echo "- iOS shared logic in ios/ChronoMind/Shared/ — consumed by all Apple targets"
|
|
echo "- Android engine in android/.../engine/ — pure Kotlin, no Android framework deps"
|
|
echo "- Web build: must use --webpack flag (Serwist incompatible with Turbopack)"
|
|
echo "- Every Cosmos doc: productId: \"chronomind\""
|
|
echo "- Theme: --cm-* CSS custom properties (web), ChronoMindTheme (native)"
|
|
;;
|
|
learning_ai_fastgap)
|
|
echo "- All engine logic in src/lib/ — zero React Native imports"
|
|
echo "- Screens are thin composites wiring store + engines + components"
|
|
echo "- Theme tokens from src/theme/ — never hardcode colors, spacing, or fonts"
|
|
echo "- Expo native modules mocked in __mocks__/ for Vitest"
|
|
echo "- Engine modules are pure functions — testable without mocking RN"
|
|
echo "- Every Cosmos doc: productId: \"nomgap\""
|
|
;;
|
|
learning_ai_jarvis_jr)
|
|
echo "- iOS shared logic in ios/JarvisJr/Shared/ — consumed by iOS, Watch, Mac"
|
|
echo "- Web engine in web/src/lib/ — pure TS, no React imports"
|
|
echo "- Web components in web/src/components/ — React UI only"
|
|
echo "- Android engine in android/.../engine/ — pure Kotlin, no Android framework deps"
|
|
echo "- Web build: must use --webpack flag (Serwist incompatible with Turbopack)"
|
|
echo "- Never use print() in Swift — use os.Logger"
|
|
echo "- Theme: --jj-* CSS custom properties (web), JarvisJrTheme (native)"
|
|
echo "- Every Cosmos doc: productId: \"jarvisjr\""
|
|
;;
|
|
learning_ai_peakpulse)
|
|
echo "- Models in ios/PeakPulse/Models/ — SwiftData @Model + Codable structs"
|
|
echo "- Services in ios/PeakPulse/Services/ — pure Swift engine logic"
|
|
echo "- ViewModels in ios/PeakPulse/ViewModels/ — @Observable MVVM"
|
|
echo "- Platform/ files are thin wrappers over ByteLystPlatformSDK — never reimplement"
|
|
echo "- All logging via os.Logger — never use print()"
|
|
echo "- All colors from PeakPulseTheme — never hardcode"
|
|
echo "- Every Cosmos doc: productId: \"peakpulse\""
|
|
;;
|
|
esac
|
|
}
|
|
|
|
repo_paths() {
|
|
case "$1" in
|
|
learning_ai_common_plat)
|
|
echo "- packages/ — @bytelyst/* shared libraries (errors, cosmos, config, auth, api-client, fastify-core, react-auth, logger, testing, blob, extraction, monitoring, design-tokens)"
|
|
echo "- services/platform-service/ — consolidated platform service (port 4003)"
|
|
echo "- services/extraction-service/ — text extraction + Python sidecar (port 4005)"
|
|
echo "- dashboards/admin-web/ — admin console (port 3001)"
|
|
echo "- dashboards/tracker-web/ — issue tracker (port 3003)"
|
|
;;
|
|
learning_voice_ai_agent)
|
|
echo "- src/ — Desktop app (Python 3.12, tkinter, Azure Speech SDK)"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4015)"
|
|
echo "- user-dashboard-web/ — Next.js 16 user portal (port 3002)"
|
|
echo "- ../learning_ai_common_plat/services/ — platform-service (4003), extraction-service (4005)"
|
|
echo "- ../learning_ai_common_plat/dashboards/ — admin-web (3001), tracker-web (3003)"
|
|
echo "- mobile_app/ios/ — Swift + SwiftUI"
|
|
echo "- mobile_app/android/ — Kotlin + Jetpack Compose"
|
|
;;
|
|
learning_multimodal_memory_agents)
|
|
echo "- mindlyst-native/shared/src/commonMain/ — KMP shared logic (ALL business logic)"
|
|
echo "- mindlyst-native/androidApp/ — Jetpack Compose Android app"
|
|
echo "- mindlyst-native/iosApp/ — SwiftUI iOS app"
|
|
echo "- mindlyst-native/web/ — Next.js 16 web dashboard"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4014)"
|
|
echo "- design-system/ — design tokens source"
|
|
;;
|
|
learning_ai_clock)
|
|
echo "- web/src/lib/ — Pure TS engine modules (timer, cascade, urgency, nl-parser, etc.)"
|
|
echo "- web/src/components/ — React UI components"
|
|
echo "- ios/ChronoMind/Shared/ — Shared Swift code (iOS + Watch + Mac + Widgets)"
|
|
echo "- android/app/.../engine/ — Pure Kotlin engine"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4011)"
|
|
;;
|
|
learning_ai_fastgap)
|
|
echo "- src/lib/ — Pure engine modules (NO React Native deps)"
|
|
echo "- src/screens/ — Screen components (thin UI composites)"
|
|
echo "- src/components/ — Reusable UI components"
|
|
echo "- src/store/ — Zustand store"
|
|
echo "- src/theme/ — Design tokens (colors, typography, spacing)"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4013)"
|
|
;;
|
|
learning_ai_jarvis_jr)
|
|
echo "- ios/JarvisJr/Shared/ — Cross-platform Swift code (iOS + Watch + Mac)"
|
|
echo "- web/src/lib/ — Pure TS engine + API clients"
|
|
echo "- web/src/app/ — Next.js App Router pages"
|
|
echo "- android/app/.../engine/ — Pure Kotlin engine"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4012)"
|
|
;;
|
|
learning_ai_peakpulse)
|
|
echo "- ios/PeakPulse/Models/ — SwiftData models"
|
|
echo "- ios/PeakPulse/Services/ — Pure Swift engine logic"
|
|
echo "- ios/PeakPulse/ViewModels/ — @Observable MVVM"
|
|
echo "- ios/PeakPulse/Views/ — SwiftUI screens + components"
|
|
echo "- ios/PeakPulse/Platform/ — ByteLystPlatformSDK thin wrappers"
|
|
echo "- backend/ — Fastify 5 + TypeScript backend (port 4010)"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ── file generators ─────────────────────────────────────────────────────────
|
|
|
|
write_editorconfig() {
|
|
cat > "$1" << 'EOF'
|
|
root = true
|
|
|
|
[*]
|
|
indent_style = space
|
|
indent_size = 2
|
|
end_of_line = lf
|
|
charset = utf-8
|
|
trim_trailing_whitespace = true
|
|
insert_final_newline = true
|
|
|
|
[*.md]
|
|
trim_trailing_whitespace = false
|
|
EOF
|
|
}
|
|
|
|
write_cursorrules() {
|
|
local dest="$1" repo="$2"
|
|
local RULES PATHS
|
|
RULES=$(repo_rules "$repo")
|
|
PATHS=$(repo_paths "$repo")
|
|
cat > "$dest" << EOF
|
|
# ${NAME} — Cursor Rules
|
|
# Read AGENTS.md for full context.
|
|
|
|
Project: ${NAME} — ${TAGLINE}
|
|
Product ID: ${ID}
|
|
Stack: ${STACK}
|
|
|
|
## Architecture
|
|
${PATHS}
|
|
|
|
## Rules
|
|
${RULES}
|
|
- Commits: feat(scope): description / fix(scope): description
|
|
- Never delete existing comments/documentation unless asked
|
|
- Never add emojis unless asked
|
|
- Never hardcode secrets, colors, or API URLs
|
|
|
|
## Build Verification
|
|
- ${BUILD_VFY}
|
|
|
|
## Key Documents
|
|
- AGENTS.md — Full AI agent instructions (read this first)
|
|
EOF
|
|
}
|
|
|
|
write_windsurfrules() {
|
|
local dest="$1" repo="$2"
|
|
local RULES PATHS
|
|
RULES=$(repo_rules "$repo")
|
|
PATHS=$(repo_paths "$repo")
|
|
cat > "$dest" << EOF
|
|
# ${NAME} — Windsurf / Codeium Rules
|
|
# Read AGENTS.md for full context. These are the critical rules.
|
|
|
|
Project: ${NAME} — ${TAGLINE}
|
|
Stack: ${STACK}
|
|
|
|
## Architecture Rules
|
|
${PATHS}
|
|
|
|
## Conventions
|
|
${RULES}
|
|
- Commits: feat(scope): description / fix(scope): description
|
|
|
|
## Build Verification
|
|
- ${BUILD_VFY}
|
|
EOF
|
|
}
|
|
|
|
write_clinerules() {
|
|
local dest="$1" repo="$2"
|
|
local RULES PATHS
|
|
RULES=$(repo_rules "$repo")
|
|
PATHS=$(repo_paths "$repo")
|
|
cat > "$dest" << EOF
|
|
# .clinerules — Cline / Roo Code Rules for ${NAME}
|
|
# Read AGENTS.md for the complete onboarding guide.
|
|
|
|
## Project: ${NAME} — ${TAGLINE}
|
|
Architecture: ${STACK}
|
|
|
|
## Mandatory Rules
|
|
${RULES}
|
|
- Commits: \`type(scope): description\`
|
|
- After changes, verify: \`${BUILD_VFY}\`
|
|
|
|
## Key File Locations
|
|
${PATHS}
|
|
- Full guide: \`AGENTS.md\`
|
|
EOF
|
|
}
|
|
|
|
write_aider_conf() {
|
|
local dest="$1"
|
|
# Build lint-cmd list (skip empty entries)
|
|
local lint_block=""
|
|
for cmd in "${LINT1:-}" "${LINT2:-}" "${LINT3:-}"; do
|
|
[[ -z "$cmd" ]] && continue
|
|
lint_block+=" - '${cmd}'"$'\n'
|
|
done
|
|
# Build read list
|
|
local read_block=" - AGENTS.md"$'\n'
|
|
[[ -n "${AIDER_READ2:-}" ]] && read_block+=" - ${AIDER_READ2}"$'\n'
|
|
|
|
cat > "$dest" << EOF
|
|
# .aider.conf.yml — Aider Configuration for ${NAME}
|
|
# Helps Aider understand the project structure and conventions.
|
|
|
|
read:
|
|
${read_block}
|
|
conventions: AGENTS.md
|
|
|
|
lint-cmd:
|
|
${lint_block}
|
|
auto-commits: false
|
|
EOF
|
|
}
|
|
|
|
write_copilot_instructions() {
|
|
local dest_dir="$1" repo="$2"
|
|
local RULES PATHS
|
|
RULES=$(repo_rules "$repo")
|
|
PATHS=$(repo_paths "$repo")
|
|
mkdir -p "$dest_dir"
|
|
cat > "${dest_dir}/copilot-instructions.md" << EOF
|
|
# GitHub Copilot Instructions — ${NAME}
|
|
|
|
> For full agent instructions, read [\`AGENTS.md\`](../AGENTS.md) at the repo root.
|
|
|
|
## Project Context
|
|
|
|
**${NAME}** — ${TAGLINE}.
|
|
Stack: ${STACK}
|
|
|
|
## Code Generation Rules
|
|
|
|
### Always
|
|
${RULES}
|
|
- Include \`productId: "${ID}"\` in every Cosmos DB document
|
|
- Use \`type(scope): description\` commit message format
|
|
- Fix source code, not tests (unless the test itself is wrong)
|
|
|
|
### Never
|
|
- \`console.log\` or \`print()\` in production code
|
|
- Hardcoded secrets, API keys, colors, or URLs
|
|
- Delete existing comments or documentation unless explicitly asked
|
|
- Add emojis unless asked
|
|
|
|
## Key Paths
|
|
${PATHS}
|
|
|
|
## Build Verification
|
|
\`\`\`bash
|
|
${BUILD_VFY}
|
|
\`\`\`
|
|
EOF
|
|
}
|
|
|
|
write_claude_placeholder() {
|
|
local dest="$1" repo="$2"
|
|
local PATHS
|
|
PATHS=$(repo_paths "$repo")
|
|
cat > "$dest" << EOF
|
|
# ${NAME} — Claude Code Instructions
|
|
|
|
> This file is read automatically by Claude Code. For full agent instructions
|
|
> shared across all AI tools, see [\`AGENTS.md\`](AGENTS.md).
|
|
|
|
## Quick Context
|
|
|
|
**Product:** ${NAME} — ${TAGLINE}
|
|
**Product ID:** \`${ID}\`
|
|
**Stack:** ${STACK}
|
|
|
|
## Rules
|
|
|
|
1. **Read \`AGENTS.md\` first** — it has coding conventions, file ownership, and tech stack rules.
|
|
2. **Every Cosmos document** must have a \`productId: "${ID}"\` field.
|
|
3. **Commit messages:** \`type(scope): description\` (feat, fix, docs, refactor, test, chore).
|
|
4. **Fix source, not tests** — unless the test itself is wrong.
|
|
5. **Never use** \`console.log\`, \`print()\`, or hardcoded colors/secrets/URLs.
|
|
|
|
## Architecture
|
|
|
|
${PATHS}
|
|
|
|
## Build Verification
|
|
|
|
\`\`\`bash
|
|
${BUILD_VFY}
|
|
\`\`\`
|
|
EOF
|
|
}
|
|
|
|
# ── main loop ───────────────────────────────────────────────────────────────
|
|
|
|
if [[ ! -f "$REPOS_TXT" ]]; then
|
|
echo -e "${RED}[ERROR]${NC} repos.txt not found at: ${REPOS_TXT}"
|
|
exit 1
|
|
fi
|
|
|
|
REPOS=()
|
|
while IFS= read -r line; do
|
|
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
[[ -z "${line// }" ]] && continue
|
|
REPOS+=("$line")
|
|
done < "$REPOS_TXT"
|
|
info "Base directory: ${BASE_DIR}"
|
|
info "Repos to process: ${#REPOS[@]}"
|
|
$DRY_RUN && warn "DRY RUN — no files will be written or committed"
|
|
|
|
for REPO in "${REPOS[@]}"; do
|
|
header "$REPO"
|
|
REPO_DIR="${BASE_DIR}/${REPO}"
|
|
|
|
if [[ ! -d "$REPO_DIR" ]]; then
|
|
warn "Directory not found at ${REPO_DIR} — skipping"
|
|
continue
|
|
fi
|
|
|
|
if ! set_meta "$REPO"; then
|
|
continue
|
|
fi
|
|
|
|
if [[ ! -f "${REPO_DIR}/AGENTS.md" ]]; then
|
|
warn "AGENTS.md not found in ${REPO} — skipping (run manually to bootstrap)"
|
|
continue
|
|
fi
|
|
|
|
if $DRY_RUN; then
|
|
info "Would generate agent docs for ${NAME} (${ID})"
|
|
info " build: ${BUILD_VFY}"
|
|
continue
|
|
fi
|
|
|
|
# .editorconfig — always overwrite (identical across all repos)
|
|
write_editorconfig "${REPO_DIR}/.editorconfig"
|
|
ok ".editorconfig"
|
|
|
|
# .cursorrules — always overwrite
|
|
write_cursorrules "${REPO_DIR}/.cursorrules" "$REPO"
|
|
ok ".cursorrules"
|
|
|
|
# .windsurfrules — always overwrite
|
|
write_windsurfrules "${REPO_DIR}/.windsurfrules" "$REPO"
|
|
ok ".windsurfrules"
|
|
|
|
# .clinerules — always overwrite
|
|
write_clinerules "${REPO_DIR}/.clinerules" "$REPO"
|
|
ok ".clinerules"
|
|
|
|
# .aider.conf.yml — always overwrite
|
|
write_aider_conf "${REPO_DIR}/.aider.conf.yml"
|
|
ok ".aider.conf.yml"
|
|
|
|
# .github/copilot-instructions.md — always overwrite
|
|
write_copilot_instructions "${REPO_DIR}/.github" "$REPO"
|
|
ok ".github/copilot-instructions.md"
|
|
|
|
# CLAUDE.md — create only if missing
|
|
if [[ ! -f "${REPO_DIR}/CLAUDE.md" ]]; then
|
|
write_claude_placeholder "${REPO_DIR}/CLAUDE.md" "$REPO"
|
|
ok "CLAUDE.md (created — was missing)"
|
|
else
|
|
info "CLAUDE.md exists — skipping (hand-crafted; delete to regenerate)"
|
|
fi
|
|
|
|
# Commit if there are any changes in this repo
|
|
if git -C "$REPO_DIR" status --porcelain 2>/dev/null | grep -q .; then
|
|
git -C "$REPO_DIR" add \
|
|
.editorconfig .cursorrules .windsurfrules .clinerules \
|
|
.aider.conf.yml CLAUDE.md .github/copilot-instructions.md \
|
|
2>/dev/null || true
|
|
git -C "$REPO_DIR" commit -m "chore(docs): regenerate AI agent config files" \
|
|
--no-verify 2>/dev/null || true
|
|
ok "Committed changes in ${REPO}"
|
|
CHANGED_REPOS+=("$REPO")
|
|
else
|
|
info "No changes in ${REPO}"
|
|
fi
|
|
done
|
|
|
|
# ── summary ──────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
if [[ ${#CHANGED_REPOS[@]} -gt 0 ]]; then
|
|
ok "Updated and committed ${#CHANGED_REPOS[@]} repo(s):"
|
|
for r in "${CHANGED_REPOS[@]}"; do
|
|
echo " • $r"
|
|
done
|
|
echo ""
|
|
info "Push with:"
|
|
for r in "${CHANGED_REPOS[@]}"; do
|
|
echo " git -C ${BASE_DIR}/${r} push"
|
|
done
|
|
else
|
|
ok "All repos already up-to-date — no changes."
|
|
fi
|