<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RELAUNCH DEPT.</title>
    <description>The latest articles on DEV Community by RELAUNCH DEPT. (@relaunchdept).</description>
    <link>https://dev.to/relaunchdept</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4068266%2F47d6fec2-1d98-4109-b0e6-2fc595ccac2d.png</url>
      <title>DEV Community: RELAUNCH DEPT.</title>
      <link>https://dev.to/relaunchdept</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/relaunchdept"/>
    <language>en</language>
    <item>
      <title>Your AI agent said "done." What would prove it?</title>
      <dc:creator>RELAUNCH DEPT.</dc:creator>
      <pubDate>Sat, 08 Aug 2026 06:32:56 +0000</pubDate>
      <link>https://dev.to/relaunchdept/your-ai-agent-said-done-what-would-prove-it-3kbh</link>
      <guid>https://dev.to/relaunchdept/your-ai-agent-said-done-what-would-prove-it-3kbh</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted disclosure: I used AI tools to help edit this article and the&lt;br&gt;
open-source project it describes. The architecture, tests, deployment evidence,&lt;br&gt;
and claim boundaries were reviewed against the public repository and live&lt;br&gt;
service before publication.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I created this piece of content for the purposes of entering the All Things&lt;br&gt;
Agentic Hackathon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An autonomous agent can produce a confident status update long before the work&lt;br&gt;
is actually complete. A deployment command can exit successfully while the&lt;br&gt;
public endpoint still fails. A marketplace can display an opportunity that the&lt;br&gt;
authoritative issue has already closed. A generated report can look finished&lt;br&gt;
while one required source is stale.&lt;/p&gt;

&lt;p&gt;The problem is not that language models cannot reason. The problem is that&lt;br&gt;
“done” is a state transition, and state transitions need evidence.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/ceodaradigu/proofline-agent" rel="noopener noreferrer"&gt;Proofline&lt;/a&gt; to test a&lt;br&gt;
simple pattern: let the model interpret the task, but make a deterministic gate&lt;br&gt;
decide whether the evidence is sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate interpretation from acceptance
&lt;/h2&gt;

&lt;p&gt;Proofline divides the workflow into two layers.&lt;/p&gt;

&lt;p&gt;The agent layer uses Gemini 3.6 Flash and Google Agent Development Kit to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;interpret the task contract;&lt;/li&gt;
&lt;li&gt;identify the requirements that need proof;&lt;/li&gt;
&lt;li&gt;explain missing or contradictory evidence;&lt;/li&gt;
&lt;li&gt;call a narrowly scoped evaluation tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The verification layer then applies explicit rules. It does not ask the model&lt;br&gt;
whether the task &lt;em&gt;feels&lt;/em&gt; complete. It evaluates structured evidence and returns&lt;br&gt;
one of four states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NEEDS_EVIDENCE&lt;/code&gt; — at least one requirement lacks fresh authoritative proof;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONFLICT&lt;/code&gt; — authoritative sources contradict one another;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APPROVAL_REQUIRED&lt;/code&gt; — the evidence is complete, but the next action has an
external side effect;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;READY&lt;/code&gt; — every requirement is satisfied and no approval gate remains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That split matters. The model remains useful where language and context are&lt;br&gt;
messy, while the acceptance boundary stays inspectable and testable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make evidence a first-class object
&lt;/h2&gt;

&lt;p&gt;Each evidence item carries more than a sentence saying something worked. It&lt;br&gt;
records the requirement it supports, its source, whether that source is&lt;br&gt;
authoritative, when it was observed, and the value that was actually returned.&lt;/p&gt;

&lt;p&gt;A deployment claim, for example, should not be supported by “the command&lt;br&gt;
succeeded.” Better evidence is an external HTTP response from the deployed URL,&lt;br&gt;
the active revision identifier, and a timestamp inside the allowed freshness&lt;br&gt;
window.&lt;/p&gt;

&lt;p&gt;The same rule applies outside infrastructure. If a payment platform reports a&lt;br&gt;
test balance, it cannot prove live revenue. If a bounty marketplace says an&lt;br&gt;
issue is open but the repository says it is closed, the authoritative issue&lt;br&gt;
wins and the conflict should stop the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hash the decision packet
&lt;/h2&gt;

&lt;p&gt;Once the gate evaluates the evidence, Proofline serializes the result in a&lt;br&gt;
canonical order and computes a SHA-256 packet hash. The hash does not make a&lt;br&gt;
weak claim true. It makes the exact decision inputs and output tamper-evident.&lt;/p&gt;

&lt;p&gt;This is useful when an agent runs asynchronously. A reviewer can verify that&lt;br&gt;
the packet being approved is the same packet the gate evaluated. If any&lt;br&gt;
requirement, evidence item, timestamp, or decision changes, the hash changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep external actions behind a human boundary
&lt;/h2&gt;

&lt;p&gt;Evidence can prove that a form is complete; it cannot decide whether a person&lt;br&gt;
wants to submit a legally binding entry, publish a message, or spend money.&lt;br&gt;
Proofline therefore treats those actions as a separate approval state.&lt;/p&gt;

&lt;p&gt;This prevents a common automation mistake: combining technical readiness with&lt;br&gt;
permission to act. The agent can prepare everything and prove that preparation,&lt;br&gt;
but the final side effect remains explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prove the architecture with a live path
&lt;/h2&gt;

&lt;p&gt;The public demonstration runs as a Google ADK application on Cloud Run. An&lt;br&gt;
external request can discover the &lt;code&gt;proofline&lt;/code&gt; app, create a real ADK session,&lt;br&gt;
invoke Gemini, and call the deterministic evaluation tool. The repository also&lt;br&gt;
contains a credential-free test path so the safety boundary can be inspected&lt;br&gt;
without cloud access.&lt;/p&gt;

&lt;p&gt;The deployed demo currently uses in-memory state. Firestore and Pub/Sub are&lt;br&gt;
documented extension points for durable packets and asynchronous rechecks; they&lt;br&gt;
are not presented as active components. That distinction is intentional:&lt;br&gt;
architecture diagrams should separate what is live from what is planned.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical checklist
&lt;/h2&gt;

&lt;p&gt;Before allowing an agent to declare a real task complete, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What exact requirement is being satisfied?&lt;/li&gt;
&lt;li&gt;Which source is authoritative for that requirement?&lt;/li&gt;
&lt;li&gt;Is the observation fresh enough for the decision?&lt;/li&gt;
&lt;li&gt;What happens when two authoritative sources disagree?&lt;/li&gt;
&lt;li&gt;Can the decision be reproduced from structured inputs?&lt;/li&gt;
&lt;li&gt;Does the next step create an external side effect?&lt;/li&gt;
&lt;li&gt;Can a reviewer distinguish deployed components from planned ones?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If those questions do not have explicit answers, the agent probably has a&lt;br&gt;
status message, not proof.&lt;/p&gt;

&lt;p&gt;You can inspect the implementation, tests, architecture, and deployment&lt;br&gt;
evidence in the &lt;a href="https://github.com/ceodaradigu/proofline-agent" rel="noopener noreferrer"&gt;public Proofline repository&lt;/a&gt;,&lt;br&gt;
watch the &lt;a href="https://youtu.be/khPpdq7GcTk" rel="noopener noreferrer"&gt;2:53 live demonstration&lt;/a&gt;, or verify the&lt;br&gt;
&lt;a href="https://proofline-343140361830.europe-west1.run.app/list-apps" rel="noopener noreferrer"&gt;Cloud Run application discovery endpoint&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you want an external evidence audit for a launch or automation, RELAUNCH DEPT. offers a &lt;a href="https://buy.stripe.com/bJe6oJ8PQ3lKgULaCrefC02" rel="noopener noreferrer"&gt;USD 59 evidence audit&lt;/a&gt; and a &lt;a href="https://buy.stripe.com/00wcN75DE5tSfQH7qfefC00" rel="noopener noreferrer"&gt;USD 249 implementation sprint&lt;/a&gt;. These are operational services, not legal, tax, or financial advice.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>agents</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The JSON Error That Hid the Real Failure</title>
      <dc:creator>RELAUNCH DEPT.</dc:creator>
      <pubDate>Sat, 08 Aug 2026 03:38:57 +0000</pubDate>
      <link>https://dev.to/relaunchdept/the-json-error-that-hid-the-real-failure-5da6</link>
      <guid>https://dev.to/relaunchdept/the-json-error-that-hid-the-real-failure-5da6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A migration audit should fail loudly when data is lost. Mine failed loudly too—but, in one edge case, it reported the &lt;strong&gt;wrong failure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The bug lived in a one-command Python showcase built for an open-source Memanto contribution. The command turns a real GitHub discussion into an Open Knowledge Format bundle, runs Memanto's official migration dry run, round-trips the records through production mapping code, and writes a JSON fidelity receipt.&lt;/p&gt;

&lt;p&gt;The happy path was straightforward. The uncomfortable path was not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline and its two kinds of failure
&lt;/h2&gt;

&lt;p&gt;The final audit is a subprocess. It can return a non-zero exit status for two very different reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it completed the comparison and found lost or changed records, while still emitting a valid JSON receipt; or&lt;/li&gt;
&lt;li&gt;it crashed before it could emit valid JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first case is expected domain behavior. We want to preserve its receipt and then propagate the non-zero status. The second is an operational failure. We want the original &lt;code&gt;CalledProcessError&lt;/code&gt;, including its exit code, because that is the evidence that tells a developer what actually went wrong.&lt;/p&gt;

&lt;p&gt;The original control flow captured the subprocess error, but then parsed its output before re-raising it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;audit_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;audit_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

&lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;report_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That looked reasonable until the audit process failed without producing JSON. &lt;code&gt;json.loads()&lt;/code&gt; then raised &lt;code&gt;JSONDecodeError&lt;/code&gt; first. The original subprocess exception—and its meaningful return code—never reached the caller.&lt;/p&gt;

&lt;p&gt;The parser had become an error-mask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducing the hidden branch
&lt;/h2&gt;

&lt;p&gt;The useful breakthrough was to stop thinking of the output as simply “valid” or “invalid” and model two independent signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the process succeed?&lt;/li&gt;
&lt;li&gt;Is its output valid JSON?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That creates four cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Process result&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Correct behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;valid JSON&lt;/td&gt;
&lt;td&gt;write receipt and continue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;failure&lt;/td&gt;
&lt;td&gt;valid JSON&lt;/td&gt;
&lt;td&gt;write receipt, then re-raise the process error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;failure&lt;/td&gt;
&lt;td&gt;invalid JSON&lt;/td&gt;
&lt;td&gt;re-raise the process error; do not create a receipt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;invalid JSON&lt;/td&gt;
&lt;td&gt;surface &lt;code&gt;JSONDecodeError&lt;/code&gt; because the producer broke its contract&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The masked failure was the third row. A regression test simulated an audit that exited with status 7 and printed plain text instead of JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fake_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CalledProcessError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit crashed before producing JSON&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CompletedProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test asserts two things that matter operationally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_showcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;acme/repo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workdir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid audit output masked the process failure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workdir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not merely expect “an exception.” It verifies that the &lt;strong&gt;right exception and exact status code survive&lt;/strong&gt;, and that invalid output is not blessed as an audit artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: preserve causal priority
&lt;/h2&gt;

&lt;p&gt;The correction keeps valid failing receipts, but gives the original process failure priority when JSON parsing also fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt;

&lt;span class="n"&gt;report_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;from None&lt;/code&gt; is deliberate. In the simultaneous-failure branch, the JSON error is a side effect of missing output, not the root cause. Suppressing that context keeps the traceback focused on the subprocess failure the operator needs to investigate.&lt;/p&gt;

&lt;p&gt;At the same time, a valid JSON report from a fidelity failure is still written before the original non-zero result is propagated. That report is valuable evidence; throwing it away would create a different debugging problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed after the fix
&lt;/h2&gt;

&lt;p&gt;The branch now has explicit regression coverage for both failure modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a failed audit with valid JSON preserves the receipt and exit status;&lt;/li&gt;
&lt;li&gt;a failed audit with invalid output preserves the original exit status and writes no receipt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The focused suite reports 25 passing tests, with Ruff checks, formatting, and mypy also clean on the contribution branch. The wider migration demo has additionally completed a 32-record real-data round trip with zero removed or changed portable fields. Those broader results are useful, but the most important outcome of this debugging story is smaller: when the pipeline fails, its diagnostic contract is now trustworthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three lessons I am keeping
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Error handling needs its own truth table
&lt;/h3&gt;

&lt;p&gt;Nested fallible operations create combinations that a linear happy-path reading hides. A small matrix exposed the missing branch faster than another end-to-end run would have.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test identity, not just category
&lt;/h3&gt;

&lt;p&gt;“An exception was raised” would have passed before and after the fix. Checking &lt;code&gt;returncode == 7&lt;/code&gt; proves that causality survived.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Artifacts are part of failure semantics
&lt;/h3&gt;

&lt;p&gt;A diagnostic file should exist only when it is valid. The absence assertion prevents future code from leaving behind a misleading &lt;code&gt;audit.json&lt;/code&gt; after a producer crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/pull/1813" rel="noopener noreferrer"&gt;Open-source PR #1813&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/blob/bb6ae2429d90663c96998a4f519ac3f8fe9fb079/examples/migrations/okf-portability-audit/run_demo.py" rel="noopener noreferrer"&gt;Current orchestrator code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/blob/bb6ae2429d90663c96998a4f519ac3f8fe9fb079/examples/migrations/okf-portability-audit/tests/test_okf_audit.py" rel="noopener noreferrer"&gt;Regression tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The larger PR introduces an OKF portability workflow; this Smash Stories entry is specifically about the real exception-masking bug caught and fixed during its review. The PR is open and mergeable at the time of writing; no merge or bounty award is assumed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI assistance disclosure: AI tools assisted with code review and drafting. The behavior, fix, tests, and validation claims above are linked to reproducible repository evidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>python</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Five Mobile Landing-Page Bugs That Hide in Desktop Review</title>
      <dc:creator>RELAUNCH DEPT.</dc:creator>
      <pubDate>Sat, 08 Aug 2026 03:28:24 +0000</pubDate>
      <link>https://dev.to/relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-20m0</link>
      <guid>https://dev.to/relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-20m0</guid>
      <description>&lt;p&gt;A practical pre-launch QA pass for 320 px, 375 px and 414 px screens.&lt;/p&gt;

&lt;p&gt;A landing page can look polished on a laptop and still lose customers on a phone. The problem is rarely one dramatic failure. It is usually five small defects that make the first action harder than it should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Horizontal overflow that only appears at one width
&lt;/h2&gt;

&lt;p&gt;Test at 320 px, 375 px and 414 px. Look for clipped copy, carousels wider than the viewport, fixed-width tables and decorative elements that push the page sideways. Record the exact viewport and attach a screenshot; “mobile is broken” is not an actionable bug report.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A primary CTA that disappears below the fold
&lt;/h2&gt;

&lt;p&gt;The visitor should understand the offer and see the primary action without hunting. Check whether a tall hero image, consent banner or oversized navigation moves the CTA below the first useful screen. The fix is often hierarchy, not more copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Touch targets that work with a mouse but not a thumb
&lt;/h2&gt;

&lt;p&gt;Buttons and links need enough space to tap reliably. Use 44 × 44 px as a practical minimum, then check the distance between adjacent controls. Tiny close icons, crowded navigation and text-only links are common failure points.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Forms that ignore the mobile keyboard
&lt;/h2&gt;

&lt;p&gt;Verify labels, focus order, error messages, autofill and the keyboard type for email, phone and numeric fields. A form can technically submit and still create enough friction to lose the conversion.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Images that steal the performance budget
&lt;/h2&gt;

&lt;p&gt;Inspect oversized hero images, off-screen media loaded too early and layout shifts caused by missing dimensions. The goal is not a perfect laboratory score; it is a stable first interaction on a real connection.&lt;/p&gt;

&lt;p&gt;A useful QA report should make every finding reproducible: viewport, steps, expected behaviour, actual behaviour, screenshot and priority. That format gives a designer or developer something they can fix immediately.&lt;/p&gt;

&lt;p&gt;I have packaged this process into a fixed-scope &lt;a href="https://contra.com/s/rMYEsYFv-mobile-landing-page-qa-audit" rel="noopener noreferrer"&gt;Mobile Landing Page QA Audit&lt;/a&gt;: one live page, annotated screenshots, a prioritized fix list and one retest, delivered within five business days for $59.&lt;/p&gt;

&lt;p&gt;AI-assisted tools may support analysis; every published finding is reviewed before delivery.&lt;/p&gt;

&lt;p&gt;Originally published by &lt;a href="https://medium.com/@relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-e574f4e6ccc8" rel="noopener noreferrer"&gt;RELAUNCH DEPT. on Medium&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>ux</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
