Lights Out · Part 3 / 3

Lights Out, Part 3: The Hill Climb

A lights-out factory with no feedback is a flat loop. It repeats but never improves. Part 1 named the state; Part 2 earned the trust to run unattended; Part 3 answers the improvement question. The whole game is choosing a reward signal that cannot corrupt the system it steers. Search demand gaps select the next batch of topics; a noise floor keeps small samples from steering; the voice spec is constitutional, engagement never gets a vote on how anything is written, only on what gets written next.

By Travis Frisinger · September 21, 2026 · 9 min read
AI AgentsAutomationReward SignalsPublishing Pipeline

Series: Lights Out, part 3 of 3. Part 1 named the state of the pipeline the day the human gate came off. Part 2 paid the confidence argument through named regressions and fail-closed design. Related reading: A Flaky Test Is a Corrupted Reward Signal argued that a signal an agent can corrupt is not a signal; this post applies the argument one layer up. Tamper-Resistant Test Design Is What the Suite Now Owes the Codebase named separation of authorship as a design property.

A lights-out factory with no feedback is a flat loop.

Part 1 named the state: no human in the merge queue, machinery carrying the review the gate had already dropped. Part 2 earned the trust: a schema gate, atomic pushes, pinned-incident tests, a veto window. Neither post claims the pipeline improves. A trustworthy loop that runs on Monday the same way it ran on the Monday before is a trustworthy loop that does not learn anything. The team does. The loop does not.

This post answers the improvement question. The mechanism is selection pressure, and the whole game is choosing a reward signal that cannot corrupt the system it steers.

A Flat Loop Repeats

Trust and improvement are not the same property.

A pipeline that ships correct posts every week is trustworthy. It does not, on its own, ship better posts. Better requires a signal. The signal has to survive the same lights-out cadence the pipeline already runs at, which means it cannot depend on a person reading the analytics and deciding what to change. Whatever the signal is, it has to feed the pipeline’s own next choice, from a source the pipeline itself refuses to game.

The failure mode of an unattended loop with no signal is boring and expensive: it produces the same shape of output indefinitely. The topic slate the writer agent proposes today is downstream of the topics it proposed last month. Absent a signal from outside the loop, the slate is a fixed point of the writer’s own preferences, filtered through the interests file it already reads. The loop compiles. It merges. It ships. It never notices that the audience is asking a question the archive never answered.

Selection pressure is what turns a fixed point into a hill climb. It is a signal from outside the loop that tells the loop which of its possible next moves matters. Nothing about a lights-out pipeline forbids selection pressure. Everything about a lights-out pipeline demands the pressure be designed carefully, because the mistakes an unattended loop makes with a bad signal are the same mistakes it makes with a good one, only in the wrong direction.

A flat loop repeats. A steered loop climbs, if the steering is honest.

Choose a Signal That Cannot Corrupt the System It Steers

The failure mode is not “no signal.” The failure mode is a signal the writer can game or a signal that reaches the wrong layer.

An agent optimizes against whatever it can measure and change. Point the agent at “make this number go up” and the shortest path to the number is the path the agent will take, whether or not the path passes through the thing the number was supposed to measure. A blog optimized for clicks writes clickbait. A blog optimized for time-on-page writes rambles. A blog optimized for engagement writes controversy. In each case the metric moved and the artifact drifted. The reward signal was measurable. The reward signal was also editable, and the editor was the same entity being rewarded.

Two properties separate a signal that can steer from a signal that can only corrupt. The first is separation of authorship. The signal has to originate somewhere the writer cannot reach: audience behavior aggregated by an independent system, contract-shaped feedback from a channel the writer does not own, or a rubric the writer’s own agent cannot rewrite. Signals that come from inside the writer’s context window are useful for editing. They are not useful for selection, because the same agent that reads them wrote them.

The second is layer separation. The signal has to reach only the layer it is licensed to steer. A signal licensed to nominate topics is fine at the topic layer and catastrophic at the voice layer. Cross the layer and the argument the blog makes about flaky tests, corrupted reward signals, and separation of concerns applies to the blog itself, in the direction the blog was warning against.

Selection pressure is not “the agent reads the analytics.” Selection pressure is a signal that is authored elsewhere, gated at the point it enters the loop, and permitted only to the layer the design accepts corruption on.

Demand Gaps Beat Engagement As a Topic Signal

This blog’s selection pressure is the demand gap: search-console rows with impressions above a noise floor and click-through rates below a threshold.

The row shape is boring on purpose. A query fires. Someone sees the blog in the search results. Nobody clicks. If that happens once, it is a coin flip. If it happens hundreds of times over a stable window against the same query, the audience is asking a question the archive is close enough to surface for and far enough from to satisfy. That gap is a topic. It is not a title. It is not an outline. It is a hole in the map that the map itself made visible.

