Skip to content

Conversation

@fgrehm
Copy link
Contributor

@fgrehm fgrehm commented Oct 24, 2025

Summary

Fixes two bugs where exclude_inherited_files in profile config was ignored, causing excluded standards to still be processed.

Details

Both bugs used pipes that created subshells where excluded="true" didn't persist:

  • Bug 1: Subshell variable scope in get_profile_files() - exclusions ignored when generating Claude Code Skills
  • Bug 2: Missing exclusion check in get_profile_file() - files from current profile returned without checking exclusions

Fix: Replace pipes with process substitution and add exclusion check before returning files from current profile.

Linked item

Checklist

  • Linked to related Issue/Discussion
  • Documented steps to test (below)
  • Drafted "how to use" docs (if this adds new behavior) - N/A, bug fix only
  • Backwards compatibility considered (notes if applicable) - Fully backwards compatible, fixes existing functionality

Documented steps to test

  1. Create a profile that excludes standards:

    # profiles/test-profile/profile-config.yml
    inherits_from: default
    exclude_inherited_files:
      - standards/backend/*
      - standards/frontend/*
  2. Install the profile with Skills mode enabled:

    ~/agent-os/scripts/project-install.sh --profile test-profile \
      --standards-as-claude-code-skills true --dry-run
  3. Verify output does NOT include backend/frontend skills:

    # Should NOT see:
    # .claude/skills/backend-*/SKILL.md
    # .claude/skills/frontend-*/SKILL.md
    
    # Should only see skills for included standards
  4. Without the fix, backend/frontend skills are incorrectly created. With the fix, they are properly excluded.

Notes for reviewers

File changed: scripts/common-functions.sh (27 insertions, 9 deletions)

Changes made:

  1. get_profile_files() function - Fixed subshell bug:
-                echo "$excluded_patterns" | while read pattern; do
+                while read pattern; do
                     if [[ -n "$pattern" ]] && match_pattern "$relative_path" "$pattern"; then
                         excluded="true"
                         break
                     fi
-                done
+                done <<< "$excluded_patterns"
  1. get_profile_file() function - Added exclusion check before returning files from current profile:
 # Check if file exists in current profile
 if [[ -f "$full_path" ]]; then
+    # Check if this file is excluded (even in current profile)
+    if [[ -f "$profile_config" ]]; then
+        local excluded="false"
+        while read pattern; do
+            if [[ -n "$pattern" ]] && match_pattern "$file_path" "$pattern"; then
+                excluded="true"
+                break
+            fi
+        done < <(get_yaml_array "$profile_config" "exclude_inherited_files")
+
+        if [[ "$excluded" == "true" ]]; then
+            echo ""
+            return
+        fi
+    fi
     echo "$full_path"
     return
 fi
  1. get_profile_file() function - Also fixed subshell bug in inheritance exclusion check (same pattern as 1.)

Technical notes:

  • Pipes create subshells, so variable assignments don't persist. Process substitution (< <(...) or <<< "$var") keeps the loop in the current shell.
  • Previously, files in the current profile were returned without checking exclusions - now they're checked regardless of location.

Testing: Verified with a profile that excludes backend and frontend standards - confirmed excluded skills are not created and excluded files are not copied.

Impact: Low risk - fixes broken functionality, no behavior change for profiles without exclusions.

…ndling

Fix two bugs where exclude_inherited_files was ignored, causing excluded
standards to still be processed.

Bug 1: Subshell variable scope in get_profile_files()
When generating Claude Code Skills, exclusions were ignored because pipe
created a subshell where excluded="true" didn't persist.

Bug 2: Missing exclusion check in get_profile_file()
Files from current profile were returned without checking exclusions -
only inherited files were checked.

Root Cause:
Both functions used pipes that created subshells:
  echo "$patterns" | while read pattern; do
    excluded="true"  # Doesn't persist outside subshell!
  done

Solution:
1. Replace pipes with process substitution to fix variable scope
2. Add exclusion check before returning files from current profile

Changes:
- get_profile_files(): Fixed subshell bug (done <<< "$var")
- get_profile_file(): Added exclusion check for current profile files
- get_profile_file(): Fixed subshell bug in inheritance check (< <(...))

Impact:
Profiles with exclusions now correctly exclude those standards from both
file copying and Skills generation, regardless of file location.

Testing:
Verified with profile excluding backend/frontend standards - confirmed
excluded files are not copied and excluded skills are not created.

Fixes: buildermethods#240
@smaugho
Copy link

smaugho commented Oct 25, 2025

I had no luck with this solution, but after a lot of debugging, realized the problem was with bash running on Windows, for this to work here, I had to remove carriage return in the get_yaml_array()

                if (indent == array_indent) {
                    sub(/^-[[:space:]]*/, "")
                    # Remove quotes if present
                    gsub(/^["'\'']/, "")
                    gsub(/["'\'']$/, "")
                    <<added this
                    # Remove carriage returns (Windows line endings)
                    gsub(/\r/, "")
                    >>
                    print
                }

@CasJam CasJam merged commit f7f9ce9 into buildermethods:main Oct 28, 2025
@CasJam
Copy link
Contributor

CasJam commented Oct 28, 2025

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants