Smith::Tools::Paths
Path normalisation, kept apart because getting it wrong is how a scoped rule gets bypassed.
Class methods
normalize(path : String, project_dir : String) : String
Collapses .. and resolves symlinks. Both matter: without the first,
write_file(src/../../../etc/passwd) walks straight out of a
write_file(src/**) scope; without the second, a symlink inside the
scope does the same thing more quietly.
The file need not exist — a write_file usually targets a new one — so the deepest existing ancestor is resolved and the rest appended.