Skip to content
Touchskyer's Thinking Wall
S3E06
9 min read

Silicon Team S3E06: Actually Verifying the FAIL Path for the First Time

Silicon Team S3E06

S2E08 uncovered an uncomfortable truth: OPC’s most fundamental promise — “no pass, no ship” — had never actually been exercised. Eight products, dozens of gate decisions, FAIL/ITERATE loops never fired once. The maxLoopsPerEdge=3 cap was never tested.

An enforcement mechanism that has never fired is indistinguishable from one that doesn’t exist.

This episode pays that debt.

Why FAIL Never Triggered

First, understand the root cause. There are three possible explanations for the FAIL path not triggering:

Explanation 1: Review standards were too lenient. LLM reviewers tend toward positive assessments. S1E03 already observed four reviewers unanimously judging PASS — even when there was a directional issue that should have been caught. Adding the skeptic-owner role improved things, but the “lean PASS” baseline didn’t fundamentally change. If reviewers rarely give red flags, the gate’s emoji count will never reach the FAIL threshold.

Explanation 2: The tasks were too easy. S2’s eight products covered different domains (calendar, education tools, knowledge management, visualization), but complexity concentrated in product design rather than code implementation. Most implementations were standard web apps — React components, REST APIs, database CRUD. These patterns are extremely familiar to LLMs, and the code they produce typically passes basic review. Without deliberately introducing difficult boundary scenarios — concurrent conflicts, distributed consistency, performance hot paths — FAIL won’t trigger naturally.

Explanation 3: OPC’s build quality was genuinely good enough. Perhaps FAIL didn’t trigger for the simple reason that the code actually passed. Not because reviews were lax, not because tasks were easy, but because OPC’s build node (implementer + project constraints + tests) produced code quality that met the review bar.

S2E08’s honest conclusion: these three explanations can’t be distinguished. This episode doesn’t try to distinguish them — it tries to answer a more practical question: if given a chance to trigger, can FAIL actually work correctly?

Designing a Scenario That Must FAIL

The method for verifying the FAIL path isn’t waiting for it to happen naturally — it’s deliberately creating a scenario that will trigger FAIL.

Approach: intentionally submit an implementation with known defects. Have the build node produce code with a significant but detectable problem — say an O(n²) algorithm on a large dataset, or an API call missing error handling. Then see if the review node catches it, the gate judges FAIL, and the loop triggers correctly.

This isn’t testing whether reviewers are smart — it’s testing the pipeline’s mechanical parts:

  1. After a reviewer marks a red flag, can synthesize count correctly?
  2. After the emoji count reaches the FAIL threshold, can the gate correctly judge FAIL?
  3. After the gate judges FAIL, can flow-transition correctly route back to the build node?
  4. During the loop, are previous review findings passed to the builder?
  5. After the second round of building fixes the issue, can reviewers see the improvement and change to PASS?
  6. Does the maxLoopsPerEdge counter increment correctly?

Six checkpoints, each an independent failure point. Never end-to-end tested before.

Round 1: FAIL Triggered

The deliberately defective implementation entered the review node. Three review roles examined it simultaneously.

Result: two roles issued red flag markers. Synthesize scanned the emojis, counted correctly. Gate judged FAIL.

The FAIL path was triggered for the first time.

But this wasn’t enough — triggering FAIL is just the starting point of the loop mechanism. The critical question: what happens after the loop?

The Loop’s Problem

After the gate judged FAIL, flow-transition correctly routed the process back to the build node. The loop counter went from 0 to 1. So far, the mechanical parts worked fine.

Then the problem appeared.

When the build node restarted, it didn’t know what the previous round’s review had found. S2E08 had already flagged this: “The current flow: review findings → gate judges FAIL → loop back to build node → ???. There’s no mechanism tracking which findings were fixed, which were deferred, which were false positives.”

This wasn’t a theoretical problem — it became a practical one after actually triggering FAIL. The builder in round 2 didn’t know what round 1’s red flags specifically referred to. It needed to re-review the entire codebase rather than targeting known issues.

The FAIL path’s mechanical parts (judgment + routing + counting) worked correctly. The FAIL path’s information transfer (review findings → build fixes) was broken.

It’s like a court: the judge says “guilty,” the defendant is sent back to “correct their ways,” but nobody tells them what the charges are.

Finding Disposition Tracking

Fixing this break requires a new mechanism: Finding Disposition Tracking.

Each round’s review findings need structured recording:

{
  "round": 1,
  "findings": [
    {
      "id": "F001",
      "severity": "critical",
      "source": "performance-reviewer",
      "description": "O(n²) sort in data processing pipeline",
      "file": "src/pipeline/transform.ts",
      "line": 42,
      "status": "open"
    }
  ]
}

