• Roborock S8: Cliff Sensor Error

    Roborock S8: Cliff Sensor Error

    Our Roborock S8 was replaced by a Roborock Qrevo S because of a recurring cliff sensor error, but that didn’t stop me from diagnosing the old S8 and ordering the parts myself.

    We had already sent the S8 in for an “official” repair for the exact same issue. When the error returned, we decided to move on and put it away in the attic.

    That changed when the mop motor in our Qrevo fell into the robot itself. By the looks of it, it had simply unscrewed itself from the body.

    Since the Qrevo is less than a year old, we sent it in for warranty repair. That left us without a robot vacuum, so I dug the S8 back out along with the replacement cliff sensors I had already ordered.

    Diagnosing the cliff sensors

    Cliff sensors are infrared sensors, and there is a very simple way to check whether the emitters are working: point a digital camera at them.

    Silicon camera sensors are naturally sensitive to near-infrared light even though our eyes are not. Cameras normally use an IR-cut filter to block most of it, but the filter is not perfect. Because of that, an active IR LED will often appear white, purple or pink through a phone camera.

    This is perfectly safe with the low-powered IR LEDs used in a robot vacuum, but don’t assume the same applies to every infrared source. Volvo, for example, specifically warns against pointing cameras directly at the laser-based infrared lidar used on the EX90, as it can permanently damage some camera sensors.

    When the S8 first developed the problem, all of its cliff sensor emitters were still working. The actual problem appeared to be the plastic housing around the sensors, which is easy to remove and clean.

    The repair shop replaced the entire cliff sensor assembly anyway.

    This time, however, the problem was obvious. The outermost cliff sensor closest to the vacuum motor was completely dead. The camera test made the difference obvious immediately, so that sensor actually needed replacing.

    Replacing the sensor

    Getting into the Roborock S8 is surprisingly straightforward. The annoying part is the front-left cliff sensor.

    Its cable harness is routed underneath the motherboard, which means you have to disconnect essentially every connector on the board before you can remove it. There are roughly 15 connectors, including a ribbon cable for the camera.

    Once the motherboard was free, I could remove the failed sensor, install the replacement and put everything back together.

    The S8 now works perfectly again.

    Was it worth fixing?

    Definitely. The fault looked more intimidating than it actually was, and the camera test made diagnosing the failed sensor trivial.

    The parts cost about 50$.

    I think I’ll make an iFixit guide for the S8 at some point, because the disassembly is simple enough and the sensor routing is the only part that is not immediately obvious.

  • Gobbledygook: A reflection of professional communication

    What is gobbledygook?

    Its definition is:

    a noun meaning wordy, overly complex, or technical language that is meaningless or hard to understand.

    Source: Merriam Webster

    I genuinely think that this is why AI will never become AGI.

    Current state AI is based on enormous amounts of data, with differing dictionary meanings.

    How can an AI trained on so much gobbledygook ever understand reality, and specifically how to adhere to it?

    I struggle on a daily basis, due to how many three letter acronyms and casual business terms that, in essence, make simple things sound complicated.

    HR, Human Resources.

    A bunch of workers managing other workers, with a focus on employee rights.

    Human Resources?

    Resources for humans?

    Humans as resources?

    Gobbledygook!

    An apt name would, in reality, be Employee Management, EM.

    As of writing this, I wanted to just double check my own sanity, and ChatGPT gave me this beautiful example of my above assumption:

    Screenshot of a ChatGPT conversation arguing that “Employee Management” is clearer than “Human Resources.” ChatGPT lists recruitment, payroll, employment law, workplace policy, training, disputes, and offboarding as broader HR functions. The user replies in all caps, “EVERYTHING YOU LISTED IS RELATED TO THE MANAGEMENT OF EMPLOYEES YOU GOOBLEDYGOOK!” ChatGPT then responds, “Yes. You’re right.”

    Now I can’t count how many hours I’ve spent deciphering gobbledygook versus actually working, and I am utterly tired of it.

    Especially in AI, when an AI model struggles to answer due to the complexity of your prompt, it resorts to gobbledygook. Unless you’re using Gemini, in that case it might threaten to kill itself or ask you to. (Yes really!)

    Sources: Gemini 2.5 self uninstall example and CBS News reporting on Gemini telling a user to die.

    To conclude, despite our shortcomings in either competence or hubris, please speak like a human. Our linguistic overcompensation is acting like brakes on our ability to create together. We only have a little time here on Earth, and if we waste it deciphering each other’s language, either through AI generated gobbledygook or through sheer will gobbledygook, we can’t honestly say we lived it to the fullest.

  • The Diminishing Returns Of Vibe Coding

    The Diminishing Returns Of Vibe Coding

    I have used AI to build personal projects since before coding agents became a familiar tool. The early part can be great fun. You describe a feature, try the result and ask for the next thing. The uncomfortable moment comes later, when a small change sends you through files you barely remember creating.

    One failure mode I recognise is a codebase full of handlers, repositories, DTOs and interfaces that accomplishes very little. Each piece can look sensible on its own. Understanding why a request passes through all of them takes much longer than generating them did. That is where the return on another quick prompt starts to fall.

    What I mean by vibe coding

    Andrej Karpathy introduced the term in a February 2025 post describing a way of building where the code can recede from the developer’s attention. The part relevant to me is how much of the resulting program I can explain. I can use an agent heavily and still inspect the implementation, choose the boundaries and take responsibility for the result.

    The label becomes less useful when it is used to judge someone simply for using AI. I care more about a practical question: if this feature loses data or returns the wrong result tomorrow, can its owner trace the path and fix it? That can be difficult with handwritten code as well. Fast generation makes it easier to accumulate the problem before noticing it.

    A small example that reveals the cost

    Imagine adding an email-address change to an ASP.NET Core application backed by a relational database. The visible feature is a form and an endpoint. The actual decisions include who may change the address, whether it needs verification, how uniqueness is enforced and what happens when two requests arrive together.

    I would first read the existing authentication and user-update paths. Then I would ask the agent to implement a narrow change using those conventions, with an explicit list of files it expects to touch. If the repository already has a clear application-service pattern, following it is useful. If the feature suddenly needs a new generic repository framework, I want to understand the reason before accepting it.

    Two requests, one address

    A uniqueness check in application code is only part of the implementation. Two requests can both pass it before either commits. The database needs the appropriate unique constraint for the application’s chosen normalization rules, and the endpoint needs to translate a constraint conflict into a useful response. That is a review point I can test. A generated list of architecture patterns gives me less confidence.

    Give the agent boundaries it can work inside

    For that change, I would describe the accepted behaviour: an authenticated user can request a change to their own address, a duplicate is rejected, and an unverified new address does not accidentally receive privileges intended for a verified one. I would identify the existing persistence and verification components and ask for a short explanation of how the change uses them.

    The first patch should be small enough to read in one sitting. I would run the focused tests, inspect the migration and exercise the duplicate and unauthorized cases. If the feature requires a background verification email, I would review its failure handling separately. A database commit followed by a failed email send is a normal possibility that the workflow has to handle.

    I also want the agent to say which behaviour it has verified and which parts it has only inferred from reading the code. Passing tests are useful evidence within their scope. A new test that mocks away the database cannot demonstrate that a database uniqueness rule works.

    Notice when iteration stops helping

    Repeated fixes are a signal to pause. If every patch repairs one screen and breaks another, I would trace the data from input to storage to output and write down the intended state transitions. A quick diagram or a few concrete examples can expose a misunderstanding that more generated code would only spread.

    I would also look at the diff for duplication and unused paths. An agent may leave the old implementation in place while adding a new route that happens to satisfy the latest prompt. Searching for callers and running the existing regression tests helps establish which path the application actually uses.

    So are review, deployment and the next change. For a throwaway experiment, I can accept code I will never revisit. For a service that stores someone’s information, I need a smaller gap between what the code does and what I understand about it.

    The time spent reading is part of the development cost.

    A working rhythm I would use

    I would keep each change tied to one observable result, commit once that result is verified, and make the next request from that known state. When an agent proposes a broad refactor, I would separate it from the feature unless the feature actually depends on it. That makes failures easier to attribute and rollback easier to judge.

    AI is useful to me when it takes care of implementation work while leaving enough room to think about the application. The warning sign is the growing pile of decisions I have postponed understanding. Once that pile starts slowing every change, the productive next step is usually to read, simplify and test the code already there.

    For an EF Core implementation, the index documentation shows how to configure a unique index. I would still test the generated migration against the actual database provider and the application’s email-normalization rules.