diff --git a/.claude/commands/speckit.clarify.md b/.claude/commands/speckit.clarify.md index 6b28dae..2961f50 100644 --- a/.claude/commands/speckit.clarify.md +++ b/.claude/commands/speckit.clarify.md @@ -1,6 +1,6 @@ --- description: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarification questions and encoding answers back into the spec. -handoffs: +handoffs: - label: Build Technical Plan agent: speckit.plan prompt: Create a plan for the spec. I am building with... diff --git a/.claude/commands/speckit.constitution.md b/.claude/commands/speckit.constitution.md index 1830264..885ac1b 100644 --- a/.claude/commands/speckit.constitution.md +++ b/.claude/commands/speckit.constitution.md @@ -1,6 +1,6 @@ --- description: Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync. -handoffs: +handoffs: - label: Build Specification agent: speckit.specify prompt: Implement the feature specification based on the updated constitution. I want to build... diff --git a/.claude/commands/speckit.implement.md b/.claude/commands/speckit.implement.md index 41da7b9..bbea031 100644 --- a/.claude/commands/speckit.implement.md +++ b/.claude/commands/speckit.implement.md @@ -105,7 +105,7 @@ You **MUST** consider the user input before proceeding (if not empty). 6. Execute implementation following the task plan: - **Phase-by-phase execution**: Complete each phase before moving to the next - - **Respect dependencies**: Run sequential tasks in order, parallel tasks [P] can run together + - **Respect dependencies**: Run sequential tasks in order, parallel tasks [P] can run together - **Follow TDD approach**: Execute test tasks before their corresponding implementation tasks - **File-based coordination**: Tasks affecting the same files must run sequentially - **Validation checkpoints**: Verify each phase completion before proceeding diff --git a/.claude/commands/speckit.plan.md b/.claude/commands/speckit.plan.md index e9e5599..f5e4f6d 100644 --- a/.claude/commands/speckit.plan.md +++ b/.claude/commands/speckit.plan.md @@ -1,6 +1,6 @@ --- description: Execute the implementation planning workflow using the plan template to generate design artifacts. -handoffs: +handoffs: - label: Create Tasks agent: speckit.tasks prompt: Break the plan into tasks diff --git a/.claude/commands/speckit.specify.md b/.claude/commands/speckit.specify.md index 4d45a4a..1216ffb 100644 --- a/.claude/commands/speckit.specify.md +++ b/.claude/commands/speckit.specify.md @@ -1,6 +1,6 @@ --- description: Create or update the feature specification from a natural language feature description. -handoffs: +handoffs: - label: Build Technical Plan agent: speckit.plan prompt: Create a plan for the spec. I am building with... @@ -37,27 +37,27 @@ Given that feature description, do this: - "Fix payment processing timeout bug" → "fix-payment-timeout" 2. **Check for existing branches before creating new one**: - + a. First, fetch all remote branches to ensure we have the latest information: ```bash git fetch --all --prune ``` - + b. Find the highest feature number across all sources for the short-name: - Remote branches: `git ls-remote --heads origin | grep -E 'refs/heads/[0-9]+-$'` - Local branches: `git branch | grep -E '^[* ]*[0-9]+-$'` - Specs directories: Check for directories matching `specs/[0-9]+-` - + c. Determine the next available number: - Extract all numbers from all three sources - Find the highest number N - Use N+1 for the new branch number - + d. Run the script `.specify/scripts/bash/create-new-feature.sh --json "$ARGUMENTS"` with the calculated number and short-name: - Pass `--number N+1` and `--short-name "your-short-name"` along with the feature description - Bash example: `.specify/scripts/bash/create-new-feature.sh --json "$ARGUMENTS" --json --number 5 --short-name "user-auth" "Add user authentication"` - PowerShell example: `.specify/scripts/bash/create-new-feature.sh --json "$ARGUMENTS" -Json -Number 5 -ShortName "user-auth" "Add user authentication"` - + **IMPORTANT**: - Check all three sources (remote branches, local branches, specs directories) to find the highest number - Only match branches/directories with the exact short-name pattern @@ -103,20 +103,20 @@ Given that feature description, do this: ```markdown # Specification Quality Checklist: [FEATURE NAME] - + **Purpose**: Validate specification completeness and quality before proceeding to planning **Created**: [DATE] **Feature**: [Link to spec.md] - + ## Content Quality - + - [ ] No implementation details (languages, frameworks, APIs) - [ ] Focused on user value and business needs - [ ] Written for non-technical stakeholders - [ ] All mandatory sections completed - + ## Requirement Completeness - + - [ ] No [NEEDS CLARIFICATION] markers remain - [ ] Requirements are testable and unambiguous - [ ] Success criteria are measurable @@ -125,16 +125,16 @@ Given that feature description, do this: - [ ] Edge cases are identified - [ ] Scope is clearly bounded - [ ] Dependencies and assumptions identified - + ## Feature Readiness - + - [ ] All functional requirements have clear acceptance criteria - [ ] User scenarios cover primary flows - [ ] Feature meets measurable outcomes defined in Success Criteria - [ ] No implementation details leak into specification - + ## Notes - + - Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan` ``` @@ -159,20 +159,20 @@ Given that feature description, do this: ```markdown ## Question [N]: [Topic] - + **Context**: [Quote relevant spec section] - + **What we need to know**: [Specific question from NEEDS CLARIFICATION marker] - + **Suggested Answers**: - + | Option | Answer | Implications | |--------|--------|--------------| | A | [First suggested answer] | [What this means for the feature] | | B | [Second suggested answer] | [What this means for the feature] | | C | [Third suggested answer] | [What this means for the feature] | | Custom | Provide your own answer | [Explain how to provide custom input] | - + **Your choice**: _[Wait for user response]_ ``` diff --git a/.claude/commands/speckit.tasks.md b/.claude/commands/speckit.tasks.md index dbe228b..4cb6a8d 100644 --- a/.claude/commands/speckit.tasks.md +++ b/.claude/commands/speckit.tasks.md @@ -1,6 +1,6 @@ --- description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts. -handoffs: +handoffs: - label: Analyze For Consistency agent: speckit.analyze prompt: Run a project analysis for consistency @@ -86,7 +86,7 @@ Every task MUST strictly follow this format: 4. **[Story] label**: REQUIRED for user story phase tasks only - Format: [US1], [US2], [US3], etc. (maps to user stories from spec.md) - Setup phase: NO story label - - Foundational phase: NO story label + - Foundational phase: NO story label - User Story phases: MUST have story label - Polish phase: NO story label 5. **Description**: Clear action with exact file path diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7665a12..afc0ad5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,4 +22,3 @@ "onCreateCommand": "bash .devcontainer/post-install.sh" } - diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 412cef9..d2d6008 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -47,4 +47,3 @@ jobs: # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://docs.claude.com/en/docs/claude-code/cli-reference for available options # claude_args: '--allowed-tools Bash(gh pr:*)' - diff --git a/.github/workflows/release-helm.yaml b/.github/workflows/release-helm.yaml index 2e75c3d..90dcd49 100644 --- a/.github/workflows/release-helm.yaml +++ b/.github/workflows/release-helm.yaml @@ -64,4 +64,4 @@ jobs: chart_version: ${{ steps.extract_version.outputs.version }} linting: on commit_username: github-actions[bot] - commit_email: github-actions[bot]@users.noreply.github.com \ No newline at end of file + commit_email: github-actions[bot]@users.noreply.github.com diff --git a/.specify/scripts/bash/check-prerequisites.sh b/.specify/scripts/bash/check-prerequisites.sh index 98e387c..1f7759c 100755 --- a/.specify/scripts/bash/check-prerequisites.sh +++ b/.specify/scripts/bash/check-prerequisites.sh @@ -57,13 +57,13 @@ OPTIONS: EXAMPLES: # Check task prerequisites (plan.md required) ./check-prerequisites.sh --json - + # Check implementation prerequisites (plan.md + tasks.md required) ./check-prerequisites.sh --json --require-tasks --include-tasks - + # Get feature paths only (no validation) ./check-prerequisites.sh --paths-only - + EOF exit 0 ;; @@ -147,19 +147,19 @@ if $JSON_MODE; then json_docs=$(printf '"%s",' "${docs[@]}") json_docs="[${json_docs%,}]" fi - + printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs" else # Text output echo "FEATURE_DIR:$FEATURE_DIR" echo "AVAILABLE_DOCS:" - + # Show status of each potential document check_file "$RESEARCH" "research.md" check_file "$DATA_MODEL" "data-model.md" check_dir "$CONTRACTS_DIR" "contracts/" check_file "$QUICKSTART" "quickstart.md" - + if $INCLUDE_TASKS; then check_file "$TASKS" "tasks.md" fi diff --git a/.specify/scripts/bash/common.sh b/.specify/scripts/bash/common.sh index 2c3165e..7b6fcba 100755 --- a/.specify/scripts/bash/common.sh +++ b/.specify/scripts/bash/common.sh @@ -153,4 +153,3 @@ EOF check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; } check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; } - diff --git a/.specify/scripts/bash/create-new-feature.sh b/.specify/scripts/bash/create-new-feature.sh index 592dab2..7f2de95 100755 --- a/.specify/scripts/bash/create-new-feature.sh +++ b/.specify/scripts/bash/create-new-feature.sh @@ -10,8 +10,8 @@ i=1 while [ $i -le $# ]; do arg="${!i}" case "$arg" in - --json) - JSON_MODE=true + --json) + JSON_MODE=true ;; --short-name) if [ $((i + 1)) -gt $# ]; then @@ -40,7 +40,7 @@ while [ $i -le $# ]; do fi BRANCH_NUMBER="$next_arg" ;; - --help|-h) + --help|-h) echo "Usage: $0 [--json] [--short-name ] [--number N] " echo "" echo "Options:" @@ -54,8 +54,8 @@ while [ $i -le $# ]; do echo " $0 'Implement OAuth2 integration for API' --number 5" exit 0 ;; - *) - ARGS+=("$arg") + *) + ARGS+=("$arg") ;; esac i=$((i + 1)) @@ -84,7 +84,7 @@ find_repo_root() { get_highest_from_specs() { local specs_dir="$1" local highest=0 - + if [ -d "$specs_dir" ]; then for dir in "$specs_dir"/*; do [ -d "$dir" ] || continue @@ -96,22 +96,22 @@ get_highest_from_specs() { fi done fi - + echo "$highest" } # Function to get highest number from git branches get_highest_from_branches() { local highest=0 - + # Get all branches (local and remote) branches=$(git branch -a 2>/dev/null || echo "") - + if [ -n "$branches" ]; then while IFS= read -r branch; do # Clean branch name: remove leading markers and remote prefixes clean_branch=$(echo "$branch" | sed 's/^[* ]*//; s|^remotes/[^/]*/||') - + # Extract feature number if branch matches pattern ###-* if echo "$clean_branch" | grep -q '^[0-9]\{3\}-'; then number=$(echo "$clean_branch" | grep -o '^[0-9]\{3\}' || echo "0") @@ -122,7 +122,7 @@ get_highest_from_branches() { fi done <<< "$branches" fi - + echo "$highest" } @@ -130,22 +130,22 @@ get_highest_from_branches() { check_existing_branches() { local short_name="$1" local specs_dir="$2" - + # Fetch all remotes to get latest branch info (suppress errors if no remotes) git fetch --all --prune 2>/dev/null || true - + # Find all branches matching the pattern using git ls-remote (more reliable) local remote_branches=$(git ls-remote --heads origin 2>/dev/null | grep -E "refs/heads/[0-9]+-${short_name}$" | sed 's/.*\/\([0-9]*\)-.*/\1/' | sort -n) - + # Also check local branches local local_branches=$(git branch 2>/dev/null | grep -E "^[* ]*[0-9]+-${short_name}$" | sed 's/^[* ]*//' | sed 's/-.*//' | sort -n) - + # Check specs directory as well local spec_dirs="" if [ -d "$specs_dir" ]; then spec_dirs=$(find "$specs_dir" -maxdepth 1 -type d -name "[0-9]*-${short_name}" 2>/dev/null | xargs -n1 basename 2>/dev/null | sed 's/-.*//' | sort -n) fi - + # Combine all sources and get the highest number local max_num=0 for num in $remote_branches $local_branches $spec_dirs; do @@ -153,7 +153,7 @@ check_existing_branches() { max_num=$num fi done - + # Return next number echo $((max_num + 1)) } @@ -189,19 +189,19 @@ mkdir -p "$SPECS_DIR" # Function to generate branch name with stop word filtering and length filtering generate_branch_name() { local description="$1" - + # Common stop words to filter out local stop_words="^(i|a|an|the|to|for|of|in|on|at|by|with|from|is|are|was|were|be|been|being|have|has|had|do|does|did|will|would|should|could|can|may|might|must|shall|this|that|these|those|my|your|our|their|want|need|add|get|set)$" - + # Convert to lowercase and split into words local clean_name=$(echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g') - + # Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original) local meaningful_words=() for word in $clean_name; do # Skip empty words [ -z "$word" ] && continue - + # Keep words that are NOT stop words AND (length >= 3 OR are potential acronyms) if ! echo "$word" | grep -qiE "$stop_words"; then if [ ${#word} -ge 3 ]; then @@ -212,12 +212,12 @@ generate_branch_name() { fi fi done - + # If we have meaningful words, use first 3-4 of them if [ ${#meaningful_words[@]} -gt 0 ]; then local max_words=3 if [ ${#meaningful_words[@]} -eq 4 ]; then max_words=4; fi - + local result="" local count=0 for word in "${meaningful_words[@]}"; do @@ -265,15 +265,15 @@ if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then # Calculate how much we need to trim from suffix # Account for: feature number (3) + hyphen (1) = 4 chars MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4)) - + # Truncate suffix at word boundary if possible TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH) # Remove trailing hyphen if truncation created one TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//') - + ORIGINAL_BRANCH_NAME="$BRANCH_NAME" BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}" - + >&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit" >&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)" >&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)" diff --git a/.specify/scripts/bash/setup-plan.sh b/.specify/scripts/bash/setup-plan.sh index d01c6d6..7e23de4 100755 --- a/.specify/scripts/bash/setup-plan.sh +++ b/.specify/scripts/bash/setup-plan.sh @@ -8,17 +8,17 @@ ARGS=() for arg in "$@"; do case "$arg" in - --json) - JSON_MODE=true + --json) + JSON_MODE=true ;; - --help|-h) + --help|-h) echo "Usage: $0 [--json]" echo " --json Output results in JSON format" echo " --help Show this help message" - exit 0 + exit 0 ;; - *) - ARGS+=("$arg") + *) + ARGS+=("$arg") ;; esac done @@ -53,9 +53,8 @@ if $JSON_MODE; then "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT" else echo "FEATURE_SPEC: $FEATURE_SPEC" - echo "IMPL_PLAN: $IMPL_PLAN" + echo "IMPL_PLAN: $IMPL_PLAN" echo "SPECS_DIR: $FEATURE_DIR" echo "BRANCH: $CURRENT_BRANCH" echo "HAS_GIT: $HAS_GIT" fi - diff --git a/.specify/scripts/bash/update-agent-context.sh b/.specify/scripts/bash/update-agent-context.sh index e0aa1de..74449cd 100755 --- a/.specify/scripts/bash/update-agent-context.sh +++ b/.specify/scripts/bash/update-agent-context.sh @@ -2,7 +2,7 @@ # Update agent context files with information from plan.md # -# This script maintains AI agent context files by parsing feature specifications +# This script maintains AI agent context files by parsing feature specifications # and updating agent-specific configuration files with project information. # # MAIN FUNCTIONS: @@ -58,7 +58,7 @@ eval $(get_feature_paths) NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code AGENT_TYPE="${1:-}" -# Agent-specific file paths +# Agent-specific file paths CLAUDE_FILE="$REPO_ROOT/CLAUDE.md" GEMINI_FILE="$REPO_ROOT/GEMINI.md" COPILOT_FILE="$REPO_ROOT/.github/agents/copilot-instructions.md" @@ -129,7 +129,7 @@ validate_environment() { fi exit 1 fi - + # Check if plan.md exists if [[ ! -f "$NEW_PLAN" ]]; then log_error "No plan.md found at $NEW_PLAN" @@ -139,7 +139,7 @@ validate_environment() { fi exit 1 fi - + # Check if template exists (needed for new files) if [[ ! -f "$TEMPLATE_FILE" ]]; then log_warning "Template file not found at $TEMPLATE_FILE" @@ -154,7 +154,7 @@ validate_environment() { extract_plan_field() { local field_pattern="$1" local plan_file="$2" - + grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \ head -1 | \ sed "s|^\*\*${field_pattern}\*\*: ||" | \ @@ -165,39 +165,39 @@ extract_plan_field() { parse_plan_data() { local plan_file="$1" - + if [[ ! -f "$plan_file" ]]; then log_error "Plan file not found: $plan_file" return 1 fi - + if [[ ! -r "$plan_file" ]]; then log_error "Plan file is not readable: $plan_file" return 1 fi - + log_info "Parsing plan data from $plan_file" - + NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file") NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file") NEW_DB=$(extract_plan_field "Storage" "$plan_file") NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file") - + # Log what we found if [[ -n "$NEW_LANG" ]]; then log_info "Found language: $NEW_LANG" else log_warning "No language information found in plan" fi - + if [[ -n "$NEW_FRAMEWORK" ]]; then log_info "Found framework: $NEW_FRAMEWORK" fi - + if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then log_info "Found database: $NEW_DB" fi - + if [[ -n "$NEW_PROJECT_TYPE" ]]; then log_info "Found project type: $NEW_PROJECT_TYPE" fi @@ -207,11 +207,11 @@ format_technology_stack() { local lang="$1" local framework="$2" local parts=() - + # Add non-empty parts [[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang") [[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework") - + # Join with proper formatting if [[ ${#parts[@]} -eq 0 ]]; then echo "" @@ -233,7 +233,7 @@ format_technology_stack() { get_project_structure() { local project_type="$1" - + if [[ "$project_type" == *"web"* ]]; then echo "backend/\\nfrontend/\\ntests/" else @@ -243,7 +243,7 @@ get_project_structure() { get_commands_for_language() { local lang="$1" - + case "$lang" in *"Python"*) echo "cd src && pytest && ruff check ." @@ -270,40 +270,40 @@ create_new_agent_file() { local temp_file="$2" local project_name="$3" local current_date="$4" - + if [[ ! -f "$TEMPLATE_FILE" ]]; then log_error "Template not found at $TEMPLATE_FILE" return 1 fi - + if [[ ! -r "$TEMPLATE_FILE" ]]; then log_error "Template file is not readable: $TEMPLATE_FILE" return 1 fi - + log_info "Creating new agent context file from template..." - + if ! cp "$TEMPLATE_FILE" "$temp_file"; then log_error "Failed to copy template file" return 1 fi - + # Replace template placeholders local project_structure project_structure=$(get_project_structure "$NEW_PROJECT_TYPE") - + local commands commands=$(get_commands_for_language "$NEW_LANG") - + local language_conventions language_conventions=$(get_language_conventions "$NEW_LANG") - + # Perform substitutions with error checking using safer approach # Escape special characters for sed by using a different delimiter or escaping local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g') local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g') local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g') - + # Build technology stack and recent change strings conditionally local tech_stack if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then @@ -336,7 +336,7 @@ create_new_agent_file() { "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|" "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|" ) - + for substitution in "${substitutions[@]}"; do if ! sed -i.bak -e "$substitution" "$temp_file"; then log_error "Failed to perform substitution: $substitution" @@ -344,14 +344,14 @@ create_new_agent_file() { return 1 fi done - + # Convert \n sequences to actual newlines newline=$(printf '\n') sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file" - + # Clean up backup files rm -f "$temp_file.bak" "$temp_file.bak2" - + return 0 } @@ -361,49 +361,49 @@ create_new_agent_file() { update_existing_agent_file() { local target_file="$1" local current_date="$2" - + log_info "Updating existing agent context file..." - + # Use a single temporary file for atomic update local temp_file temp_file=$(mktemp) || { log_error "Failed to create temporary file" return 1 } - + # Process the file in one pass local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK") local new_tech_entries=() local new_change_entry="" - + # Prepare new technology entries if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)") fi - + if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)") fi - + # Prepare new change entry if [[ -n "$tech_stack" ]]; then new_change_entry="- $CURRENT_BRANCH: Added $tech_stack" elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB" fi - + # Check if sections exist in the file local has_active_technologies=0 local has_recent_changes=0 - + if grep -q "^## Active Technologies" "$target_file" 2>/dev/null; then has_active_technologies=1 fi - + if grep -q "^## Recent Changes" "$target_file" 2>/dev/null; then has_recent_changes=1 fi - + # Process file line by line local in_tech_section=false local in_changes_section=false @@ -411,7 +411,7 @@ update_existing_agent_file() { local changes_entries_added=false local existing_changes_count=0 local file_ended=false - + while IFS= read -r line || [[ -n "$line" ]]; do # Handle Active Technologies section if [[ "$line" == "## Active Technologies" ]]; then @@ -436,7 +436,7 @@ update_existing_agent_file() { echo "$line" >> "$temp_file" continue fi - + # Handle Recent Changes section if [[ "$line" == "## Recent Changes" ]]; then echo "$line" >> "$temp_file" @@ -459,7 +459,7 @@ update_existing_agent_file() { fi continue fi - + # Update timestamp if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file" @@ -467,13 +467,13 @@ update_existing_agent_file() { echo "$line" >> "$temp_file" fi done < "$target_file" - + # Post-loop check: if we're still in the Active Technologies section and haven't added new entries if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" tech_entries_added=true fi - + # If sections don't exist, add them at the end of the file if [[ $has_active_technologies -eq 0 ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then echo "" >> "$temp_file" @@ -481,21 +481,21 @@ update_existing_agent_file() { printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file" tech_entries_added=true fi - + if [[ $has_recent_changes -eq 0 ]] && [[ -n "$new_change_entry" ]]; then echo "" >> "$temp_file" echo "## Recent Changes" >> "$temp_file" echo "$new_change_entry" >> "$temp_file" changes_entries_added=true fi - + # Move temp file to target atomically if ! mv "$temp_file" "$target_file"; then log_error "Failed to update target file" rm -f "$temp_file" return 1 fi - + return 0 } #============================================================================== @@ -505,19 +505,19 @@ update_existing_agent_file() { update_agent_file() { local target_file="$1" local agent_name="$2" - + if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then log_error "update_agent_file requires target_file and agent_name parameters" return 1 fi - + log_info "Updating $agent_name context file: $target_file" - + local project_name project_name=$(basename "$REPO_ROOT") local current_date current_date=$(date +%Y-%m-%d) - + # Create directory if it doesn't exist local target_dir target_dir=$(dirname "$target_file") @@ -527,7 +527,7 @@ update_agent_file() { return 1 fi fi - + if [[ ! -f "$target_file" ]]; then # Create new file from template local temp_file @@ -535,7 +535,7 @@ update_agent_file() { log_error "Failed to create temporary file" return 1 } - + if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then if mv "$temp_file" "$target_file"; then log_success "Created new $agent_name context file" @@ -555,12 +555,12 @@ update_agent_file() { log_error "Cannot read existing file: $target_file" return 1 fi - + if [[ ! -w "$target_file" ]]; then log_error "Cannot write to existing file: $target_file" return 1 fi - + if update_existing_agent_file "$target_file" "$current_date"; then log_success "Updated existing $agent_name context file" else @@ -568,7 +568,7 @@ update_agent_file() { return 1 fi fi - + return 0 } @@ -578,7 +578,7 @@ update_agent_file() { update_specific_agent() { local agent_type="$1" - + case "$agent_type" in claude) update_agent_file "$CLAUDE_FILE" "Claude Code" @@ -635,43 +635,43 @@ update_specific_agent() { update_all_existing_agents() { local found_agent=false - + # Check each possible agent file and update if it exists if [[ -f "$CLAUDE_FILE" ]]; then update_agent_file "$CLAUDE_FILE" "Claude Code" found_agent=true fi - + if [[ -f "$GEMINI_FILE" ]]; then update_agent_file "$GEMINI_FILE" "Gemini CLI" found_agent=true fi - + if [[ -f "$COPILOT_FILE" ]]; then update_agent_file "$COPILOT_FILE" "GitHub Copilot" found_agent=true fi - + if [[ -f "$CURSOR_FILE" ]]; then update_agent_file "$CURSOR_FILE" "Cursor IDE" found_agent=true fi - + if [[ -f "$QWEN_FILE" ]]; then update_agent_file "$QWEN_FILE" "Qwen Code" found_agent=true fi - + if [[ -f "$AGENTS_FILE" ]]; then update_agent_file "$AGENTS_FILE" "Codex/opencode" found_agent=true fi - + if [[ -f "$WINDSURF_FILE" ]]; then update_agent_file "$WINDSURF_FILE" "Windsurf" found_agent=true fi - + if [[ -f "$KILOCODE_FILE" ]]; then update_agent_file "$KILOCODE_FILE" "Kilo Code" found_agent=true @@ -681,7 +681,7 @@ update_all_existing_agents() { update_agent_file "$AUGGIE_FILE" "Auggie CLI" found_agent=true fi - + if [[ -f "$ROO_FILE" ]]; then update_agent_file "$ROO_FILE" "Roo Code" found_agent=true @@ -701,7 +701,7 @@ update_all_existing_agents() { update_agent_file "$Q_FILE" "Amazon Q Developer CLI" found_agent=true fi - + # If no agent files exist, create a default Claude file if [[ "$found_agent" == false ]]; then log_info "No existing agent files found, creating default Claude file..." @@ -711,19 +711,19 @@ update_all_existing_agents() { print_summary() { echo log_info "Summary of changes:" - + if [[ -n "$NEW_LANG" ]]; then echo " - Added language: $NEW_LANG" fi - + if [[ -n "$NEW_FRAMEWORK" ]]; then echo " - Added framework: $NEW_FRAMEWORK" fi - + if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then echo " - Added database: $NEW_DB" fi - + echo log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|codebuddy|shai|q]" @@ -736,18 +736,18 @@ print_summary() { main() { # Validate environment before proceeding validate_environment - + log_info "=== Updating agent context files for feature $CURRENT_BRANCH ===" - + # Parse the plan file to extract project information if ! parse_plan_data "$NEW_PLAN"; then log_error "Failed to parse plan data" exit 1 fi - + # Process based on agent type argument local success=true - + if [[ -z "$AGENT_TYPE" ]]; then # No specific agent provided - update all existing agent files log_info "No agent specified, updating all existing agent files..." @@ -761,10 +761,10 @@ main() { success=false fi fi - + # Print summary print_summary - + if [[ "$success" == true ]]; then log_success "Agent context update completed successfully" exit 0 @@ -778,4 +778,3 @@ main() { if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi - diff --git a/.specify/templates/checklist-template.md b/.specify/templates/checklist-template.md index 806657d..0caeacf 100644 --- a/.specify/templates/checklist-template.md +++ b/.specify/templates/checklist-template.md @@ -6,16 +6,16 @@ **Note**: This checklist is generated by the `/speckit.checklist` command based on feature context and requirements. - diff --git a/.specify/templates/plan-template.md b/.specify/templates/plan-template.md index 6a8bfc6..5ac33c0 100644 --- a/.specify/templates/plan-template.md +++ b/.specify/templates/plan-template.md @@ -17,14 +17,14 @@ the iteration process. --> -**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION] -**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION] -**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A] -**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION] +**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION] +**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION] +**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A] +**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION] **Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION] -**Project Type**: [single/web/mobile - determines source structure] -**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION] -**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION] +**Project Type**: [single/web/mobile - determines source structure] +**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION] +**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION] **Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION] ## Constitution Check diff --git a/.specify/templates/spec-template.md b/.specify/templates/spec-template.md index c67d914..db6bdb2 100644 --- a/.specify/templates/spec-template.md +++ b/.specify/templates/spec-template.md @@ -1,8 +1,8 @@ # Feature Specification: [FEATURE NAME] -**Feature Branch**: `[###-feature-name]` -**Created**: [DATE] -**Status**: Draft +**Feature Branch**: `[###-feature-name]` +**Created**: [DATE] +**Status**: Draft **Input**: User description: "$ARGUMENTS" ## User Scenarios & Testing *(mandatory)* @@ -11,7 +11,7 @@ IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance. Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them, you should still have a viable MVP (Minimum Viable Product) that delivers value. - + Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical. Think of each story as a standalone slice of functionality that can be: - Developed independently @@ -85,7 +85,7 @@ ### Functional Requirements - **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"] -- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"] +- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"] - **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"] - **FR-004**: System MUST [data requirement, e.g., "persist user preferences"] - **FR-005**: System MUST [behavior, e.g., "log all security events"] diff --git a/.specify/templates/tasks-template.md b/.specify/templates/tasks-template.md index 60f9be4..8accc1d 100644 --- a/.specify/templates/tasks-template.md +++ b/.specify/templates/tasks-template.md @@ -25,21 +25,21 @@ description: "Task list template for feature implementation" - **Mobile**: `api/src/`, `ios/src/` or `android/src/` - Paths shown below assume single project - adjust based on plan.md structure - diff --git a/hack/commit-hash.sh b/hack/commit-hash.sh index 1943402..f3bf931 100755 --- a/hack/commit-hash.sh +++ b/hack/commit-hash.sh @@ -5,6 +5,6 @@ set -euxo pipefail HASH=$(git rev-parse --short HEAD) if [[ $(git status --porcelain) ]]; then HASH=${HASH}-dirty -fi +fi echo $HASH diff --git a/hack/install-setup-envtest.sh b/hack/install-setup-envtest.sh index 867ac87..4c95b3a 100644 --- a/hack/install-setup-envtest.sh +++ b/hack/install-setup-envtest.sh @@ -9,4 +9,4 @@ then go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest else echo 'setup-envtest is already installed' -fi \ No newline at end of file +fi diff --git a/hack/update-kubernetes-library.sh b/hack/update-kubernetes-library.sh index 8bc6704..47f754f 100755 --- a/hack/update-kubernetes-library.sh +++ b/hack/update-kubernetes-library.sh @@ -42,4 +42,4 @@ for MOD in "${MODS[@]}"; do done go get "k8s.io/kubernetes@v${VERSION}" -go mod tidy \ No newline at end of file +go mod tidy diff --git a/prek.toml b/prek.toml new file mode 100644 index 0000000..e422afa --- /dev/null +++ b/prek.toml @@ -0,0 +1,16 @@ +[[repos]] +repo = "https://github.com/pre-commit/pre-commit-hooks" +rev = "v6.0.0" +hooks = [ + { id = "trailing-whitespace" }, + { id = "end-of-file-fixer" }, + { id = "check-yaml", args = ["--allow-multiple-documents"], exclude = "^helm/" }, + { id = "check-added-large-files" }, +] + +[[repos]] +repo = "https://github.com/golangci/golangci-lint" +rev = "v2.10.1" +hooks = [ + { id = "golangci-lint" }, +] diff --git a/specs/001-selfhost-supabase-operator/contracts/supabaseproject-crd.yaml b/specs/001-selfhost-supabase-operator/contracts/supabaseproject-crd.yaml index 5297130..207fe60 100644 --- a/specs/001-selfhost-supabase-operator/contracts/supabaseproject-crd.yaml +++ b/specs/001-selfhost-supabase-operator/contracts/supabaseproject-crd.yaml @@ -526,4 +526,4 @@ spec: kind: SupabaseProject shortNames: - sbp - - supabase \ No newline at end of file + - supabase diff --git a/specs/001-selfhost-supabase-operator/data-model.md b/specs/001-selfhost-supabase-operator/data-model.md index 963c11f..fbcc2be 100644 --- a/specs/001-selfhost-supabase-operator/data-model.md +++ b/specs/001-selfhost-supabase-operator/data-model.md @@ -411,4 +411,4 @@ meta: requests: memory: "64Mi" cpu: "50m" -``` \ No newline at end of file +``` diff --git a/specs/001-selfhost-supabase-operator/design-decisions.md b/specs/001-selfhost-supabase-operator/design-decisions.md index ab85bd9..8e9bb72 100644 --- a/specs/001-selfhost-supabase-operator/design-decisions.md +++ b/specs/001-selfhost-supabase-operator/design-decisions.md @@ -101,4 +101,4 @@ 2. Implement CRD types with kubebuilder markers 3. Create controller with resource defaulting logic 4. Implement secret validation in webhook -5. Write integration tests with envtest \ No newline at end of file +5. Write integration tests with envtest diff --git a/specs/001-selfhost-supabase-operator/future-considerations.md b/specs/001-selfhost-supabase-operator/future-considerations.md index 4585fcf..9358911 100644 --- a/specs/001-selfhost-supabase-operator/future-considerations.md +++ b/specs/001-selfhost-supabase-operator/future-considerations.md @@ -240,4 +240,4 @@ For each deferred decision: --- *Last Updated*: 2025-10-03 -*Review Frequency*: Quarterly after v1alpha1 release \ No newline at end of file +*Review Frequency*: Quarterly after v1alpha1 release diff --git a/specs/001-selfhost-supabase-operator/plan.md b/specs/001-selfhost-supabase-operator/plan.md index 31d363b..b8a8be7 100644 --- a/specs/001-selfhost-supabase-operator/plan.md +++ b/specs/001-selfhost-supabase-operator/plan.md @@ -193,8 +193,8 @@ Samples are documented inline in quickstart; no repository samples directory. ## Phase 3+: Future Implementation *These phases are beyond the scope of the /plan command* -**Phase 3**: Task execution (/tasks command creates tasks.md) -**Phase 4**: Implementation (execute tasks.md following constitutional principles) +**Phase 3**: Task execution (/tasks command creates tasks.md) +**Phase 4**: Implementation (execute tasks.md following constitutional principles) **Phase 5**: Validation (run tests, execute quickstart.md, performance validation) ## Complexity Tracking diff --git a/specs/001-selfhost-supabase-operator/research-references.md b/specs/001-selfhost-supabase-operator/research-references.md index bfb8a5a..a7be1b7 100644 --- a/specs/001-selfhost-supabase-operator/research-references.md +++ b/specs/001-selfhost-supabase-operator/research-references.md @@ -132,4 +132,4 @@ func (r *SupabaseProjectReconciler) Reconcile(ctx context.Context, req ctrl.Requ - [ ] Implement similar phase progression logic - [ ] Adopt Rook's component status tracking approach - [ ] Use Rook's event emission patterns -- [ ] Follow Rook's testing strategies with envtest \ No newline at end of file +- [ ] Follow Rook's testing strategies with envtest diff --git a/specs/001-selfhost-supabase-operator/research.md b/specs/001-selfhost-supabase-operator/research.md index 547ef67..dcf1b32 100644 --- a/specs/001-selfhost-supabase-operator/research.md +++ b/specs/001-selfhost-supabase-operator/research.md @@ -200,4 +200,4 @@ 2. Update components in dependency order 3. Verify health after each update 4. Keep failed state for investigation (no automatic rollback) -5. Allow manual intervention or reconciliation retry \ No newline at end of file +5. Allow manual intervention or reconciliation retry diff --git a/specs/001-selfhost-supabase-operator/spec.md b/specs/001-selfhost-supabase-operator/spec.md index aa7cd1a..123c2be 100644 --- a/specs/001-selfhost-supabase-operator/spec.md +++ b/specs/001-selfhost-supabase-operator/spec.md @@ -102,4 +102,3 @@ As a platform administrator, I want to deploy multiple isolated Supabase instanc - [x] Success criteria are measurable - [x] Scope is clearly bounded - [x] Dependencies and assumptions identified - diff --git a/specs/002-helm-chart-release/checklists/requirements.md b/specs/002-helm-chart-release/checklists/requirements.md index 5568ada..4aea695 100644 --- a/specs/002-helm-chart-release/checklists/requirements.md +++ b/specs/002-helm-chart-release/checklists/requirements.md @@ -34,4 +34,4 @@ - All checklist items pass validation - The specification is complete and ready for planning phase - No clarifications needed from the user -- The feature scope is well-defined with clear boundaries \ No newline at end of file +- The feature scope is well-defined with clear boundaries diff --git a/specs/002-helm-chart-release/contracts/chart-metadata.yaml b/specs/002-helm-chart-release/contracts/chart-metadata.yaml index d5e5618..6f8ea77 100644 --- a/specs/002-helm-chart-release/contracts/chart-metadata.yaml +++ b/specs/002-helm-chart-release/contracts/chart-metadata.yaml @@ -83,4 +83,4 @@ annotations: # 3. annotations.artifacthub.io/changes SHOULD be updated with changelog # File Encoding: UTF-8 -# Line Endings: LF (Unix-style) \ No newline at end of file +# Line Endings: LF (Unix-style) diff --git a/specs/002-helm-chart-release/contracts/github-workflow.yaml b/specs/002-helm-chart-release/contracts/github-workflow.yaml index 975ff10..f62113e 100644 --- a/specs/002-helm-chart-release/contracts/github-workflow.yaml +++ b/specs/002-helm-chart-release/contracts/github-workflow.yaml @@ -107,4 +107,4 @@ jobs: # - Workflow stops immediately # - No partial release # - No notification sent (per spec) -# - Failure visible in GitHub Actions UI \ No newline at end of file +# - Failure visible in GitHub Actions UI diff --git a/specs/002-helm-chart-release/contracts/helm-repository-index.yaml b/specs/002-helm-chart-release/contracts/helm-repository-index.yaml index d567036..633a459 100644 --- a/specs/002-helm-chart-release/contracts/helm-repository-index.yaml +++ b/specs/002-helm-chart-release/contracts/helm-repository-index.yaml @@ -92,4 +92,4 @@ entries: # helm repo index . --url https://helm.strrl.dev # Update Command (preserving existing entries): -# helm repo index . --url https://helm.strrl.dev --merge index.yaml \ No newline at end of file +# helm repo index . --url https://helm.strrl.dev --merge index.yaml diff --git a/specs/002-helm-chart-release/data-model.md b/specs/002-helm-chart-release/data-model.md index 7a10ab3..a669690 100644 --- a/specs/002-helm-chart-release/data-model.md +++ b/specs/002-helm-chart-release/data-model.md @@ -174,4 +174,4 @@ graph TD 2. **Signing metadata**: Add GPG signature fields 3. **Approval workflow**: Add approval state before publishing 4. **Rollback tracking**: Track rollback operations -5. **Dependency graph**: Model chart dependencies \ No newline at end of file +5. **Dependency graph**: Model chart dependencies diff --git a/specs/002-helm-chart-release/plan.md b/specs/002-helm-chart-release/plan.md index 73867d8..6950fda 100644 --- a/specs/002-helm-chart-release/plan.md +++ b/specs/002-helm-chart-release/plan.md @@ -95,4 +95,4 @@ charts/ > **Fill ONLY if Constitution Check has violations that must be justified** -*No violations - section not applicable* \ No newline at end of file +*No violations - section not applicable* diff --git a/specs/002-helm-chart-release/quickstart.md b/specs/002-helm-chart-release/quickstart.md index 3ec3664..130cded 100644 --- a/specs/002-helm-chart-release/quickstart.md +++ b/specs/002-helm-chart-release/quickstart.md @@ -243,4 +243,4 @@ helm upgrade my-supabase supabase-operator/supabase-operator \ - [Workflow File](.github/workflows/release-helm.yaml) - [Chart Repository](https://helm.strrl.dev) - [GitHub Actions Runs](https://github.com/STRRL/supabase-operator/actions) -- [Helm Documentation](https://helm.sh/docs/) \ No newline at end of file +- [Helm Documentation](https://helm.sh/docs/) diff --git a/specs/002-helm-chart-release/research.md b/specs/002-helm-chart-release/research.md index 2fb704b..22ee0f9 100644 --- a/specs/002-helm-chart-release/research.md +++ b/specs/002-helm-chart-release/research.md @@ -148,4 +148,4 @@ supabase-operator-0.2.0.tgz - [stefanprodan/helm-gh-pages documentation](https://github.com/stefanprodan/helm-gh-pages) - [Helm Chart Repository Guide](https://helm.sh/docs/topics/chart_repository/) - [GitHub Actions workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) -- [Reference workflow](https://github.com/STRRL/cloudflare-tunnel-ingress-controller/blob/master/.github/workflows/release-helm.yaml) \ No newline at end of file +- [Reference workflow](https://github.com/STRRL/cloudflare-tunnel-ingress-controller/blob/master/.github/workflows/release-helm.yaml) diff --git a/specs/002-helm-chart-release/spec.md b/specs/002-helm-chart-release/spec.md index d30f2a6..3b5885c 100644 --- a/specs/002-helm-chart-release/spec.md +++ b/specs/002-helm-chart-release/spec.md @@ -107,4 +107,4 @@ As a potential user, I want to discover available Helm charts, understand their - **SC-004**: Chart repository maintains 99.9% availability for chart downloads - **SC-005**: All published charts pass validation checks without errors - **SC-006**: Chart upgrades complete successfully 95% of the time without manual intervention -- **SC-007**: Repository index updates reflect new versions within 1 minute of publishing \ No newline at end of file +- **SC-007**: Repository index updates reflect new versions within 1 minute of publishing diff --git a/specs/002-helm-chart-release/tasks.md b/specs/002-helm-chart-release/tasks.md index 8b3354e..1de97c7 100644 --- a/specs/002-helm-chart-release/tasks.md +++ b/specs/002-helm-chart-release/tasks.md @@ -230,4 +230,4 @@ With multiple developers: - Each user story is independently testable - Commit after each task completion - Test workflow with incremental tags (v0.0.1-test, v0.0.2-test) -- No operator code changes required - purely CI/CD configuration \ No newline at end of file +- No operator code changes required - purely CI/CD configuration