Proving code is dead before you delete it
On the evening of 2026-08-12, three commits removed what was left of this site before Svelte:
- 18:25
07af320removedhandlers/auth.py, login code from 2014. - 20:05
228414aremovedtemplates/andstatic/: 28 files deleted, 13 screenshots moved, 5,381 lines gone. - 20:38
0548a35removed thetemplate_pathsetting and the nginx/static/alias.
Deleting is the easy part. Anyone can run git rm. The work is the
argument that it is safe, and that argument is made of things that are
not there. It is worth looking at how it was put together, because
absence is a different kind of claim from the ones tests usually make.
Three findings, in order
Nothing loads handlers/auth.py. The route table never registered
its Login or Logout handlers, so the app's login_url="/login"
pointed at no handler at all. The file's own contents made the case
stronger. It queried MongoDB (M[db].users.find_one), which the app has
never depended on. It rendered login.html, which was not in
templates/. And it has no import lines. The first line of the file is
class Logout( AuthHandler):, so loading it raises
NameError: name 'AuthHandler' is not defined. The commit that added it
in 2014 was called stashing some reference code, and that is what it
was: a fragment, not a module.
With auth.py gone, nothing renders a template. The app still had
template_path="templates" in its settings, which is a string, not a
reference. What uses a template is a self.render() call, and after the
first commit a search of every Python file for render( came back
empty. That finding depends on the first one. auth.py held the last
render() in the repository, so templates could not be proven dead
until it was gone.
Nothing asks for /static/. No Tornado route served it, and nothing
in the built Svelte app requested it. But nginx did serve it:
location /static/ {
alias /opt/pearachute/static/;
}
So "dead" meant unreferenced, not unreachable. Until that alias went,
the server would hand a copy of jQuery from 2014 to anyone who asked for
/static/jquery.min.js. A search can prove that nothing in the
repository links to a path. Only the
access log can say whether anything outside the repository still does,
an old blog post or a bookmark. That is the edge of what this kind of
evidence covers, and it is worth saying out loud when you delete
something public.
Absence is a different kind of argument
A test proves presence: this request returns that page. A search proves absence: no file anywhere says this name. The two fail differently. A test that passes is evidence about the thing it ran. A search that comes back empty is evidence only about the places it looked.
That is why the useful version of the search crosses every place a
reference can live, and why tools mostly will not do it for you. A
dead-code checker reads one language's imports. The references that
mattered here were in four different languages: a Python string setting
(template_path), a Tornado route table, an nginx alias, and <img>
tags inside Markdown files. Nothing that reads only Python would have
connected static/docimgs/ to docs/united-federal.txt.
One more trap, from the same evening. The message on 228414a says it
"also drops the now-unused template_path setting and the nginx /static/
alias". It doesn't. Those edits were made in the working tree and never
staged, and 0548a35 carried them in 33 minutes later. The commit
message described evidence that the commit did not contain. Check the
tree, not the message, including your own.
Age is not evidence
It is tempting to treat old as dead. Here is every file in the tree on the morning of the deletions, placed by the date it was last edited:
07af320^, the commit before the first deletion, by the date of its last non-merge edit. docs/ (44 files of unserved writing, kept by policy) is left out. Hover a dot for its path.The 44 deleted, moved and kept files as a table
| file | last edited | verdict |
|---|---|---|
static/d3.v3.min.js | 2014-01-16 | deleted |
static/jquery.min.js | 2014-01-16 | deleted |
static/queue.js | 2014-01-20 | deleted |
static/pperfect.js | 2014-01-31 | deleted |
static/doc.css | 2014-05-14 | deleted |
static/marketmagic.js | 2014-05-16 | deleted |
handlers/auth.py | 2014-05-29 | deleted |
static/tonalpohualli.js | 2014-05-29 | deleted |
static/logo.png | 2014-11-01 | deleted |
static/three.min.js | 2014-11-01 | deleted |
static/threedemo.html | 2014-11-01 | deleted |
static/threelogo.html | 2014-11-05 | deleted |
templates/legacy.html | 2016-08-27 | deleted |
static/logo.svg | 2016-09-08 | deleted |
static/pforex.js | 2017-01-31 | deleted |
static/css/normalize.css | 2017-05-04 | deleted |
static/css/skeleton.css | 2017-05-04 | deleted |
static/redditreader.js | 2017-05-04 | deleted |
templates/ga-snippet.html | 2017-05-05 | deleted |
static/js/homepage-logo.js | 2017-05-08 | deleted |
static/images/favicon-16x16.png | 2017-05-17 | deleted |
static/images/favicon-32x32.png | 2017-05-17 | deleted |
static/images/favicon.ico | 2017-05-17 | deleted |
templates/index.html | 2017-05-17 | deleted |
static/loading.js | 2022-12-06 | deleted |
templates/hello.html | 2025-10-24 | deleted |
templates/market_magic.html | 2025-10-24 | deleted |
templates/pitch_perfect.html | 2025-10-24 | deleted |
templates/tonalpohualli.html | 2025-10-24 | deleted |
static/docimgs/putty_download_1.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_download_2.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_download_3.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_start_1.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_start_2.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_start_3.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_start_7.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/putty_website.jpg | 2011-01-21 | moved to docs/imgs/ |
static/docimgs/writingmapreduce.png | 2014-01-22 | moved to docs/imgs/ |
static/docimgs/logging-gone-wrong.png | 2014-06-07 | moved to docs/imgs/ |
static/docimgs/united-federal-newsletter.png | 2014-06-07 | moved to docs/imgs/ |
static/docimgs/cabinhiring.png | 2014-07-28 | moved to docs/imgs/ |
static/docimgs/blekko_v_duckduckgo.png | 2014-11-12 | moved to docs/imgs/ |
handlers/reddit.py | 2017-05-05 | dead, still here |
web/src/lib/Counter.svelte | 2023-01-02 | dead, still here |
The dates overlap almost completely. Age is a decent prior: most of the "everything else" row was touched during the July 2026 rebuild, and most of what got deleted had not been touched since 2017. But it is a prior, not proof, and both ends of the chart show why.
The youngest dead files were nine months old. On 2025-10-24 a coding
bot added market_magic.html, pitch_perfect.html and
tonalpohualli.html to templates/, with handlers on master that
rendered them. Three months later the Svelte merge kept the svelte side's
server, which had no handlers for those pages, and kept the files
anyway. They were dead for 196 days before anyone deleted them. Sorting by
age would have saved them.
Some of the oldest live files are older than most of the dead ones.
handlers/__init__.py came in on 2014-05-29, in the same commit as
auth.py, stashing some reference code. It is an empty file. Twelve
years later auth.py was deleted and __init__.py is the package every
handler on the site lives in. The demo datasets under /data/ were last
edited in January 2023 and are served on every visit to two demo pages.
Sorting by age would have deleted them.
Moved, not deleted
Thirteen screenshots in static/docimgs/ were just as dead by the
serving standard, and they were moved to docs/imgs/ instead of deleted,
because old write-ups in docs/ show them:
<img src="/static/docimgs/united-federal-newsletter.png" class="img-responsive">
That is the third outcome, and the easiest to miss: dead here, wanted somewhere. Running the search again for this note turned up two footnotes to it.
Only nine of the thirteen are referenced, from three files in docs/.
The other four (cabinhiring.png, logging-gone-wrong.png,
blekko_v_duckduckgo.png and putty_start_7.jpg) are not named
anywhere in the repository. They moved because their directory moved.
That was a reasonable call, but it was a call, not a finding, and by the
standard the rest of the evening used, those four were dead.
And the nine references have outlived their target. Those <img> tags
still say /static/docimgs/, which no longer exists. Nothing breaks,
because docs/ is not served. The references that justified keeping the
files now point nowhere.
When the answer is keep it
handlers/reddit.py is dead by exactly the same standard. Nothing
imports it and no route uses it. It is kept on purpose, and the reason is
written down where an agent or a person will find it: the repo's
instructions call it "kept as reference from an earlier project".
That is the right shape for a keep decision. But run the same check on it anyway:
$ python -c "import handlers.reddit"
AttributeError: module 'tornado.web' has no attribute 'asynchronous'
It uses @tornado.web.asynchronous, which Tornado removed in 6.0, in
2019. It also passes a str to md5(), which Python 3 rejects. It is
reference code that cannot load on the stack it sits in. That doesn't
make keeping it wrong. It makes the note incomplete. A keep decision
should say what the code is for, and also what it no longer does.
And then there is web/src/lib/Counter.svelte, the demo counter that
ships with the Svelte starter template. It arrived on 2023-01-02 with
stock svelte starter kit, nothing has ever imported it, and it is still
in the tree. Nobody decided to keep it. It passed every review by being
too small to notice, which is a different thing from being kept.
The checklist
What made this evening's deletions safe, as steps:
- Search every place a reference can live, not just one language's imports: route tables, template names in strings, server config like nginx, the built output, documentation, and if the thing was public, the access log.
- Delete in dependency order, so each finding rests on the one
before it. Templates could not be proven dead while
auth.pyheld the lastrender(). - Know which kind of dead you have. Unreferenced is not unreachable. A public path can be dead in the repo and alive on someone's bookmark.
- Check the tree, not the commit message. Including your own.
- For anything you keep, write down why, next to it, and run it once in a while to see if the reason still holds.
The deletions were three commits and about two hours. Most of that time was spent showing that nothing would notice.