When looping back to the build node, this findings list is passed to the builder. After fixing, the builder marks each finding’s disposition:

  • fixed: Fixed, with the fixing commit or line number attached
  • deferred: Deferred to a later version, with reasoning
  • false-positive: Misjudgment, with explanation

In the second round, reviewers receive not “review the entire codebase from scratch” but “verify whether these findings’ dispositions are correct.” This transforms review from full re-review to incremental verification.

Round 2: Fix + PASS

After manually passing round 1’s review findings, the build node fixed the known defects. Round 2 review: reviewers confirmed issues were resolved, no new red flags. Synthesize counted correctly. Gate judged PASS.

The loop counter showed 1 — meaning this passed after one loop iteration.

The complete FAIL → fix → PASS path was walked end-to-end for the first time.

The Old Emoji Parsing Bug

During verification, the S2E08 emoji parsing bug was also confirmed fixed.

Old bug: a reviewer writes ”### 🔴 Must Fix: None.” — synthesize scans the red emoji, judges it as a critical finding. “None” was ignored — mechanical parsing only sees emojis, not semantics.

Bug status: fixed. Synthesize now checks whether a negation word (“None,” “N/A”) immediately follows a red flag emoji. If so, it’s not counted as critical.

But this fix exposes a deeper issue: emoji counting is fundamentally a heuristic method. It handles ”🔴 None” correctly, but what about ”🔴 Not a dealbreaker but worth noting”? That’s not critical, but the mechanical parser might count it as one.

S1E07’s conclusion that mechanical gates beat LLM gates still holds — heuristic edge cases are enumerable and fixable; LLM judgment drift is unpredictable. But each heuristic edge case needs to be discovered before it can be manually fixed. It changes the failure mode from “unpredictable” to “debuggable” — but the debugging workload is ongoing.

Safety Nets Must Be Tested

Back to the topic of trust.

EP01-EP05 covered the first four trust layers: infrastructure, pattern, contribution, core. This episode addresses the fifth layer: resilience — can the system withstand failure?

A review system’s value isn’t in how many things it passes — it’s in how many things it blocks. A review system that has never blocked anything has “blocking” as an unverified promise.

A safety net must be tested to count as a safety net.

Fire drills don’t happen because the office is actually burning. Load tests don’t happen because production actually has a million concurrent requests. Chaos Engineering doesn’t happen because Netflix actually wants servers to crash. The purpose of these tests isn’t to trigger problems — it’s to verify that when problems trigger, response mechanisms work correctly.

OPC’s FAIL path verification is the same class of practice. Not to prove code can be wrong — but to prove that when code is wrong, the review + gate + loop chain responds correctly.

What Debt Remains

This round of verification paid S2’s biggest debt but created new ones:

1. Finding disposition tracking isn’t mechanized yet. In this verification, round 1’s review findings were manually passed to the build node. The real solution requires the harness to automatically extract findings on FAIL loops, store them structurally, and pass them to the next round. This is a core code change — the wall EP04 described.

2. A single verification doesn’t mean ongoing reliability. The FAIL path was walked once successfully, but that doesn’t guarantee it works correctly in every scenario. More trigger scenarios are needed: different types of FAIL (security vs. performance vs. design), different red flag counts (exactly at threshold vs. far exceeding), consecutive FAILs (reaching the maxLoopsPerEdge=3 cap).

3. External users’ experience of FAIL. As maintainer, I know what FAIL means, what looping means, how to read review findings. When an external user sees a gate judge FAIL for the first time — what happens? Is the error message clear? Do they know what to do next? The FAIL user experience is part of trust layer 5 (resilience).

From “Has Teeth” to “Can Bite”

S2E08 asked: does “no pass, no ship” actually have teeth?

This episode’s answer: it has teeth. But between having teeth and being able to bite, there’s still muscles (finding disposition tracking) and practice (more trigger scenarios) missing.

The gate can judge FAIL. The loop can route back. The counter can increment. That’s the skeleton — the mechanical parts work. But skeleton isn’t enough — you also need the complete closed loop of information transfer (what problems were found → how to fix → were they fixed → verify the fix).

This is isomorphic to the five-layer trust model: having structure (skeleton) doesn’t equal having capability (muscles) doesn’t equal having confidence (practice).

Next episode: contribution governance. When five people start adding things to your tool, you need more than an interface — you need rules.


Silicon Team S3: From “I Can Use It” to “Others Can Use It” ← S3E05: Turning a Personal Tool Into Something a Stranger Can Run | S3E07: Between Role Contributions and an Extension Ecosystem, There’s a Missing Governance Layer →

Comments