Skip to content

Update license header template to remove year#3122

Merged
dlwh merged 11 commits intomainfrom
codex/license-header-2026
Mar 4, 2026
Merged

Update license header template to remove year#3122
dlwh merged 11 commits intomainfrom
codex/license-header-2026

Conversation

@dlwh
Copy link
Copy Markdown
Member

@dlwh dlwh commented Feb 28, 2026

Summary

  • remove the year from Marin, Levanter, and Haliax license header templates
  • migrate existing Python file headers repo-wide from yearful to yearless format
  • simplify infra/pre-commit.py license checks to enforce only the yearless header format
  • merge latest origin/main into this branch

Validation

  • run ./infra/pre-commit.py --all-files (passes)

Notes

  • this is a mechanical, comment-only migration across 1411 files

@dlwh dlwh added the agent-generated Created by automation/agent label Feb 28, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 28, 2026

Claude finished @dlwh's task in 4m 59s —— View job


Review: PR #3122

  • Gather context and read changed files
  • Check PR diff against stated objectives
  • Review for correctness and behavioral regressions
  • Post final review

Despite the title, this PR bundles license header year bumps (2025 -> 2026) with a major restructuring of the Grug subsystem: migrating the trainer from lib/levanter/src/levanter/grug/ to experiments/grug/base/, deleting the GrugWrapper adapter, replacing the old speedrun, refactoring callbacks and eval for non-Trainer consumers, and rewriting grug documentation. The license header portion is trivially correct.

Specification check

No linked spec or issue. The PR exceeds ~500 lines of code changes. Per docs/recipes/agent-coding.md, a specification is expected for changes of this scope.

Findings

Lost test coverage for levanter.grug shared primitives -- The tests in lib/levanter/tests/grug/ (test_grugformer_core.py, test_grugformer_compilation.py, test_grugformer.py, test_grugformer_fused_loss.py, test_grugformer_model_loss.py) are all deleted. The new tests/test_grug_base_template.py adds 3 replacement tests (train step, run-with-metrics, abstract-mesh lowering), but several previously-covered areas now have zero test coverage:

  • AttentionMask materialization (causal, sliding window, segment IDs) -- exercises still-present levanter.grug.attention
  • Blocksparse attention reference comparison
  • Parameter sharding spec validation (levanter.grug.sharding)
  • Fused loss correctness tests
  • full_like sharding preservation

These primitives remain in the codebase as shared library code and are actively imported by the new template.

License header year inconsistency -- The templates are bumped to 2026, but every new source file added in this PR (experiments/grug/__init__.py, experiments/grug/base/__init__.py, launch.py, model.py, train.py, state_adapter.py) carries Copyright 2025. Pre-commit will rewrite these on next touch, which is consistent with the PR description ("headers will migrate as files are touched"), but it is somewhat odd that files being created fresh in this PR don't use the new year.

@dlwh dlwh force-pushed the codex/license-header-2026 branch from 730bfc3 to 8b4ecd3 Compare February 28, 2026 04:23
@dlwh
Copy link
Copy Markdown
Member Author

dlwh commented Feb 28, 2026

@claude please look again and lmk if you can think of a better workaround. ideally we wouldn't migrate everything all at once

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 28, 2026

Claude finished @dlwh's task in 2m 55s —— View job


Re-reviewing license header migration approach

  • Read the changed files and understand the current approach
  • Analyze the pre-commit license header logic
  • Think through alternative workarounds for gradual migration
  • Post findings

🤖 I re-read the PR in its current state (just the 4 license/pre-commit files — my earlier review was stale). The approach looks solid to me. Here's my analysis:

How the current approach works

The key insight is ALLOW_LEGACY_LICENSE_HEADERS = all_files:

Invocation ALLOW_LEGACY_LICENSE_HEADERS Behavior on 2025 headers
Git pre-commit hook (--fix, staged files) False Migrates 2025 → 2026
make fix (--fix, modified files) False Migrates 2025 → 2026
make lint / CI (--all-files) True Accepts 2025, no failure
--all-files --fix (CLAUDE.md agents) True Accepts 2025, no migration

This is exactly "migrate as files are touched" — staged/modified files get their headers updated on commit, while full-repo scans don't fail or mass-rewrite.

Could we do better?

I considered a few alternatives:

  1. Separate --allow-legacy-headers flag — More explicit, but adds surface area for no real benefit since all_files is a reliable proxy for "full scan, don't require current year."

  2. Regex-based year matching (accept any \d{4}) — Simpler (no _template_with_previous_year needed), but loses the guarantee that really stale headers (e.g. 2020) get caught. The N-1 limit is actually a feature.

  3. Accept legacy for validation but always fix with --fix — This would make --all-files --fix do a mass migration, which is the opposite of the goal.

Verdict

I don't think there's a meaningfully better workaround. The current design is clean:

  • _template_with_previous_year is self-contained and only tolerates N-1 (so headers can't drift indefinitely)
  • The fix logic correctly does an in-place year swap (line 272-273) rather than prepending a duplicate header
  • The ALLOW_LEGACY_LICENSE_HEADERS = all_files coupling matches the actual usage patterns in Makefile and CI
  • Next year you just bump the template to 2027 and the code automatically accepts 2026 as legacy

One minor note: if a file has a blank line between its shebang and header (e.g. #!/usr/bin/env python\n\n# Copyright...), the fix path would prepend a new header rather than swapping — but that's a pre-existing edge case from before this PR, not something introduced here.

LGTM as-is. 👍


View job

@rjpower
Copy link
Copy Markdown
Collaborator

rjpower commented Mar 1, 2026

Let's just remove the date entirely? Year of creation is trivially available via the repo history already...

@dlwh dlwh changed the title Update license header templates to 2026 Update license header template to remove year Mar 2, 2026
…2026

# Conflicts:
#	lib/iris/tests/cluster/test_pickle_version_mismatch.py
#	lib/levanter/scripts/bench/bench_fused_cross_entropy_loss_pallas.py
#	lib/levanter/scripts/tune/tune_fused_cross_entropy_loss_block_sizes.py
#	lib/levanter/src/levanter/kernels/pallas/fused_cross_entropy_loss/api.py
#	lib/levanter/src/levanter/kernels/pallas/fused_cross_entropy_loss/pallas_tpu.py
#	lib/levanter/src/levanter/kernels/pallas/fused_cross_entropy_loss/tuned_block_sizes.py
#	lib/levanter/tests/kernels/test_pallas_fused_cross_entropy_loss.py
#	tests/test_grug_base_template.py
@dlwh dlwh merged commit e986875 into main Mar 4, 2026
18 checks passed
@dlwh dlwh deleted the codex/license-header-2026 branch March 4, 2026 05:02
ruili33 pushed a commit that referenced this pull request Mar 25, 2026
## Summary
- remove the year from Marin, Levanter, and Haliax license header
templates
- migrate existing Python file headers repo-wide from yearful to
yearless format
- simplify `infra/pre-commit.py` license checks to enforce only the
yearless header format
- merge latest `origin/main` into this branch

## Validation
- run `./infra/pre-commit.py --all-files` (passes)

## Notes
- this is a mechanical, comment-only migration across 1411 files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-generated Created by automation/agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants