Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/agents/knowledge/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,24 @@ Template scopes:
- `Files` — invoked once with all matched files (`{FILES}`)
- `Project` — invoked once with no file args; skipped
entirely if no matching files changed

## Baseline Expansion

Normal changed-file runs keep each check scoped to changed files. Before
execution, `src/main.rs` also computes a set of checks that need a full file
list to establish a new baseline.

A check is expanded to all matching files when:

- it was not active at the merge base, meaning its tool was newly added to
`mise.toml`
- its resolved tool version changed in `mise.toml`
- its registered `.linter_config(...)` file changed under `FLINT_CONFIG_DIR`
- `flint.toml` changed under `[settings]`
- `flint.toml` changed the check-specific section for a special check

This is per-check. Unaffected checks still receive the normal changed-file list.
Explicit `--full` bypasses this selection because every check is already using
the all-files list. Config-change triggers use the raw git change list before
`settings.exclude` is applied, so excluded config paths still expand the affected
check.
6 changes: 3 additions & 3 deletions default.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
{
"matchPackageNames": [
"actionlint",
"biome",
"cargo:yaml-lint",
"cargo:xmloxide",
"editorconfig-checker",
"github:google/google-java-format",
Expand All @@ -46,12 +48,10 @@
"golangci-lint",
"hadolint",
"lychee",
"npm:@biomejs/biome",
"npm:markdownlint-cli2",
"npm:prettier",
"npm:renovate",
"pipx:codespell",
"pipx:ruff",
"rumdl",
"shellcheck",
"shfmt"
],
Expand Down
25 changes: 25 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,31 @@ Every flag has an env var equivalent: `FLINT_FIX`, `FLINT_FULL`, `FLINT_FAST_ONL
| Pre-push hook (CC / agentic) | `flint run --fix --fast-only` | Fixes what it can silently, surfaces only what needs human review |
| CI | `flint run` | Full output for humans reading CI logs |

## Changed-file and baseline runs

By default, `flint run` checks only files changed relative to the merge base.
Use `--full` to check every matching file explicitly.

Some changed-file runs intentionally expand one or more affected checks to all
matching files. This establishes a baseline when lint coverage changes, while
leaving unrelated checks scoped to changed files.

A check runs against all matching files when:

- the check is newly active because its tool was added to `mise.toml`
- the check's tool version changed in `mise.toml`
- the check's flint-managed config file changed, such as `.shellcheckrc` or
`.yamllint.yml` in `FLINT_CONFIG_DIR`
- `flint.toml` changed under `[settings]`
- `flint.toml` changed the check-specific config for a special check, such as
`[checks.links]` or `[checks.renovate-deps]`

`--full` is still the explicit whole-repo mode. The automatic baseline behavior
only applies in changed-file mode, and only to checks whose lint coverage may
have changed. Config-file triggers are detected from the raw git change list, so
they still apply when the config path itself is excluded from ordinary lint file
selection.

**`--short` output** — failed checks partitioned by fixability, fixable ones
expressed as the exact command to run:

Expand Down
28 changes: 20 additions & 8 deletions src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const BUILTIN_EXCLUDES: &[&str] = COMMITTED_PATHS;
#[derive(Clone)]
pub struct FileList {
pub files: Vec<PathBuf>,
/// Changed paths from git before user excludes are applied.
pub changed_paths: Vec<String>,
/// The merge base ref, used by project-scoped checks (e.g. golangci-lint).
pub merge_base: Option<String>,
/// True when the file list contains all project files (explicit --full or no merge base).
Expand All @@ -29,21 +31,26 @@ pub fn changed(
let exclude = build_exclude_set(cfg);

if full {
return all_files(project_root, &exclude);
return all(project_root, cfg);
}

let merge_base = resolve_merge_base(project_root, cfg, from_ref)?;

let files = if let Some(ref base) = merge_base {
let (files, changed_paths) = if let Some(ref base) = merge_base {
let to = to_ref.unwrap_or("HEAD");
collect_changed_files(project_root, &exclude, base, to)?
let names = collect_changed_names(project_root, base, to)?;
(
filter_names(project_root, &exclude, names.clone()),
names.into_iter().collect(),
)
} else {
// No merge base (shallow clone etc.) — fall back to all files.
return all_files(project_root, &exclude);
return all(project_root, cfg);
};

Ok(FileList {
files,
changed_paths,
merge_base,
full: false,
})
Expand Down Expand Up @@ -88,12 +95,11 @@ fn resolve_merge_base(
Ok(None)
}

fn collect_changed_files(
fn collect_changed_names(
project_root: &Path,
exclude: &GlobSet,
base: &str,
to: &str,
) -> Result<Vec<PathBuf>> {
) -> Result<std::collections::BTreeSet<String>> {
let range = format!("{base}...{to}");
let mut names: std::collections::BTreeSet<String> = Default::default();

Expand All @@ -110,7 +116,12 @@ fn collect_changed_files(
names.insert(line);
}

Ok(filter_names(project_root, exclude, names))
Ok(names)
}

pub fn all(project_root: &Path, cfg: &Config) -> Result<FileList> {
let exclude = build_exclude_set(cfg);
all_files(project_root, &exclude)
}

fn all_files(project_root: &Path, exclude: &GlobSet) -> Result<FileList> {
Expand All @@ -132,6 +143,7 @@ fn all_files(project_root: &Path, exclude: &GlobSet) -> Result<FileList> {

Ok(FileList {
files: filter_names(project_root, exclude, names),
changed_paths: vec![],
merge_base: None,
full: true,
})
Expand Down
1 change: 1 addition & 0 deletions src/linters/renovate_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ mod tests {
fn file_list(paths: &[&str], full: bool) -> FileList {
FileList {
files: paths.iter().map(PathBuf::from).collect(),
changed_paths: paths.iter().map(|path| path.to_string()).collect(),
merge_base: Some("base".to_string()),
full,
}
Expand Down
Loading
Loading