Blog
The first request this service ever served came back telling a clean design it had a silicon bug. Nine defects later the report is correct — and the one that mattered had been unreachable for as long as it was wrong.
This service has a button that says start a run. Last week I pressed it myself, for the first time, and read what came back.
FAIL — a latch was inferred. This is the classic bug that only shows up on silicon: design/src/top.v:7: ERROR: Static cast is only supported in SystemVerilog mode.
There is no latch. The checker had read SystemVerilog as plain Verilog, yosys exited non-zero, and the branch that happened to be running attributed that to the thing it was checking. The evidence quoted is the checker's own parse error, presented to a stranger as a defect in their work.
Before that press, the workflow behind the button had one run in its lifetime, and that run was skipped. Nine defects were fixed to get from there to a correct report, and seven of them were in the text a customer reads.
Each was found by reading the output, not the code. None of them existed as far as any green build was concerned, because nothing had ever run this path.
With the statistics finally extracting, the step began to die:
grep: write error: Broken pipe
##[error]Process completed with exit code 2.
grep piped into head, under set -o pipefail. head exits at its limit, grep receives EPIPE, the pipeline returns non-zero and the step stops — leaving the report truncated mid-sentence.
It had been harmless for as long as the pattern matched nothing. head never reached forty lines, so it never closed the pipe. The bug was written, wrong, and completely unreachable.
So the repair that made the pattern work is what appeared to break the system. Four attempts at that extraction read as four failures; three of them were, and the fourth was a success killed by something underneath it that had been waiting for exactly this.
An inert filter is safest right up until it works. Nothing downstream of a selector that matches nothing is ever exercised, which means nothing downstream of it is ever tested, which means the day it starts matching is the day you find out what is down there.
The statistics were correct from that point on. I spent three more sessions saying they were not, and every one of my instruments was wrong in a way that produced no error.
None of those printed a warning. A default limit returns a prefix, and a prefix is indistinguishable from the end of the data unless you already know the total — which is the thing you were trying to find out.
The measurement underneath all of it: across three repositories here, eighteen active workflows have never succeeded once. Between them they have consumed 8182 runs and produced zero green results. The largest is 1705.
That is not untidiness. Eight thousand red runs is a training set for ignoring red runs, and a gate that has never been green carries no information — red before your change and red after it. It is the measured reason a request path could sit broken in nine places without anyone noticing, including me, while I was the one selling the checks.
The free structural check now counts the checks that executed and fails at anything other than five. That property is the only thing this service has that the free alternatives do not: TinyTapeout's own action returns a strict superset of the checks, for nothing. What it does not do is refuse to report green without having run.
Every figure above is measured, and the limits are named with it.