A function can only do what its signature admits to.

Not a lint, not a convention. Deed reads the body, and a function that reaches for something its signature did not mention is not a program.

This function saves a file.

fn keep(files: Dir, name: String, text: String) -> Result<(), String>
  uses
    Io.read,
{
    match Io.read(files, name) {
        ok(_) => ok(()),
        err(_) => Io.save(files, name, text),
    }
}

Its signature only admits to reading one.

error[DEED5001]: `keep` performs `Io.save` without declaring it
  --> main.deed:3:4
  |
3 | fn keep(files: Dir, name: String, text: String) -> Result<(), String>
  |    ^^^^ add `Io.save` to the `uses` clause
  |
  = note: a function can only do what its signature admits to

That list has a name, an effect row, and it is part of the type. It is checked in both directions, so a row that claims authority the body never uses is an error too: a signature is only worth reading if it is tight. Nothing is ambient. If a function can touch the filesystem, it was handed the filesystem, and you can see that from the call.