./Scripts/check-core-boundary.sh
swift build --build-tests && swift test
./Scripts/build-app.sh releaseCI runs exactly this on macos-26.
SiltCore does not import SwiftUI or AppKit. The engine has to be testable without a
window; that is the only reason any of it has tests. A change that needs an interface framework
in the engine belongs in SiltApp instead.
Widening what can be deleted needs a test first. RemovalGuard is tested from the refusing
side — every case in RemovalGuardTests asserts that something is not removable. If your
change makes a new class of path deletable, add the cases that must still be refused before you
add the ones that should now pass.
A rule needs three things beyond its paths:
explanation— what this is, for someone who has never heard of it.consequence— what changes after it is gone. One sentence, concrete. "Rebuilds the index" is useful; "may affect performance" is not.safety—.rebuiltif it comes back on its own,.refetchedif it comes back only over the network,.irreplaceableif it does not come back..irreplaceableis never preselected in the interface, so getting this wrong is how someone loses data.
If you cannot write the consequence in a sentence, the rule is not ready. A cleaner that offers gigabytes next to a checkbox and no explanation is asking the user to gamble.
Measure it on a real machine before proposing it — swift run silt cleaners --verbose prints
what a rule would actually match.
Include the output of both:
swift run silt scan <path> --depth 1
du -sk <path>du also reports allocated blocks, so the two should agree closely. If they do not, that is a
real bug and a good report. If Silt disagrees with Finder, read Docs/accounting.md first —
Finder reports logical size in several places, and the difference is usually the point rather
than the fault.
Match the surrounding code. Comments explain why something is the way it is, not what the line
does; the ones worth writing are the ones that stop the next person undoing a decision that
looks arbitrary. Docs/accounting.md and CLAUDE.md hold the reasoning that outlived the
commit it came from — if you work something out the hard way, put it there.