diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f8dde19633..be3caa784c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 with: - python-version: "3.13" + python-version: "3.14" - name: Run ruff check run: uvx ruff check src/ @@ -30,8 +30,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, windows-latest] - python-version: ["3.11", "3.12", "3.13"] + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.13", "3.14"] steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/extensions/agent-context/scripts/bash/update-agent-context.sh b/extensions/agent-context/scripts/bash/update-agent-context.sh index c3e5c2020e..b7121a2f64 100755 --- a/extensions/agent-context/scripts/bash/update-agent-context.sh +++ b/extensions/agent-context/scripts/bash/update-agent-context.sh @@ -59,6 +59,13 @@ case "$(uname -s 2>/dev/null || true)" in esac # Parse extension config once; emit context files as JSON, followed by marker strings. +# +# NOTE (bash 3.2 / macOS portability): the embedded Python heredocs below run +# inside $(...) command substitution. bash 3.2 (the system /bin/bash on macOS) +# mis-parses a single-quote/apostrophe in a heredoc body nested in $(...), +# failing with "unexpected EOF while looking for matching `''". Keep these +# $(...)-nested heredoc bodies free of apostrophes (use double quotes in Python +# string literals and avoid contractions in comments). if ! _raw_opts="$("$_python" - "$EXT_CONFIG" "$_case_insensitive_context_files" "$PROJECT_ROOT" <<'PY' import json import sys @@ -113,11 +120,11 @@ if isinstance(raw_files, list): if not context_files: add_context_file(get_str(data, "context_file")) if not context_files: - # Self-seed: the agent-context extension owns its lifecycle, so when its - # own config declares no target it derives one from the active integration - # recorded in init-options.json, using the extension's OWN bundled mapping - # (agent-context-defaults.json). This is independent of the Specify CLI by - # design — nothing here imports specify_cli. + # Self-seed: the agent-context extension manages its own lifecycle, so when + # its config declares no target, it derives one from the active integration + # recorded in init-options.json, mapped through the bundled + # agent-context-defaults.json file. This is independent of the Specify CLI + # by design; nothing here imports specify_cli. project_root = sys.argv[3] if len(sys.argv) > 3 else "." integration_key = "" try: @@ -144,7 +151,7 @@ if not context_files: except Exception: print( "agent-context: unable to read %s; cannot self-seed the context " - "file. Set 'context_file' in the extension config." % defaults_path, + "file. Set context_file in the extension config." % defaults_path, file=sys.stderr, ) mapping = {} @@ -152,7 +159,7 @@ if not context_files: if not context_files: print( "agent-context: no default context file is known for integration " - "'%s'. Set 'context_file' in the extension config to choose one." + "%s. Set context_file in the extension config to choose one." % integration_key, file=sys.stderr, ) diff --git a/extensions/git/scripts/bash/create-new-feature-branch.sh b/extensions/git/scripts/bash/create-new-feature-branch.sh index d638b048c9..a13e49812c 100755 --- a/extensions/git/scripts/bash/create-new-feature-branch.sh +++ b/extensions/git/scripts/bash/create-new-feature-branch.sh @@ -288,7 +288,7 @@ generate_branch_name() { if ! echo "$word" | grep -qiE "$stop_words"; then if [ ${#word} -ge 3 ]; then meaningful_words+=("$word") - elif echo "$description" | grep -qw -- "${word^^}"; then + elif printf '%s' "$description" | grep -qw -- "$(printf '%s' "$word" | tr '[:lower:]' '[:upper:]')"; then meaningful_words+=("$word") fi fi diff --git a/scripts/bash/create-new-feature.sh b/scripts/bash/create-new-feature.sh index c9609764f7..746e88a2dc 100644 --- a/scripts/bash/create-new-feature.sh +++ b/scripts/bash/create-new-feature.sh @@ -152,7 +152,7 @@ generate_branch_name() { if ! echo "$word" | grep -qiE "$stop_words"; then if [ ${#word} -ge 3 ]; then meaningful_words+=("$word") - elif echo "$description" | grep -q "\b${word^^}\b"; then + elif printf '%s' "$description" | grep -qw -- "$(printf '%s' "$word" | tr '[:lower:]' '[:upper:]')"; then # Keep short words if they appear as uppercase in original (likely acronyms) meaningful_words+=("$word") fi