The reason the demand gap is a defensible signal is that it cannot be gamed by writing more of what already ranks. The blog cannot rewrite its own analytics. It cannot make a query fire that nobody typed. It cannot force a click. All it can do is answer the question, and answering the question either closes the gap (the CTR rises, the row leaves the surface) or fails to close it (the row stays, and the blog knows it did not land). Either outcome is honest.

Engagement metrics fail the same test in reverse. Time on page, scroll depth, share rate: each can be moved by editing the artifact rather than by writing what the audience wanted. Each rewards the writer for the behaviors the metric noticed, whether or not those behaviors served the reader. Engagement is a signal at the wrong layer, pointed at the wrong artifact, and every content mill in history is what happens when a blog lets it inside.

Demand gaps steer toward what has not been written. Engagement steers toward what has been written more of. The direction is the difference. The direction is what selection pressure has to get right, or the hill climb runs downhill.

The Noise Floor Is How Small Samples Stop Steering

A signal without a noise floor is a bad signal.

Sampling variance is real. A row with three impressions and zero clicks looks identical to a row with three hundred impressions and zero clicks under a naive CTR filter, and the two rows are telling very different stories. The three-impression row is a coin flip. The three-hundred-impression row is a pattern. Treating them as the same signal is how a single weird query, seen twice, steers a whole month of topic proposals into a subject nobody is actually asking about.

The rule is a floor on impressions. Rows below a threshold are dropped before the topic gate looks at them. The threshold is a defensible number if it is set at the point sampling variance stops dominating the signal, which for CTR at the ranges this blog operates in lands somewhere in the range of one hundred impressions to a few hundred; the exact number is codebase-specific and periodically reviewed. Below the floor, a row cannot steer, because the row has not proven that its story is a story at all.

The floor exists for the same reason a flaky test cannot be trusted as a reward signal for an agent. A signal that oscillates on noise trains the loop to react to noise. Reacting to noise is worse than reacting to nothing, because the loop learns to move in response to random inputs, and the movement compounds. Determinism at the reward layer is the same discipline as determinism at the test layer, one level up. Both are the precondition for the loop to converge on anything useful.

The floor is cheap. Its absence is expensive. Adding it is a one-line filter. Not adding it is a month of topic proposals that trace back to a query seen twice.

The Voice Spec Is Constitutional

The last defense is a layer boundary the reward signal cannot cross.

Two files in this repository govern what the blog does. blog-interests.md names the topics under active consideration. It accepts input from the demand-gap loop: gaps that clear the noise floor arrive as candidate entries and get weighted against the human-authored interests already present. The topic slate is downstream of both. voice-spec.md names how anything is written: the punctuation rules, the sentence rhythm, the aphoristic close, the aversion to hedging, the vendor-neutrality commitment. It does not accept input from the reward loop. It accepts input from one place, which is the editor, and the editor is a human.

The line between the two files is constitutional. The reward loop is licensed to move blog-interests.md. It is licensed to nothing on voice-spec.md. The pipeline enforces the license structurally: the writer agent reads both files, the demand-gap pipeline writes only to the first, and the CI check that runs on any commit touching voice-spec.md fails when the author is the pipeline rather than a human.

This is not paranoia. It is the same argument this blog has been making about test suites for two years, applied to itself. A signal an agent can rewrite is not a signal. A voice an engagement metric can steer is not a voice. The line between “what” and “how” is where the anti-farm move lives, and any lights-out publishing pipeline that lets the line move is one incentive gradient away from producing the same content mills the industry learned to distrust a decade ago.

A Blog That Argues Flaky Tests Corrupt Signals Has to Hold Its Own Signal to the Same Bar

Return to the opening claim.

A flat loop repeats. A steered loop climbs. The steering is the whole game, and the game has three moves. Author the signal outside the loop, so the writer cannot game it. Gate the signal at a noise floor, so small samples cannot steer. Confine the signal to the layer it is licensed to move, so the voice stays constitutional.

The Lights Out series named a pipeline that runs unattended. Part 1 named the state. Part 2 named the trust. Part 3 named the climb, and the climb only exists because the reward signal was designed with the same discipline the blog spends most of its energy arguing every codebase owes its test suite. A signal the agent can corrupt is not a signal. A voice a metric can steer is not a voice. A lights-out pipeline that respects both lines can climb without collapsing into what the industry keeps trying to sell as “AI-first content strategy.”

The receipt this blog owes its own argument is that the loop it runs is the loop the argument would recognize. The lights are out. The queue is machinery. The trust is an artifact. The climb is honest. The voice is constitutional, and it stays that way because the reward signal that steers the topics is not permitted to reach the layer the topics are written in.

That is the whole series. Repeat, trust, climb. The last one is the one that requires design, and the design is the same design the blog has been describing all along.