Severity: medium. Found by an adversarial-operator user test. Pre-existing.
The containment guard added for symlinks refuses links pointing outside the repository. A link pointing inside is followed and written through — but GitHub does not follow a symlinked CODEOWNERS at all, so the reason the outside-guard gives ("GitHub does not follow one anyway … governing nothing") applies identically here.
Repro
.github/CODEOWNERS -> ../real_owners.txt, then:
cot sync --repo r --op 'add_owner(f.txt, @org/new)'
# applied, proven: tree, paths_changed: 1, old_owners [@org/real] -> [@org/real, @org/new]
# the edit lands in real_owners.txt. No warning.
cot snapshot --repo r
{".github/CODEOWNERS": null, "f.txt": null, "real_owners.txt": null}
cot audit --repo r
3 of 3 tracked paths (100%) have no owner
So sync asserts a tree-proven ownership change for a file GitHub never reads, while the tool's own two read commands report that nothing is owned. Three commands, three incompatible answers about the same repository at the same moment.
Suggested fix
Treat a symlinked CODEOWNERS as governing nothing regardless of where it points — refuse, or at minimum warn with the same reasoning the outside-repo guard already uses.
Severity: medium. Found by an adversarial-operator user test. Pre-existing.
The containment guard added for symlinks refuses links pointing outside the repository. A link pointing inside is followed and written through — but GitHub does not follow a symlinked CODEOWNERS at all, so the reason the outside-guard gives ("GitHub does not follow one anyway … governing nothing") applies identically here.
Repro
.github/CODEOWNERS -> ../real_owners.txt, then:So
syncasserts a tree-proven ownership change for a file GitHub never reads, while the tool's own two read commands report that nothing is owned. Three commands, three incompatible answers about the same repository at the same moment.Suggested fix
Treat a symlinked CODEOWNERS as governing nothing regardless of where it points — refuse, or at minimum warn with the same reasoning the outside-repo guard already uses.