Summary
expand_glob_pattern (src/graph/builder.cpp:657-695) expands a pattern two ways: against the filesystem via glob_expand, and — when that finds nothing — against NodeType::Generated nodes in the graph. #174 canonicalized the first branch. The second pushes matches in nodes_of_type order, which is arena order, i.e. node creation order, with no sort.
Measured
: foreach zeta.c mike.c alpha.c |> cp %f %o |> %B.o
: *.o |> echo %f > %o |> order.txt
putup: build/zeta.o build/mike.o build/alpha.o <- rule order
tup: alpha.o mike.o zeta.o <- name order
Why it matters
Unlike #171 this is not a reproducibility bug: creation order derives from parse order, and parse order is content-canonical (sort_dirs_by_depth, src/cli/context.cpp:686-706, whose final tiebreak is a_sv < b_sv). The same commit gives the same order on every machine.
What it breaks is the invariant #174 just established: the same rule text yields lexicographic %f when its matches come from disk and rule-order %f when they come from the graph. It also diverges from tup, which serves both node types from one query on node_dir_index (dir, name) — measured above.
Fix
Sort the merged match list by path, as glob_expand now does. See #178: the two branches should produce one list, so there should be exactly one sort.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TLob4Ef3qyMd3Dnp9q3XmA
Summary
expand_glob_pattern(src/graph/builder.cpp:657-695) expands a pattern two ways: against the filesystem viaglob_expand, and — when that finds nothing — againstNodeType::Generatednodes in the graph. #174 canonicalized the first branch. The second pushes matches innodes_of_typeorder, which is arena order, i.e. node creation order, with no sort.Measured
Why it matters
Unlike #171 this is not a reproducibility bug: creation order derives from parse order, and parse order is content-canonical (
sort_dirs_by_depth,src/cli/context.cpp:686-706, whose final tiebreak isa_sv < b_sv). The same commit gives the same order on every machine.What it breaks is the invariant #174 just established: the same rule text yields lexicographic
%fwhen its matches come from disk and rule-order%fwhen they come from the graph. It also diverges from tup, which serves both node types from one query onnode_dir_index (dir, name)— measured above.Fix
Sort the merged match list by path, as
glob_expandnow does. See #178: the two branches should produce one list, so there should be exactly one sort.🤖 Generated with Claude Code
https://claude.ai/code/session_01TLob4Ef3qyMd3Dnp9q3XmA