◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/Cowork
◈ Cowork/2026-07-05Advanced

The Two Weeks My Web Monitor Said Everything Was Fine — Field Notes on Catching Silent Misses

A competitor monitor built on Cowork and Claude in Chrome can keep reporting no changes while quietly missing them. Here is how I separated fetch success from extraction success and instrumented the silent failures, with the code I actually run.

cowork16claude-in-chrome4web-monitoringobservability21scheduled-tasks5selector-drift

✦ Premium Article

The Two Weeks My Monitor Said Everything Was Fine

I had a task watching a competitor's pricing page. It crawled three times a day and reported any diff. For weeks the log read a calm row of "no changes," and I took that calm as proof that all was well.

Then one day I opened that competitor's page for an unrelated reason and my finger froze on the trackpad. A top-tier plan's price had moved. A new entry plan had appeared. My monitor had not noticed any of it for two weeks.

The monitor had not crashed. It started on schedule every time, fetched the page every time, and concluded "no changes" every time. It was reporting health while seeing nothing, and it had no idea.

These are the notes on how I traced those two silent weeks and what instrumentation I added so it would never happen again — with the code I actually run. As an indie developer running several sites myself, I am writing this for anyone doing competitor monitoring, price tracking, or change detection on Cowork who would rather not learn it the way I did.

Fetch Success and Extraction Success Are Not the Same Thing

The root cause was that my pipeline collapsed two entirely different outcomes into a single notion of "success."

The fetch succeeded: HTTP 200, real body text in hand. But the extraction — pulling prices out of that text — was failing silently. The competitor had rebuilt the page, and the class names wrapping the prices had changed. My extraction selector matched nothing and returned an empty string. Compare empty to empty, and of course you get "no changes."

StageWhat actually happenedHow the monitor read it
Page fetchSuccess (200, body present)Healthy
Element extractionFailed (selector miss, empty)Misread as healthy
Diff compareEmpty vs empty → zero diff"No changes"

Put plainly, the monitor was translating "could not read it" into "it did not change." Those two mean the opposite things. The first is a fault in the monitor; the second is the monitor working correctly. As long as they share a shelf, faults will forever walk past wearing the face of business as usual.

The first thing to fix was to carry a signal for whether extraction succeeded, entirely independent of the comparison.

✦

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
✦Separating fetch success from extraction success and measuring extraction liveness with content anchors
✦A coverage watcher that treats a too-quiet stretch of zero changes as its own weak alert
✦Structure fingerprinting to catch selector drift, cutting both false positives and silent misses
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-08-23
Not Every Unreachable Connector Means the Same Thing in an Unattended Run
When an unattended task cannot reach a connector, the cause splits into three states: still connecting, unauthenticated, or genuinely absent. Each demands the opposite response. Here is the resolver that tells them apart.
◈ Cowork2026-10-08
The Night I Halved the Instructions I Load Every Time: Three Drawers Before Any Cutting
The longer an instruction file grows, the more rules slip through. Here is how I sorted what gets loaded every time into keep, move, and delete, plus a small script that measures each heading.
◈ Cowork2026-09-08
Until I planted a failing sample, my unattended checks had never once failed
A check running on an unattended schedule lost its exit code to a single pipe added for readable logs. I measured where the status disappears and built a small harness that checks the checker.