Canary / How it works
The whole pipeline, end to end
What happens between the moment a file lands in a watched folder and the moment a report says something about it — including the one setting that decides whether you are still reading the report a month from now.
Two tools, because they answer different questions
They are shipped separately and either one runs without the other. That is a deliberate cost: it means two repositories, two release processes, and this page. The reason it is worth paying is that the questions do not collapse into one.
“Is this column still carrying information?”
Give it a table, it scores every column and answers. It has no opinion about when to run — it waits to be asked. That is what makes it usable inside someone else’s script, build pipeline, or nightly job that has nothing to do with us.
“What is wrong in the file that just landed?”
Watches folders, decides when to ask, remembers the last answer, and reports what changed. It does none of the analysis itself — it calls flatline. Two copies of the same analysis diverge the first time only one of them gets fixed.
What actually happens, in order
This is a real sequence — each step depends on the one above it, and step 2 exists specifically so that the rest cannot quietly be skipped.
- A file changes in a watched folder Canary is pointed at the folders where your exports already get saved. It compares each file against what it recorded last time — size, modification time, content fingerprint — so an untouched file is not re-analysed just because the clock moved.
- Canary checks it can reach flatline — before analysing anything Availability is settled up front rather than discovered halfway through. If flatline cannot be reached, that is an ERROR and a non-zero exit, never a quiet “nothing found”. A checker that reports clean because it never ran is the exact failure these tools exist to catch.
- Flatline reads the table and scores every column It normalises values, counts how they are distributed, and computes how much information each column is actually carrying. Verdicts and severities below.
- Canary compares the answer against the last look It keeps the previous result per file, so it can tell you what is new rather than re-reading the same twenty findings at you every night.
- Columns you have marked as expected-constant are set aside Named and counted in the report, not deleted from it. This is the step most people need and the one that was undocumented until now — see below.
- The report is written and the exit code is set Human-readable HTML for you; an exit code for whatever scheduler is running it. The exit code reports news, not inventory.
What flatline looks for
The core check is information content: a column whose value never changes cannot be affecting any decision downstream, whatever the report built on top of it implies.
| Verdict | Meaning | Severity |
|---|---|---|
| CONSTANT | Every row carries the same value. The column is decoration. | HIGH if the column name looks like a decision signal, otherwise INFO |
| NEAR_CONSTANT | Nearly every row is the same value — a signal that has mostly stopped moving. | MEDIUM if it looks like a decision signal, otherwise INFO |
How canary reaches flatline
Three paths, because the tool ships in two very different shapes and the third case must not be silent.
| Situation | What canary does |
|---|---|
| installed | Runs python -m flatline scan <file> as a subprocess and reads what it prints. |
| frozen .exe | Calls flatline’s own cli.main in-process. In a bundled application a subprocess would relaunch the application itself, not flatline. |
| not found | ERROR and a non-zero exit. Never a clean report. |
canary-ignore.txt — the setting that decides whether you keep reading
Without this, canary is correct and unusable. On the first real folder we pointed it at, two columns — a ruleset version and a regime code — produced two thirds of every finding, every night. Both are constant by design. Nothing in the data can tell canary that. Only the person who owns the file knows, so they say it once, in a plain text file they can open and read.
It lives beside canary’s state file, and the report tells you the exact path it looked at. The same list can be passed on the command line with --ignore.
Exit codes
For whatever is running canary on a schedule. Two rules in here are deliberate and worth knowing, because both look wrong at first glance.
| Code | Meaning |
|---|---|
| 0 | Every re-examined file came back clean. |
| 1 | A file could not be checked. |
| 2 | New findings — only with --fail-on-findings. |
What the pair cannot see
- Whether a number is correct. A column full of varied, confidently wrong values looks healthy to flatline.
- Whether the job that was supposed to write the file ran at all. Canary sees files, not work — a job that dies before writing produces no event to react to.
- Anything in a folder it was not pointed at.
- Whether a constant column is supposed to be constant. That is what the ignore file is for, and why it is yours to write rather than something we guess.
The first two are covered by other tools in the set, which is the whole reason there is more than one.
Read the source
Every claim on this page is a few lines of readable Python away. Both are MIT.
canary on GitHub · flatline on GitHub · back to Canary · Flatline