Skip to content

fix: unshadow the license task, reconcile the template lock - #99

Merged
tschm merged 2 commits into
mainfrom
fix/quality-findings
Aug 21, 2026
Merged

fix: unshadow the license task, reconcile the template lock#99
tschm merged 2 commits into
mainfrom
fix/quality-findings

Conversation

@tschm

@tschm tschm commented Aug 21, 2026

Copy link
Copy Markdown
Member

Two tooling fixes from a /rhiza:quality run. No source or test changes, so the
performance figures in README.md and docs/paper/ are untouched.

make license silently no-oped on macOS (#96)

macOS defaults to case-insensitive APFS, where the LICENSE file at the repo
root satisfies make's search for a target named license: an existing file with
no prerequisites, so make declared it up to date and the shim's catch-all %:
rule never fired.

$ make license
make: `license' is up to date.

The copyleft scan reported success while scanning nothing — the one failure shape
a licence check must not have in a package whose reason to exist is being an
MIT-licensed replacement for a GPL-2.0 one.

Fixed in local.mk, which the shim's header names as the place for
repo-specific one-offs, and where an explicit rule beats the pattern rule.
.PHONY is what does the work: it tells make the target is a command rather
than a file. It could not be declared upstream in the generated shim, whose
header notes that .PHONY cannot name targets it does not know — and whose
claim that no file shares a task name is exactly what fails here.

Blast radius was local only. CI is unaffected (Linux is case-sensitive), and
make all was unaffected too, because it hands the whole graph to
uvx rhiza-task all, which resolves needs internally without consulting make.
Only the direct local call was broken.

After:

$ make license
$ uv run --with pip-licenses pip-licenses --fail-on=GPL;LGPL;AGPL --partial-match ...
      ok  license

template.lock disagreed with template.yml (#97)

The lock still listed .github/workflows/rhiza_mutation.yml under files: and
omitted it from exclude:, because it was written at the 2026-08-19 sync while
the exclusion landed 2026-08-21 (64d9b8b).

It matters because CLAUDE.md rule 4 points readers at the lock's files:
block as the authoritative list of template-owned paths, and for this one entry
it said the opposite of the truth: the file is excluded, so the next sync will
not re-deliver it. Two lines, bringing the record into line with the intent
rather than waiting for the next /rhiza:update to rewrite it.

Not included: #98

The _solve_with_factors complexity refactor is deliberately not here. It
worked — B(10) to A(3), package average 3.96 to 3.79, suite green at 100%
statement and branch coverage — but it cost a measured 3–4% at n <= 100, which is
3–4x the ~1% budget _solve.py's own comment records for the _steps split. See
the measurement in #98.

Gates

make fmt, make typecheck, make docs-coverage, make deps, make security,
make license, make rhiza-test and make test all pass locally — 1132 tests,
100% statement and branch coverage.

Closes #96
Closes #97

🤖 Generated with Claude Code

tschm and others added 2 commits August 21, 2026 17:01
macOS defaults to case-insensitive APFS, where `LICENSE` at the repo root
satisfies make's search for a target named `license`: an existing file with no
prerequisites, so make declares it up to date and the shim's catch-all `%:` rule
never fires. The copyleft scan reported success while scanning nothing --

    $ make license
    make: `license' is up to date.

-- which is the one failure shape a licence check must not have in a package
whose reason to exist is being an MIT-licensed replacement for a GPL-2.0 one.

`local.mk` is where the shim's header says repo-specific one-offs belong, and an
explicit rule there beats the pattern rule. `.PHONY` is what actually fixes it:
it tells make the target is a command rather than a file. It could not be
declared upstream in the generated shim, whose header notes that `.PHONY` cannot
name targets it does not know -- and whose claim that no file shares a task name
is exactly what fails here.

Neither CI nor `make all` was affected: Linux is case-sensitive, and `make all`
hands the whole graph to the CLI, which resolves `needs` internally without
consulting make. Only the direct local call was.

Closes #96

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The lock still described `.github/workflows/rhiza_mutation.yml` as a synced file
and omitted it from `exclude:`, because it was written at the 2026-08-19 sync
while the exclusion landed on 2026-08-21 (64d9b8b).

That matters only because CLAUDE.md rule 4 points readers at the lock's `files:`
block as the authoritative list of template-owned paths, and for this one entry
it said the opposite of the truth: the file is excluded, so it will not be
re-delivered by the next sync. Bringing the two into agreement now means the
record matches the intent rather than waiting for the next `/rhiza:update` to
rewrite it.

Closes #97

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 21, 2026 13:02

Copilot AI left a comment

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.

Pull request overview

This PR applies two tooling fixes identified by a /rhiza:quality run: it ensures make license always executes the Rhiza license gate on case-insensitive filesystems (macOS), and it reconciles the Rhiza template lockfile with the current template exclusion list.

Changes:

  • Add a repo-owned local.mk override to make license a .PHONY target so it can’t be shadowed by the root LICENSE file on case-insensitive filesystems.
  • Update .rhiza/template.lock to exclude .github/workflows/rhiza_mutation.yml and remove it from the synced files: list.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.

File Description
local.mk Adds an explicit .PHONY: license rule so make license runs the intended Rhiza task even on case-insensitive filesystems.
.rhiza/template.lock Aligns the lockfile’s exclude:/files: entries with the template’s intent regarding the mutation workflow.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread local.mk
Comment on lines +18 to +21
# `.PHONY` is the fix: it tells make the target is a command rather than a file, so the LICENSE
# file stops shadowing it. It could not be declared in the shim itself, whose header explains
# that `.PHONY` cannot name targets it does not know -- and whose claim that no file shares a
# task name is exactly what fails here.
@tschm
tschm merged commit 93e822c into main Aug 21, 2026
44 checks passed
@tschm
tschm deleted the fix/quality-findings branch August 21, 2026 14:10
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.

Reconcile .rhiza/template.lock with the rhiza_mutation.yml exclusion make license silently no-ops on case-insensitive filesystems

2 participants