CLAUDE LABJP
VERSION — v2.1.227 landed on August 10 with no new features, just fixes around plan detection and CI behaviorAUTO — Two days remain until August 14, when auto mode becomes the default in Claude Code for Pro, Max, and TeamCI — Bash commands no longer fail across the board under claude-code-action with allowed_non_write_users on GitHub-hosted runnersBILLING — Sessions started with an expired token could misread your plan and nudge Max users toward usage credits; that is now fixedSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, five days outPRICE — Sonnet 5 promo pricing at $2/$10 per Mtok runs through August 31, moving to $3/$15 on September 1VERSION — v2.1.227 landed on August 10 with no new features, just fixes around plan detection and CI behaviorAUTO — Two days remain until August 14, when auto mode becomes the default in Claude Code for Pro, Max, and TeamCI — Bash commands no longer fail across the board under claude-code-action with allowed_non_write_users on GitHub-hosted runnersBILLING — Sessions started with an expired token could misread your plan and nudge Max users toward usage credits; that is now fixedSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, five days outPRICE — Sonnet 5 promo pricing at $2/$10 per Mtok runs through August 31, moving to $3/$15 on September 1
Articles/Cowork
Cowork/2026-06-27Advanced

Logged as success, but it produced nothing — stopping silent failures in Cowork scheduled tasks with end-of-run assertions

A Cowork scheduled task exits 0, yet not a single artifact was produced. Trusting the exit code alone hides this silent failure. Here is how to turn your definition of done into end-of-run assertions that fail loudly with an evidence log.

cowork13scheduled-task2automation101reliability17

Premium Article

A task you believe is running on schedule keeps logging "SUCCESS" — but you open the output folder and not a single file has appeared since last week. As an indie developer running several sites under Dolice, if you run a handful of unattended Cowork scheduled tasks, you will hit this exact accident at least once. I did, one morning when I sat down to review a batch of logs and realized that a recurring job marked "success" for three days straight had not actually written a single line. My stomach dropped.

The cruel part is that nothing crashed. No exception was raised. The exit code was 0. The scheduler history was green. And yet the deliverable count was zero. This article is about catching that silent success: not by trusting the exit code, but by turning the definition of done itself into assertions that fail loudly.

An exit code does not promise that work happened

We unconsciously read "exit 0" as "it worked." But all an exit code guarantees is that the last command that ran returned 0 — not that the job you actually wanted got done. Those are two completely different propositions.

Silent failure tends to arrive by one of three routes.

RouteWhat happensWhy it stays exit 0
Wrong write targetYou think you generated a file, but it landed in a stale temp path or a directory that doesn't existcat > file itself succeeds. The contents just aren't where you meant
Empty inputYou mistype the path of an input file, and processing proceeds on an empty stringcat wrong-path doesn't error — it returns empty. Downstream "succeeds" on nothing
Commit that never landedAn unset git identity means the commit silently does nothing, and the push goes green with "up to date"There's no diff to push, so the push itself counts as a success

What they share is that every individual command is honestly returning 0. Not one command is lying. And yet the whole thing failed. That is precisely why staring at exit codes from above will never reveal it.

The first time this bit me was a freshly cloned repo where I had forgotten to set the git identity. git commit printed a warning and effectively did nothing; git push came back with "Everything up-to-date." The scheduler history stayed a clean green for three days while the remote gained not one line.

Write your definition of done out loud

The first step toward killing silent failure is not writing code. It is stating, as concrete observable facts, what it means for this job to have succeeded. If that stays vague, you have no way to decide what to assert.

For a recurring job that "reflects generated output into a repo," the definition of done decomposes like this:

  • The output file actually exists and its size exceeds a floor
  • The expected count matches the real file count (for a JA/EN pair, both sides are even)
  • The local commit SHA has changed from its value before the push
  • The remote SHA and the local SHA match

The point is that each of these is a fact you can check from the outside, not a "should be done." Not "I committed" but "the SHA changed." Not "I wrote the file" but "there is a file of at least the floor size at that path." Once you can make that translation, the assertions write themselves.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Stop trusting exit 0 on automation that quietly produced nothing — you'll be able to detect that silent failure mechanically
You'll get a reusable harness that turns your definition of done into end-of-run assertions, writes an evidence log on failure, and exits non-zero
You'll learn to separate three nasty states — empty success, partial success, and double production — using idempotency keys and post-run checks
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Cowork2026-07-05
When Claude Declines a Request on Safety Grounds, What Should an Unattended Pipeline Return?
A third kind of ending that is neither an error nor a normal completion — a safety decline. Here is how to fold it into a pipeline you run unattended, with a classifier and a review-queue design drawn from indie development.
Cowork2026-05-04
Why Cowork Scheduled Tasks Stop Mid-Run and How to Recover
Diagnose Cowork scheduled task failures using measured exit codes and real error output — why safe.directory delays failure instead of fixing it, how to pick a writable root before cloning, and how to structure logs with reason codes.
Cowork2026-07-17
It Worked on My Machine, but Nobody Could Trigger It — Four Assumptions I Stripped Out of a Cowork Plugin
I bundled four working automation skills into a plugin and shared it. Only one of them ever fired. Here is how I measured skill trigger rate, and the four assumptions — vocabulary, paths, connections, and naming — I had to strip out before it was portable.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →