Skip to content

feat(config): set default value for exclude to List()#781

Merged
jdx merged 2 commits intojdx:mainfrom
timothysparg:feat/config-exclude-default
Apr 1, 2026
Merged

feat(config): set default value for exclude to List()#781
jdx merged 2 commits intojdx:mainfrom
timothysparg:feat/config-exclude-default

Conversation

@timothysparg
Copy link
Copy Markdown
Contributor

@timothysparg timothysparg commented Mar 29, 2026

This PR improves the developer experience of extending file exclusions in hk.pkl.

By changing the default value of exclude from null to an empty List() in the Pkl schema, we eliminate the need for unwieldy null-checks when concatenating lists.

Currently, to safely extend an exclusion list without knowing if the builtin provides one, you must use the null-coalescing operator:

// Current way 
["actionlint"] = (Builtins.actionlint) {
    exclude = (Builtins.actionlint.exclude ?? List()) + List("**/ignored-dir/**")
}

With this change, exclude is guaranteed to not be null.

// New way
["actionlint"] = (Builtins.actionlint) {
   exclude = Builtins.actionlint.exclude + List("**/ignored-dir/**")
}

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request changes the 'exclude' field in 'pkl/Config.pkl' from an optional type to a non-optional type with a default empty list. A critical issue was identified where this change breaks the configuration merging logic in 'src/config.rs', as the field will now always be populated, preventing the intended fallback to user-level 'hkrc' settings.

Comment thread pkl/Config.pkl Outdated
/// - Can be overridden per-step with `<STEP>.exclude`
/// - Regex patterns use Rust regex syntax and match against full file paths
exclude: (String | List<String> | Regex)?
exclude: (String | List<String> | Regex) = List()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This change from an optional type to a non-optional type with a default List() value introduces a subtle bug in the configuration merging logic for hkrc files.

In src/config.rs, the merge_from_hkrc function merges the project configuration with a user-level hkrc configuration. The logic for the exclude field is:

self.exclude = self.exclude.take().or(hkrc.exclude);

This logic is intended to use the hkrc value only if the project configuration's exclude is not set (i.e., is None).

With your change, exclude will now always be Some(List()) when not specified in hk.pkl, instead of None. As a result, self.exclude.take() will always return Some(List()), and the hkrc.exclude value will be ignored. This effectively breaks the fallback to the user's global configuration for this setting.

To fix this, the merge logic in src/config.rs needs to be updated to correctly handle this new default value, for example by treating an empty list as "not set" for merging purposes. A broader fix would be to review all settings that have been made non-optional with default values and adjust their merge logic accordingly.

@timothysparg timothysparg marked this pull request as draft March 29, 2026 12:23
@timothysparg timothysparg force-pushed the feat/config-exclude-default branch from aab3b79 to b7f937b Compare March 29, 2026 12:54
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@timothysparg timothysparg force-pushed the feat/config-exclude-default branch from 027f7d1 to 2464229 Compare March 29, 2026 20:33
@timothysparg timothysparg marked this pull request as ready for review March 29, 2026 21:57
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 29, 2026

Greptile Summary

This PR improves the developer experience when extending exclusion patterns by changing exclude in the Pkl schema from a nullable optional ((String | List<String> | Regex)?) to a non-nullable field with a default empty list (= List()). The Rust side is updated consistently to treat Some(Pattern::Globs(vec![])) — the deserialized form of List() — as equivalent to no exclusion, via the new Pattern::is_empty() method used in both has_filters() and filter_files().

Key changes:

  • pkl/Config.pkl: exclude now defaults to List() instead of implicitly null, removing the need for ?? List() null-coalescing when concatenating exclude lists.
  • src/step/types.rs: New Pattern::is_empty() returns true for an empty Globs vector and always false for Regex patterns.
  • src/step/batching.rs: has_filters() updated to ignore an empty Pattern::Globs so a step with the default empty exclude is not treated as filter-active.
  • src/step/filtering.rs: filter_files() skips exclude processing when the pattern is empty, avoiding a no-op glob match pass.

Confidence Score: 5/5

This PR is safe to merge; the changes are minimal, well-scoped, and logically consistent across the Pkl schema and Rust runtime.

No P0 or P1 issues found. The is_empty() method is correctly implemented and applied in all relevant call sites. The Pkl default of List() serializes to [], which Rust deserializes as Some(Pattern::Globs(vec![])), and the new guards handle that correctly.

No files require special attention.

Important Files Changed

Filename Overview
pkl/Config.pkl Changes exclude field from nullable optional to non-nullable with an empty List() default, enabling list concatenation without null-coalescing operators.
src/step/types.rs Adds is_empty() method to Pattern enum that returns true for an empty Globs vector and always false for Regex patterns.
src/step/batching.rs Updates has_filters() to treat Some(Pattern::Globs(vec![])) as no filter, preventing an empty default exclude from being counted as an active filter.
src/step/filtering.rs Updates filter_files() to skip exclude processing when the pattern is empty, correctly handling the new List() default from the Pkl schema.

Reviews (2): Last reviewed commit: "Merge branch 'main' into feat/config-exc..." | Re-trigger Greptile

Comment thread src/step/types.rs
Comment on lines +38 to +43
pub fn is_empty(&self) -> bool {
match self {
Pattern::Regex { .. } => false,
Pattern::Globs(globs) => globs.is_empty(),
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 is_empty silently passes a single-element empty-string glob

is_empty() checks whether the Globs vector itself is empty, but a glob of "" — which Pkl allows via exclude = "" — would produce Pattern::Globs(vec!["".to_string()]). That is a one-element vector, so is_empty() returns false, and the empty-string glob is passed through to get_pattern_matches. An empty string glob matches every path in most glob implementations, meaning all files would effectively be excluded.

This edge case existed before this PR, but the new is_empty() method is the right place to guard against it. Consider also treating globs that are all-empty strings as "empty":

pub fn is_empty(&self) -> bool {
    match self {
        Pattern::Regex { .. } => false,
        Pattern::Globs(globs) => globs.iter().all(|g| g.is_empty()),
    }
}

This is a minor defensive improvement; the primary use-case (List() → empty vec) is handled correctly.

@jdx jdx merged commit 795d579 into jdx:main Apr 1, 2026
18 checks passed
@jdx jdx mentioned this pull request Apr 1, 2026
jdx added a commit that referenced this pull request Apr 1, 2026
### 🚀 Features

- **(betterleaks)** add betterleaks config to hk builtin config by
[@hituzi-no-sippo](https://github.com/hituzi-no-sippo) in
[#750](#750)
- **(builtins)** add google-java-format to builtins by
[@timothysparg](https://github.com/timothysparg) in
[#777](#777)
- **(builtins)** add dclint to builtins by
[@timothysparg](https://github.com/timothysparg) in
[#779](#779)
- **(config)** set default value for exclude to List() by
[@timothysparg](https://github.com/timothysparg) in
[#781](#781)
- **(core)** add required field to prevent unconfigured steps from
running by [@timothysparg](https://github.com/timothysparg) in
[#785](#785)
- **(gitleaks)** add gitleaks config to hk builtin config by
[@hituzi-no-sippo](https://github.com/hituzi-no-sippo) in
[#749](#749)
- **(mdschema)** add mdschema config to hk builtin config by
[@hituzi-no-sippo](https://github.com/hituzi-no-sippo) in
[#748](#748)
- **(pkl)** add pklr as opt-in pkl backend by
[@jdx](https://github.com/jdx) in
[#769](#769)
- add pklr as opt-in pkl backend by [@jdx](https://github.com/jdx) in
[#768](#768)

### 🐛 Bug Fixes

- **(docs)** replace invalid /latest/ pkl package URIs with versioned
format by [@jdx](https://github.com/jdx) in
[#770](#770)
- **(stage)** do not stage pre-existing untracked files by
[@jdx](https://github.com/jdx) in
[#788](#788)

### 📚 Documentation

- add benchmarks page and reproducible benchmark suite by
[@jdx](https://github.com/jdx) in
[#766](#766)
- add recommended setup section to mise integration by
[@timothysparg](https://github.com/timothysparg) in
[#780](#780)

### 📦️ Dependency Updates

- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#762](#762)
- update rust crate pklr to 0.4 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#776](#776)
- update apple-actions/import-codesign-certs digest to fe74d46 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#774](#774)
- update anthropics/claude-code-action digest to 094bd24 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#773](#773)
- update taiki-e/upload-rust-binary-action digest to 0e34102 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#775](#775)
- bump usage to 3.2.0 and pkl to 0.31.1, add windows platforms by
[@jdx](https://github.com/jdx) in
[#787](#787)
- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#786](#786)

### New Contributors

- @timothysparg made their first contribution in
[#781](#781)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily a version/documentation bump, but it also updates the Rust
dependency lockfile (e.g., `hyper` and `windows-sys`), which could
introduce build/runtime regressions.
> 
> **Overview**
> Bumps hk to **v1.40.0** and publishes the corresponding release notes
in `CHANGELOG.md`.
> 
> Updates generated CLI/docs and all Pkl package URL references in
docs/examples to point at `v1.40.0`, and refreshes `Cargo.lock` with
dependency updates/removals consistent with the new release.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
da00ab8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <123107610+mise-en-dev@users.noreply.github.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Apr 2, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [hk](https://github.com/jdx/hk) | minor | `1.39.0` → `1.40.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/hk (hk)</summary>

### [`v1.40.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1400---2026-04-01)

[Compare Source](jdx/hk@v1.39.0...v1.40.0)

##### 🚀 Features

- **(betterleaks)** add betterleaks config to hk builtin config by [@&#8203;hituzi-no-sippo](https://github.com/hituzi-no-sippo) in [#&#8203;750](jdx/hk#750)
- **(builtins)** add google-java-format to builtins by [@&#8203;timothysparg](https://github.com/timothysparg) in [#&#8203;777](jdx/hk#777)
- **(builtins)** add dclint to builtins by [@&#8203;timothysparg](https://github.com/timothysparg) in [#&#8203;779](jdx/hk#779)
- **(config)** set default value for exclude to List() by [@&#8203;timothysparg](https://github.com/timothysparg) in [#&#8203;781](jdx/hk#781)
- **(core)** add required field to prevent unconfigured steps from running by [@&#8203;timothysparg](https://github.com/timothysparg) in [#&#8203;785](jdx/hk#785)
- **(gitleaks)** add gitleaks config to hk builtin config by [@&#8203;hituzi-no-sippo](https://github.com/hituzi-no-sippo) in [#&#8203;749](jdx/hk#749)
- **(mdschema)** add mdschema config to hk builtin config by [@&#8203;hituzi-no-sippo](https://github.com/hituzi-no-sippo) in [#&#8203;748](jdx/hk#748)
- **(pkl)** add pklr as opt-in pkl backend by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;769](jdx/hk#769)
- add pklr as opt-in pkl backend by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;768](jdx/hk#768)

##### 🐛 Bug Fixes

- **(docs)** replace invalid /latest/ pkl package URIs with versioned format by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;770](jdx/hk#770)
- **(stage)** do not stage pre-existing untracked files by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;788](jdx/hk#788)

##### 📚 Documentation

- add benchmarks page and reproducible benchmark suite by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;766](jdx/hk#766)
- add recommended setup section to mise integration by [@&#8203;timothysparg](https://github.com/timothysparg) in [#&#8203;780](jdx/hk#780)

##### 📦️ Dependency Updates

- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;762](jdx/hk#762)
- update rust crate pklr to 0.4 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;776](jdx/hk#776)
- update apple-actions/import-codesign-certs digest to [`fe74d46`](jdx/hk@fe74d46) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;774](jdx/hk#774)
- update anthropics/claude-code-action digest to [`094bd24`](jdx/hk@094bd24) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;773](jdx/hk#773)
- update taiki-e/upload-rust-binary-action digest to [`0e34102`](jdx/hk@0e34102) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;775](jdx/hk#775)
- bump usage to 3.2.0 and pkl to 0.31.1, add windows platforms by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;787](jdx/hk#787)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;786](jdx/hk#786)

##### New Contributors

- [@&#8203;timothysparg](https://github.com/timothysparg) made their first contribution in [#&#8203;781](jdx/hk#781)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ1cGRhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIlJlbm92YXRlIEJvdCIsImF1dG9tYXRpb246Ym90LWF1dGhvcmVkIiwiZGVwZW5kZW5jeS10eXBlOjptaW5vciJdfQ==-->
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.

2 participants