Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

On a Power Trip

20 July 2026 at 10:17
My laptop is one of my most important tools. While my servers and office systems have all of my configured software and documents, I can't take them with me on customer trips, or even to the living room for some late-night catching up while watching TV. The laptop is basically my portable window into my office.

I don't need a powerful laptop. I'm not a gamer and I rarely develop software directly on it. The biggest applications I use are Impress for presentations and VLC for watching movies on airplanes. Most of the time, I'm simply accessing websites, running diagnostics, or remotely logging into my office. (If someone were to steal my laptop, they won't get much. They can't access the office without my passwords and biometrics. If it ever were stolen, I can immediately lock down all network access to my office with a single unpublished URL.)

More Laptop

Last year, I wrote about my laptop. Back then, the Windows 10 operating system was hitting end-of-life and needed to be replaced. The final straw was the "Patch Tuesday" where the laptop sat at "Restarting" forever. Since the laptop is only used for remote access, there was nothing that needed keeping. I ended up reinstalling it with Ubuntu Linux.

This OS switch came with a few pleasant surprises:
  • The laptop was significantly faster. (Windows is a resource hog!)

  • The hard drive had a lot more room. (Linux is smaller than Windows.)

  • Restoring the network from suspend worked perfectly. This had been a problem under Windows.

  • The original battery lasted 8-9 hours under Windows, but had aged to lasting 4-6 hours from a full charge. With Linux, I was getting 10-12 hours of use from the same hardware.

  • I had some touchpad issues under Windows. Switching to Linux made those issues mostly go away.

Touchpad

While the touchpad issues were mostly resolved, they weren't completely gone. The mouse cursor would move correctly, but sometimes the mouse buttons would become non-responsive or require multiple presses before they worked. A reboot would fix the problem temporarily, so I didn't think it was the hardware wearing out.

Under Windows, I found a few other people with the same problem, but "reboot Windows" was the cure for everything. With Linux, there are enough tools for a real diagnosis and easy fix.

The laptop communicates with the touchpad using a two-wire protocol called I2C. When the laptop suspends and restores, the I2C drivers can get into an inconsistent state, causing the buttons to fail. The solution? I created a system restore script that restarts the I2C drivers when it wakes up. With Ubuntu, create the executable file "/lib/systemd/system-sleep/restart-touchpad":
#!/bin/sh
case "$1" in
post)
# Unload the ACPI and I2C drivers
rmmod i2c_hid_acpi
rmmod i2c_hid

# Reload them for a clean reset
modprobe i2c_hid
modprobe i2c_hid_acpi
;;
esac
That's it. You don't need to restart anything. Now the touchpad works properly all of the time.

Old Hardware

I usually keep hardware until it stops working. For example, I had an old Pentium computer with a 120MB hard drive that I used as my mail server for over 20 years. OS patches? Ha! It was still running Redhat 5.1! (Old hacker security tip: nobody looks for 20-year-old vulnerabilities, and newer vulnerabilities didn't work on old systems.) In my opinion, as long as the system is stable, why risk replacing it? The only reason I retired that old mail server was that everyone was moving to TLS for secure email transfers and some of the OpenSSL dependencies were too complicated to port to the old system. The 30+ year old hardware itself still worked fine.

The same goes with laptops. For someone who has been in the computer field for over 40 years, I've only ever owned four laptops. My first one was an Apple. (Never again.) It lost OS support after 2 years. However, I didn't move off of the laptop until the browser providers (Chrome and Firefox) stopped supporting it. I needed a modern browser, so that meant a modern laptop.

My Asus EeePC was my favorite because it was tiny and lightweight. However, after a decade most OS's dropped support for the Atom processor, so I had to update again.

These days, I'm using a Dell XPS that I purchased in 2017. The hardware is designed to last, the only issue was the touchpad -- and that's fixed now. That just left the battery.

Battery

No laptop batteries last forever. With lithium-ion, they start with a long lifespan and then slowly degrade over time. However "slowly" isn't linear. After a few years, you'll start seeing the battery runtime decline, and as time passes it will decline very rapidly. When it's completely dead, it might hold a charge for five minutes.

Lithium-ion batteries typically last seven to ten years, although heavy cycling, deep discharges, and heat can shorten that lifespan. My laptop was from 2017, putting it well into the "old battery" range. When it was new, it could hold a charge for 8-10 hours while running Windows. After eight years, Windows was lasting 4-6 hours before I switched to Linux. Linux lightened the power requirements, bringing it back to a 10 hour battery. That doesn't mean that the battery is fresh; it just means that the new OS was more power efficient.

Over the last year, it had entered the fast decline that is typical for lithium batteries. Last month, a full charge was lasting 2.5 - 3.5 hours (still under Linux). If I can't last an entire airplane flight, then that's effectively a dead battery. While I'm thrilled to have had nearly 9.5 years out of this battery, I had to make a choice:
  • (A) Get a new laptop. These days, that would cost me $900 - $1500.

  • (B) Get a new battery. I saw prices that varied from $25 to $100.
My thought: if I could get a new battery and maybe another 7 years of life out of this laptop, then it was definitely worth it. (Also, I wouldn't have to lose all of the stickers I had plastered on the laptop.) In the worst case, either a new battery wouldn't help or I'd damage the laptop while swapping batteries. But for under $100? I was willing to experiment.

The huge price range really bothered me. As far as I can tell, all of the sub-$75 batteries were from pop-up providers. Vendors who were here today and gone tomorrow. Each had reviews that ranged from "5 stars: It works!" to "1 star" with long paragraphs about all of the problems and non-responsive vendors. Even though the batteries were all marketed as "new", they were probably "newly rebuilt" and not really "new".

Dell no longer makes this battery, but a few companies still have good reputations for selling genuinely new batteries rather than rebuilt packs. I had never purchased from iFixIt before. And now that I have, I highly recommend them. (I am not a paid spokesperson, I'm just a very happy customer. As an aside, I often blog about problems with vendors. This time, I only have positive things to say.)

The battery was affordable (under $100 and with free shipping). It arrived on time. It arrived well-packaged and undamaged. (This is always a concern with lithium batteries.) It said that the package included a small toolbox, but that wasn't part of my decision process. Now that I've used it, this is one of the nicest toolboxes I've ever had for repairing equipment. It includes:
  • A metal shim, for prying open lids without cracking the tabs.

  • A bunch of plastic shims, so the lid doesn't close while sliding the metal shim around the seams.

  • Every screw driver bit size you might need.

  • High quality tweezers.

  • A plastic tool that is great for helping peel up tape.

  • A suction cup, in case you're repairing a cellphone screen.

  • Even the toolbox lid is well-designed, with grids for holding screws. I populated it with the screws I pulled out (each type and location went in a different holder) and put the screwdriver bit next to it as I went.
I found out the hard way that it is designed for use with one hand! With my laptop, I had removed the screws and was using the metal shim to pry off the back. I realized that I needed a plastic shim to prevent the lid from snapping back on while I worked. With one hand, I held the metal shim in the lid. With the other hand, I was able to push down on one side of the plastic shim and have it pop up so I could grab it. I didn't realize that there were multiple plastic shims until they popped up and exploded all over the desk. This was a very pleasant surprise.

Here's the toolbox:

(Be careful pushing on the blue plastic triangular shims in the middle. There are a bunch of them and they will all suddenly pop out!)

And here's the laptop mid-replacement:

(The old battery is off the top of the photo. The new battery is the black rectangle in the top center. It goes over the touchpad, which is the green board at the bottom of the screen.)

A few years ago, I tried to replace the battery in my Samsung tablet. I had a hodgepodge collection of tools and ended up destroying the tablet. I was worried about doing the same thing to the laptop. But with the right tools, going slowly, and taking photos, I managed to replace the battery without any problems in under 30 minutes. (Now that I know what I'm doing, I could probably do it in 10 minutes without feeling rushed.) It was truly painless.

Calibration

After swapping the battery, the laptop wouldn't turn on. That's fine -- the new battery shipped without a charge. After 10 minutes of charging, I could turn the laptop on. (Good! I didn't break anything.)

The next step is to calibrate the battery. This isn't for the battery's health; it calibrates the software that reports how much power remains.
  • Typical batteries: With regular lead-acid and alkaline batteries, the output voltage is pretty linear. You can measure the voltage to determine the battery's remaining capacity.

  • Lithium-ion batteries: Lithium-ion batteries have a long, flat discharge rate. You can't just look at the voltage and determine how much battery time is left. During the flat discharge rate, the micro-voltage differences can be too small for the hardware to detect; there may be no measurable difference between 30% and 70% capacity. To estimate the remaining time, the OS uses a combination of measured voltage and a timer for how long it took to drain. For the calibration, you put it through a full charging cycle, full discharge, and full charge again. This helps the software guestimate the capacity during the flat discharge rate.
My laptop's battery is rated at 7.6V and 60Wh. With Windows, I was getting nearly 10 hours with the original battery. But now I'm on Linux, which consumes much less power. I had no idea how long this new battery would last.

To calibrate with Linux, you should remove the power history. This forces it to learn based on the new battery.
sudo systemctl stop upower
sudo rm /var/lib/upower/history-*
sudo systemctl start upower
Next, fully charge the battery. Let it charge for at least two hours beyond "fully charged".

The full discharge step is kind of a challenge, since the OS wants to be as efficient as possible. Turn off power-saving mode, turn off the screen saver, turn off suspend, etc. I gave it something to do: play the movie "The Bourne Identity" over and over until the battery was fully drained. (The computer will warn about low voltage, and then shutdown automatically. That's the full discharge.) With this new battery? I expected it to last for 12 or 14 hours. Instead, it ran for 30 hours! (I suspect that it was using a hardware-based video decoder which is very power-efficient, and letting the CPU itself effectively rest and consume flea power.)

The final full charge cycle probably only needed a few hours, but I let it go overnight.

With the new battery installed and calibrated, Linux reports "15 hours remaining". After five hours of use, I still have "14 hours remaining", and if I start compiling code, it drops to "10 hours remaining." I'm not too worried about the calibration's accuracy since it may take the OS time to learn. I might not be able to tell the time remaining with extreme accuracy, but I'm sure it will last an entire plane flight on travel days.

Right to Repair

There's an entire movement centered around the right to repair equipment. Being able to change a battery in a working device is one of those basic tenets. My Samsung tablet appeared designed to self-destruct when opened. My Dell laptop was built to be repaired, and the tools from iFixIt simplified this process. I'm sure my laptop is good for at least another seven years.

In my home town of Fort Collins, they are building a new library. This one will include an "innovation maker-space". They recently had an open house to discuss wants and needs with the community. People wanted everything from a 3D printer and laser cutter to sewing machines, button makers, and classes on gardening. One of the things that was repeatedly mentioned by attendees was a repair station. Whether it's a team of volunteers, one-time hands-on classes, or something in between, people have a strong desire to repair electronics before buying a replacement.

My successful weekend project is exactly why community maker-spaces are so vital. When manufacturers design hardware to be opened, and companies like iFixIt provide the exact toolkits to do it safely, fixing our own tech transitions from a stressful gamble to a rewarding afternoon project. We don't need to throw away perfectly good silicon just because a battery gets old. Keeping this laptop out of a landfill isn't just a win for my wallet, it's a small victory for a more sustainable, fix-it-first mindset.

The combination of a lightweight Linux OS, a fresh battery, and the right tools completely resurrected a piece of hardware that most people would have recycled years ago. It may not be the latest or greatest, but it's perfect for the next time I leave the office.

Beyond grep: The case for a context-rich AI coding harness

20 July 2026 at 07:20

There are a lot of AI coding applications out there, and as impressive as large language models and the agents they enable have become, many of the most recent developments in AI-assisted development have been in the software that manages those models, not just the models themselves.

Earlier this summer, I spoke with the head of product for Claude Code, Anthropic's Cat Wu, about that company's approach to building that software.

Read full article

Comments

© Augment Code

Rust Will Help Linux Succeed and Makes Coding Fun, Says Greg Kroah-Hartman

20 July 2026 at 00:20
ZDNet reports on June's Open Source Summit India 2026 in Mumbai, where Linux stable kernel maintainer Greg Kroah-Hartman gave a talk titled "Rust and Linux: How the Rust Language is Going to Help Linux Succeed." Kroah-Hartman said in his keynote that "the [Linux] kernel is moving toward Rust. Git is moving toward Rust. Lots of projects are starting to move toward Rust." He didn't always feel that way. Kroah-Hartman added, "A number of years ago, when a friend of mine said, 'Ah, you got to try this new language. It's called Rust.' I was like, 'What? No, C is great.' His friend continued, "'No, no, no! It makes programming fun again.' I'm like, 'Nah, programming is fun in C.' He was right. I should have done it then. Rust is actually fun. It makes programming fun. It takes a lot of stuff away from having to worry about the compiler, which can fix a lot of your problems for you, and it makes code a little bit better." So, Kroah-Hartman has moved from being a Rust skeptic to one of its strongest champions inside the kernel. He now regards Rust as a permanent part of Linux, not an experiment. His case is straightforward: Rust's ownership and type system can eliminate most of the "stupid little tiny things" that dominate kernel Common Vulnerabilities and Exposures (CVEs), while making life easier for overworked maintainers. "Rust," in short, "makes my life so much easier...." In India, he said Linux sees "about 13 CVEs a day" and has been running at "almost nine changes an hour" for a decade or more. Most of those vulnerabilities, he argued, are not exotic attacks but simple C mistakes — unchecked pointers, forgotten unlocks, and sloppy cleanup paths: "This is what we're fixing 13 times a day. Small, trivial, little bugs like this all the time.... I've seen every CVE the kernel has done in the past 25 years. I think 80% would be gone, just because they would be caught by Rust." The remaining 20% are the logic bugs he'd prefer to focus on...." Moreover, Rust is becoming the default for new work in key subsystems. "New drivers for some subsystems are only going to be accepted in Rust...." he said. Binder, the Android IPC mechanism at the heart of billions of devices, now has parallel C and Rust implementations in the kernel. The C version "will go away soon," leaving the Rust version "as the bedrock of all Android devices going forward."

Read more of this story at Slashdot.

Beyond Signals and Observables: Microsecond Reactivity for Complex Graph Data Structures in…

15 July 2026 at 11:52

Beyond Signals and Observables: Microsecond Reactivity for Complex Graph Data Structures in TypeScript

Why fine-grained reactivity libraries break down when scaling past nested states, and how flat-map semantic graphs unlock pure \(O(k)\) propagation without wrappers or memory leaks.

The modern frontend and edge ecosystem is currently undergoing a reactivity revolution. Over the past few years, the web development community has rightfully moved away from heavy, coarse-grained virtual DOM diffing toward fine-grained updates. Modern frameworks have almost universally consolidated around Signals (Preact, SolidJS, Angular, Vue) or Observables (RxJS) to synchronize state directly with the execution layer [neurons-me.github.io].

For linear UI updates — like toggling a modal, changing a username, or validating a single form field — Signals are highly effective.

However, when engineering complex, relational, or multi-domain graph data structures (such as real-time geospatial tracking, peer-to-peer social meshes, or concurrent multi-agent simulations), the core assumptions behind standard Signals and Observables break down completely [neurons-me.github.io]. They introduce massive proxy wrappers, complex runtime dependency subscription overhead, and catastrophic memory leak vectors.

To scale past these limitations without sacrificing performance, systems must bypass deep runtime tracking and move toward in-memory semantic trees that achieve pure \(O(k)\) data state propagation at microsecond scales [neurons-me.github.io].

The Hidden Cost of Signals and Observables at Scale

To understand why traditional reactive patterns struggle with complex graph structures, we must look at how they manage dependencies under the hood:

[ Traditional Signals / RxJS: Heavy Wrapper Proxy Tree ]
State Mutation ──► Proxy Wrapper ──► Subscriptions Array Loop ──► Dynamic Re-evaluation (Prone to Memory Leaks & O(N) Cascade)

[ Flat Semantic Graph (.me): Static Address Resolution ]
State Mutation ──► Flat Hash Map Path Lookup ──► Pure O(k) Dependency Jump (Executed in 0.045ms)

GitHub - neurons-me/.me: Here we're codependently creating .me while it concurrently creates us.

  1. The Wrapper/Proxy Bloat: Signals require wrapping primitive values inside dynamic object containers or JavaScript Proxies. When scaling an architecture to hundreds of thousands of active relational nodes, these wrappers destroy JavaScript engine (V8) optimizations [neurons-me.github.io]. They create millions of separate internal heap allocations, inflating memory usage and triggering severe Garbage Collection (GC) pauses.
  2. The Dynamic Subscription Maze: When computed values depend on multiple dynamic variables, reactive frameworks must continuously track subscriptions at runtime. In complex graphs featuring frequent cross-node pointers and multi-directional flows, this leads to exponential dependency tracing overhead and hard-to-debug Circular Reference Deadlocks.
  3. Memory Leaks and Dangling Subscriptions: In a graph data structure where nodes are added or removed dynamically (such as a changing traffic simulation), explicit subscription hooks must be meticulously cleared. A single forgotten unsubscription or detached proxy holds an entire branch of the graph in memory, causing fatal application memory leaks.

The Architecture: Flat Semantic Keys and Invariant O(k) Jumps

The solution to the scale bottleneck does not involve building a smarter proxy or a faster subscription array. It requires decoupling the reactivity model from object nesting entirely [neurons-me.github.io].

By using a continuous semantic namespace modeled as a Flat Key-Value Map, data paths are stored as flat strings (e.g., affinity.targets.2.score, users.pablo.isAdult). This flat layout unlocks immediate \(O(1)\) hash-map lookups directly inside the runtime memory space [neurons-me.github.io].

>>> Running Concurrent_Storm.ts
╔══════════════════════════════════════════════════════════════╗
║ .me — Concurrent Storm: 1000 events ║
╚══════════════════════════════════════════════════════════════╝

1,000 mutations processed: 44.85ms
Per-event resolution latency: 0.045ms
Maximum sustained throughput: 22,294 events/sec
explain().k on last event: 3
explain().recomputed: ["geo.13981.blackout","geo.13981.gridlock","geo.13981.alert"]

When a variable changes in a flat semantic graph, the engine relies on hardcoded, explicit dependency metadata (dependsOn) generated at the node's origin [neurons-me.github.io]. Instead of dynamically discovering what changed at runtime, the engine performs a precise \(O(k)\) deterministic jump across memory boundaries:

  • N (The Application Data Matrix Size): Up to 1,000,000 active keys.
  • k (The Target Impact Factor): The explicit number of downstream nodes bound to that mutation.

By keeping the resolution complexity strictly bound to \(k\) instead of \(N\), a high-concurrency stream like Concurrent_Storm.ts can easily process 22,294 events per second on a standard monohilo client environment [neurons-me.github.io]. Each individual update resolves in an average of 45 microseconds [neurons-me.github.io].

Contextual Node Awareness: Beyond Flat Values

Standard reactivity frameworks evaluate expressions globally, assuming that a value means the exact same thing to every consumer. However, advanced systems require Context-Aware Policies, where data changes its operational meaning based on the consumer’s environment [neurons-me.github.io].

In an in-memory semantic tree, variables are resolved dynamically through cross-node pointers. For example, in a robotics simulation, multiple distinct autonomous agents (Loader, Nurse, Surgeon) can point to the exact same physical asset (objects.canister7) [neurons-me.github.io].

The asset itself remains a stable data structure, but as its attributes change (e.g., changing sterilization status), the downstream reaction is evaluated through the unique lens of each robot’s environment context [neurons-me.github.io]

explain("robots.nurse.canProceed") -> {
"value": true,
"expression": "canLift && softGripReady && !needsHumanReview && contextAllowsMotion",
"inputs": [
{ "label": "canLift", "value": true, "origin": "public" },
{ "label": "needsHumanReview", "value": false, "origin": "derived" }
],
"dependsOn": [
"objects.canister7.sterile",
"contexts.hospital.sterileZone"
]
}

The system automatically resolves these deep dependency trees across entirely different domains (from physical object tracking to strict internal safety constraints), updating complex authorization states across the board in real time without manual sync steps [neurons-me.github.io].

Engineering Sovereign Data States

Moving past the overhead of traditional Signals and Observables allows us to rethink state management entirely. Developers no longer need to compromise between fine-grained reactivity and memory efficiency [neurons-me.github.io].

By migrating to flat, explicit semantic maps, you can scale data layers to millions of interdependent elements while ensuring lightning-fast performance and total runtime predictability on client hardware [neurons-me.github.io].

Take the Next Step into Sovereign Computing

The code behind these microsecond-level reactive benchmarks is open-source and ready for production testing.

  • Explore the reactive engine and run performance benchmarks on your local machine via GitHub (neurons-me) [neurons-me.github.io].
  • Read the foundational mathematical theory and deep-dive essays into the Algebra of Digital Spaces at Sui Gn on Substack.
  • Review the technical API documentation, stable interfaces, and typedocs at neurons-me.github.io [neurons-me.github.io].

Beyond Signals and Observables: Microsecond Reactivity for Complex Graph Data Structures in… was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Linus Torvalds on Rust, C, Bugs, and AI Patch-Checking Tools

13 July 2026 at 07:34
"Git and email are the two really only tools I use," Linus Torvalds said at Open Source Summit India 2026. But ZDNet reports that he also shared his thoughts on Rust, C, and patch-checking tools: "I use Google as a way to look things up." He added, "I'm unusual; most of the other maintainers end up using many more tools, and I think a lot of them are starting to use AI tools for patch checking," while he "works at a higher level. I work with people, not tools." When asked about Rust both in Git and the kernel, he pushed back against hype: "I'm not sure Rust is going to take over the world. I still think Rust is very interesting, [but] I still find C to be a much simpler tool." Torvalds continued, "I'm much more excited about all the tools we have for verification of C," including "automated patch verification tools" and "automated email checking tools for patches like Sashiko." Summing up, Torvalds told the Mumbai audience: "I'm more of a hack-and-slash kind of person, and I still like the raw and simple power of C, and I don't think that's going to change." Torvalds also warned against overestimating Rust's benefits: "Rust fixes a few easy bugs that you can make in C, but it does not fix the logic errors, right? It does not think for you, and when you write incorrect code, the language does not matter. The end result will be incorrect." On mixed C/Rust code bases, he pointed out that guarantees are limited: "The guarantees that Rust give you only apply in the Rust-only parts of your code base, and wherever you interact with C code, all bets are off," with most Rust code in Linux talking to "core kernel C code" that is "much better quality... because that code has been tested in every single environment." At the same time, Torvalds pointed out, "some of our big and more high-profile bugs in the kernel lately have been logic errors" rather than the kind of memory errors Rust prevents. "It was just bad programming, which sadly happens even in carefully maintained subsystems and important kernels that are supposed to be very secure."

Read more of this story at Slashdot.

What Is Agentic AI? Why Businesses Are Choosing Agentic AI Development Companies in 2026

9 July 2026 at 11:33

Agentic AI is transforming how businesses automate operations, make intelligent decisions, and boost productivity. Learn why companies are investing in Agentic AI development in 2026

Why Businesses Are Choosing Agentic AI Development Companies in 2026

Artificial intelligence has already transformed the way businesses communicate, analyze data, and automate routine tasks. However, a new phase of AI is emerging in 2026 one that goes beyond responding to commands. Instead of waiting for instructions, modern AI systems can understand goals, plan actions, make decisions, and complete complex workflows with minimal human involvement. This advancement is known as Agentic AI, and it is changing how organizations approach automation. As businesses look for smarter and more adaptive solutions, the demand for an experienced Agentic AI Development Company is growing rapidly across industries.

Understanding What Makes Agentic AI Different

Traditional AI systems usually perform a single task after receiving a specific instruction. Agentic artificial intelligence, on the other hand, is not simply designed to respond to prompts; rather, it is intended to work toward certain goals. It can analyze situations, break large goals into smaller tasks, choose appropriate actions, and adapt when circumstances change. This ability makes autonomous AI agents more suitable for business environments where decisions and workflows are constantly evolving. Instead of automating one process at a time, organizations can automate complete business operations with greater intelligence.

Why Businesses Are Moving Beyond Traditional Automation

Many companies have already automated repetitive activities such as email responses, appointment scheduling, and customer support. While these improvements save time, they often require continuous human supervision. Businesses now want systems that can manage interconnected tasks, coordinate between multiple applications, and respond to changing conditions automatically. This shift has increased interest in AI business automation powered by intelligent agents. Companies are no longer looking for simple automation; they want technology that can think, prioritize, and execute workflows with minimal intervention.

The Growing Role of Agentic AI Development Companies

Building intelligent AI agents requires expertise in machine learning, workflow orchestration, language models, data integration, and enterprise software architecture. This is why many organizations choose to work with an Agentic AI Development Company instead of developing everything internally. Experienced development teams understand how to design secure, scalable, and reliable AI systems that align with business objectives. They also ensure that AI solutions integrate smoothly with existing software, allowing businesses to adopt intelligent automation without disrupting daily operations.

Industries Already Exploring Agentic AI

The flexibility of enterprise AI solutions allows Agentic AI to support a wide range of industries. Healthcare providers use intelligent agents to coordinate patient scheduling and administrative workflows. Financial organizations automate compliance monitoring and document processing. Manufacturing companies optimize supply chain activities through intelligent workflow automation, while retail businesses improve inventory planning and customer engagement. These examples show that Agentic AI is not limited to one sector; it is becoming a valuable technology for organizations seeking greater efficiency and faster decision-making.

Intelligent Automation Is Becoming a Competitive Advantage

Businesses that adopt AI-powered business processes are discovering benefits beyond simple time savings. Intelligent agents can reduce operational delays, improve consistency, analyze large volumes of information, and respond more quickly to changing business conditions. As competition increases across industries, organizations need technologies that help them operate efficiently while maintaining high service quality. Agentic AI provides this advantage by combining automation with intelligent decision-making, enabling businesses to achieve better outcomes with fewer manual processes.

Multi-Agent Systems Are Expanding Business Capabilities

One of the most exciting developments in Agentic AI is the use of multi-agent AI systems. Instead of relying on a single intelligent agent, businesses can deploy multiple AI agents that collaborate to complete complex objectives. One agent may collect information, another may analyze data, while a third executes actions or generates reports. This collaborative approach improves efficiency and allows organizations to automate end-to-end workflows that previously required coordination across multiple departments.

Choosing the Right Agentic AI Development Company

Selecting the right development partner is one of the most important decisions for any business investing in intelligent automation. A reliable Agentic AI Development Company should understand both AI technologies and business processes. Expertise in AI software development, secure system architecture, workflow integration, and scalable deployment guarantees that AI solutions persist in providing value as business needs change. Companies should also evaluate the provider’s ability to customize solutions instead of offering one-size-fits-all products, since every organization has unique operational goals and challenges.

Long-Term Business Benefits of Agentic AI

Businesses investing in Agentic AI are preparing for long-term operational improvements rather than short-term automation. Intelligent agents can streamline decision-making, improve resource allocation, reduce repetitive manual work, and support employees with real-time recommendations. These capabilities contribute to better business process optimization, higher productivity, and faster response times across departments. As organizations continue their digital transformation journey, Agentic AI is becoming a strategic technology that supports sustainable growth while helping teams focus on innovation instead of routine administration.

The Prospects for Artificial Intelligence in Business Organizations in 2026 and Beyond

Artificial intelligence continues to evolve from simple automation into intelligent collaboration. Future AI productivity tools are expected to coordinate with enterprise software, understand business priorities, and adapt to changing objectives with minimal human supervision. Combined with generative AI integration, intelligent agents will assist with planning, reporting, customer interactions, and operational management. Businesses that begin exploring Agentic AI today will be better positioned to adopt these innovations as enterprise automation becomes increasingly intelligent, connected, and goal-oriented.

Final Thoughts

Agentic AI represents a significant step forward in the evolution of business automation. Instead of completing isolated tasks, intelligent AI agents can plan, adapt, collaborate, and execute workflows that support real business objectives. This shift is encouraging organizations across industries to partner with an Agentic AI Development Company capable of building secure, scalable, and customized AI solutions. As demand for custom AI solutions, intelligent automation platforms, and enterprise AI implementation continues to grow in 2026, businesses that invest early will be better equipped to improve productivity, accelerate digital transformation, and remain competitive in an increasingly AI-driven world.


What Is Agentic AI? Why Businesses Are Choosing Agentic AI Development Companies in 2026 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Gas Optimization & Auditing Tips

9 July 2026 at 11:31

How Does a Compiler Actually Work?

Image: Grok AI

Solidity is the dominant high-level programming language for writing smart contracts on Ethereum and compatible EVM blockchains. However, the Ethereum Virtual Machine (EVM) cannot execute Solidity code directly. It requires low-level bytecode consisting of opcodes and data.

The Solidity compiler (solc) bridges this gap by translating human-readable Solidity into EVM-executable bytecode. Understanding how and why the compiler works is essential for writing secure, gas-efficient, and maintainable smart contracts. It helps developers avoid common pitfalls, leverage optimizations effectively, debug issues, and ensure contracts can be verified on explorers like Etherscan.

The primary implementation is solc, a C++ compiler maintained by the Solidity team (with solc-js as a JavaScript port via Emscripten). It takes Solidity source code (.sol files) as input and produces multiple outputs, including:

  • EVM bytecode (creation and runtime)
  • Application Binary Interface (ABI)
  • Contract metadata
  • Gas estimates
  • Abstract Syntax Tree (AST)
  • Assembly representations
  • And more (via the Standard JSON interface)

In modern versions (Solidity 0.8.x series, with documentation referencing 0.8.36-develop as of mid-2026), the compiler supports two main compilation pipelines:

  • Legacy pipeline (default): Direct translation from analyzed Solidity to bytecode.
  • IR-based pipeline (viaIR: true): Solidity → Yul intermediate representation → optimization → bytecode. This path generally enables superior optimizations.

Fun fact, inside the solidity compiler, there are two Solidity languages. 3 if you count Core. And 4 if you count Fe! Thx Daniel for spotting this funny fact.

What Does It Actually Do?

First of all, we must note that compilers essentially take text, parse and process it, then turn it into binary for your computer to read. This keeps you from having to manually write binary for your computer, and furthermore, allows you to write complex programs easier.

In other words, the compiler converts high-level source code to low-level code. Then, the target machine executes low-level code. The compilation process consists of several phases:

  • 1. Lexical analysis
  • 2. Syntax analysis
  • 3. Semantic analysis
  • 4. Intermediate code generation
  • 5. Optimization
  • 6. Machine Code generation

To proceed to the next topic, we must first understand how this occurs in Solidity and, as a result, how we can use it to audit and write code safely. It’s critical to understand the specifics of the process we’ll go over below:

  1. Lexing and Parsing
    The source code is broken into tokens (lexer) and then structured into an Abstract Syntax Tree (AST) (parser). This captures the syntactic structure of contracts, functions, variables, inheritance, etc.
  2. Semantic Analysis
    The compiler performs type checking, resolves names, handles inheritance (using C3 linearization), checks for errors (e.g., visibility, mutability), and analyzes control flow. It also processes pragmas (e.g., pragma solidity ^0.8.0;) and library linking.
  3. Intermediate Representation (IR) Generation (especially in viaIR mode)
    The analyzed code is translated into Yul, a low-level but human-readable intermediate language. Yul uses constructs like functions, if/switch/for loops, and variables while abstracting away raw EVM stack manipulation (DUP, SWAP, JUMP).
    Yul serves as a clean target for optimizations and can also be written directly (via inline assembly or standalone Yul contracts).
  4. Optimization
    This is one of the most important stages. The optimizer runs at multiple levels:
  • Yul optimizer (powerful in the IR pipeline):
    Applies passes such as common subexpression elimination (CSE), function inlining, dead code elimination, loop-invariant code motion, constant folding, and more.
  • Opcode/peephole level: Simplifies instruction sequences.
  • Configurable via — optimize (or optimizer.enabled: true) and — optimize-runs (default often 200).
    Low runs values prioritize smaller deployment bytecode (cheaper to deploy). High values prioritize runtime gas efficiency.

5. Code Generation
The optimized representation (Yul or direct) is converted into EVM bytecode. This includes generating function selectors (via keccak256 of signatures), handling storage/memory/calldata layouts, events, and constructors. The compiler also appends CBOR-encoded metadata (containing compiler version, settings, and a hash) to the end of the bytecode (unless disabled).

6. Output Generation
The compiler produces all requested artifacts based on the output selection.

What Does the Compiler Actually Do to Solidity Code?

We can roughly break down the entire process into the following three phases:

a) Splits code into tokens

b) Analyzes syntax

c) Constructs an AST (abstract syntax tree)

What Does the Compiler Do With AST?

Here we can also divide the entire process into three phases, which are listed below:

a) Analyzes semantics (at this point compiler errors are exposed/derived!)

b) Optimizes AST (that’s what runs value in the project’s config is specified for — check out this example!)

c) Generates bytecode!

Here is a simple example of some of the compiler’s phases:

Source: My Own Screenshot

The design is driven by fundamental constraints of the EVM:

  • EVM is a stack machine with a hard limit of 1024 stack items and expensive operations (especially storage writes).
  • High-level abstractions in Solidity (mappings use keccak256 hashing for storage slots, inheritance packs variables according to C3 linearization, structs/arrays have specific packing rules) must be translated into raw storage slots (0, 1, 2, …), memory, and calldata.
  • Gas is money: Every opcode has a cost. The compiler and optimizer exist to minimize both deployment size and execution gas without changing semantics.
  • Security and determinism: The compiler enforces rules (e.g., overflow checks by default since 0.8.0) and produces verifiable output.
  • Yul as IR: It provides a sweet spot — more optimizable than raw Solidity but more readable and portable than pure EVM assembly. This enables whole-program optimizations that would be difficult at the opcode level.

Why It Is Important to Understand the Compiler

Many developers treat the compiler as a black box. This leads to suboptimal or insecure contracts. Here’s why deep understanding pays off:

1. Gas Optimization (The Biggest Practical Benefit)
The optimizer does a lot automatically, but it cannot fix fundamentally expensive patterns. Understanding compilation helps you:

  • Write code the optimizer loves (e.g., simple expressions, reusable functions).
  • Manually optimize where needed (storage packing, using calldata vs memory, avoiding unnecessary state changes, custom errors instead of require strings).
  • Choose the right optimizer-runs and consider enabling viaIR for better results in many cases.
  • Inspect Yul or assembly output to see what the compiler actually generates.

2. Security and Correctness

  • Storage layout collisions are a major risk in upgradeable contracts and inheritance. The compiler’s deterministic layout rules (starting at slot 0, packing rules, keccak for mappings) must be respected.
  • Compiler bugs, while rare, have existed historically. Using recent, audited versions and pinning exact versions (pragma solidity 0.8.XX;) reduces risk.
  • Understanding how features compile (e.g., modifiers, inheritance) helps spot subtle issues.

3. Debugging and Maintenance
Source maps and assembly output allow stepping through code at the EVM level. When things go wrong on-chain, inspecting bytecode or Yul is often necessary.

4. Contract Verification and Reproducibility
Explorers verify source by recompiling it with the exact compiler version and settings. Mismatched settings produce different bytecode, breaking verification.

5. Advanced Development and Tooling

  • Inline assembly/Yul gives fine-grained control when Solidity abstractions are insufficient.
  • Frameworks (Hardhat, Foundry, etc.) expose compiler settings. Knowing them lets you tune builds effectively.
  • Future-proofing: As EVM evolves (new versions, EOF), the compiler adapts. Understanding pipelines helps adopt improvements.

6. Best Practices
Always:

  • Pin exact compiler versions.
  • Enable the optimizer (and consider viaIR).
  • Review warnings as errors.
  • Use the latest stable 0.8.x version for safety features.
  • Inspect storageLayout for complex contracts.

Gas Optimization & Auditing Tips

  • Modifiers: each inclusion of `_` in a modifier inserts the function body into bytecode. If a function has several modifiers, it may significantly increase the size of the contract and the cost of deployment. If you need to save money, you can combine modifiers or put the checks into a separate function;
  • In older versions of solidity, reading the storage length of the array (array.length) in the loop condition means reading from storage at each iteration;
  • Sometimes when auditing code, you may notice unnecessary copying (calldata->storage; calldata->memory; memory <-> storage) when assigning or passing arguments to a function. For example, you should always mark reference-type arguments of external functions as calldata, not memory; sometimes you may even use storagereferences in internal calls;
  • You can change the order of storage variables or fields in a structure somewhere to use storage packing, and it will be useful. However, sometimes reading and writing with storage packing is not always cheaper than without it. You can save a lot of gas when writing a storage array of structures with packed fields;
  • In Solidity, some data types have a higher gas cost than others. And that is what is often required of a smart contract developer and that’s why you should understand the gas utilization of the available data types;
  • Custom errors is cheaper to use than revert(“error text”). There is more information in this article: soliditylang.org/blog/2021/04/21/custom-errors.

The integration of your project will be substantially more secure if you implement the below recommendations:

  • Functions: Internal calls preserve the context (msg.sender, msg.value, etc). For example, an internal call to `transfer(…)` inside a token transfers tokens from the address of the caller, not from the balance of the token contract itself;
  • Functions: external > public
  • Variables: Visibility of private and internal does not hide data. Variable values are readable from off-chain;
  • Variables: Public visibility for variables creates getters and the code of getters takes up space in the contract. When optimizing gas, you can remove Public visibility for some variables (unused or already read in some other functions) and thus reduce gas consumption during contract execution;
  • Constants: Magic constants are dangerous, so make full-fledged constants with a normal name. Immutable is also ok;
  • Constants: Function signatures should be checked using 4bytes;
  • Ether: payable — can be redundant (the function can receive ether but does not process it);
  • Ether: fallback vs receive; receive is sufficient for receiving money. It often includes a check that the broadcast comes from one of the addresses (e.g. WETH);
  • Ether: It is impossible to limit the consumption of ether (selfdestruct, mining), so you cannot rely on the exact value of the balance. This is also true for tokens;
  • Ether: Three Ether sending options: send, call, transfer:

a) Specifics of use address.transfer() — throws on failure, forwards 2,300 gas stipend (not adjustable), safe against reentrancy, should be used in most cases as it’s the safest way to send ether;

b) Specifics of use address.send() — returns false on failure, returns false on failure, should be used in rare cases when you want to handle failure in the contract;

c) Specifics of use address.call.value().gas()() — returns false on failure, forwards all available gas (adjustable), not safe against reentrancy, should be used when you need to control how much gas to forward when sending ether or to call a function of another contract;

  • It’s bad form to work directly with gas: When working with the tx.gasprice variable, it is necessary to remember that its value is set by the user at the moment of transaction execution;
  • It’s bad form to work directly with gas: release of a specific amount of gas through .gas(X) / {gas: X}
  • .transfer VS .send VS .call — call is a good standard, but it brings its own set of problems (reentrancy etc);
  • It is easy to make collisions, for example with arrays: abi.encodePacked([1,2],[3]) == abi.encodePacked([1],[2,3]))so check them out carefully. Technically, similar can be done with abi.encode, e.g. via structures.
  • Use SafeMath and analogs for Solidity <0.8 (and do not use for more recent ones), keep in mind that a.add(b).mul(c) == (a+b)*c ;
  • Very carefully check all unchecked sections for Solidity >=0.8 ;
  • It is better to do all calculations in the uint256 type, because, for example, in the case of `uint256(a) = uint16(b) * uint32(c) / uint16(d)` the right part may overflow, because the intermediate value may not fit into uint32 (for each operation the maximum of operand types is taken, i.e. the result of multiplication of uint16 and uint32 will be uint32);
  • Type conversion — always check that the number is converted normally. Recommendation: use libraries like SafeCast ;
  • It’s almost always multiplication first, then division;
  • When calculating fractions, don’t forget that you can accidentally get zero. e.g. `balanceOf(user) / totalSupply() == 0`. You need to multiply by a suitable multiplier (often 1e18).
  • It is better to put the additional multiplier in a constant like `uint constant private HUNDRED_PERCENT=1e18;` ;
  • There are times when you need to calculate the sum of fractions (i.e., the common denominator of all fractions). It is correct to add first, then divide;
  • Instead of `a/b > c/d` it is often better to use `a*d > c*b`.

Short Types in Solidity: Rare Tricks Uncovered

In Solidity, some data types have a higher gas cost than others. And that is what is often required of a smart contract developer and that’s why you should understand the gas utilization of the available data types; — in order to choose the most efficient one according to your needs.

For the purposes of this article, we refer to uint8-uint248 and int8-int248 types as “short types”.

  • Solidity compiler tightly packs short types (if possible) to reduce storage footprint of storage variables, struct fields, array elements;
  • Short types require more opcodes and gas in all other cases (calldata, memory, stack).
  • Overflows happen more often;
  • Solidity 0.8 and SafeMath do not check for overflows during type casts;
  • Short types behave differently for abi.encodePacked and other abi.encode* calls.
  • Solidity ABI encoder puts every value into a separate slot, i.e. the size of calldata or returndata remains the same.
  • The compiler often inserts additional opcodes — it may inflate the size of the contract.

I recommend:

  • Using short types only to reduce storage footprint;
  • Local variables, return values, function and event parameters should be uint256 or int256
  • Converting uint256 values to shorter types right before you write them to storage. Utilize libs like a SafeCast; — they have a pretty good syntax;
  • When you read short type value from storage, convert it to uint256 immediately
  • Utilizing storage location when possible: function foo(MyStruct storage ms, uint32[] storage array) internal {…}
  • Read individual fields or elements if you don’t need the whole structure or array: uint256 value = uint256(ms.field) + uint256(array[i]);

Conclusion

The Solidity compiler is far more than a simple translator. It is a sophisticated tool that handles the immense complexity of mapping high-level smart contract logic onto a constrained, gas-metered virtual machine. It performs parsing, semantic analysis, powerful optimizations (especially via Yul in the IR pipeline), and generates critical artifacts like ABI and metadata.

Developers who understand its inner workings like how code becomes bytecode, how storage is laid out, how the optimizer functions, and what outputs it produces will write better contracts. They save on gas, reduce security risks, debug faster, and build more reliable decentralized applications.

In the evolving world of blockchain development (with L2s, account abstraction, and potential EVM upgrades), compiler literacy is no longer optional, it is a core skill for professional Solidity engineers.

Master the compiler, and you master the bridge between your ideas and the blockchain.


Gas Optimization & Auditing Tips was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

How AI Calling Agents Can Save Your Business Time in 2026

7 July 2026 at 09:44

AI Calling Agents automate customer conversations, helping businesses respond faster and work smarter around the clock

Turn Conversations into Conversions with AI Calling Agents

Imagine receiving hundreds of customer calls every day. Some callers want to book an appointment, others ask about pricing, while many simply need basic information. Now imagine your team repeating the same answers over and over again. Although these conversations are important, they consume valuable working hours that could be spent on sales, strategy, or customer relationships. This is exactly where an AI Calling Agent is changing the way modern businesses operate. Instead of replacing people, it handles repetitive phone conversations with speed and consistency, allowing employees to focus on work that genuinely requires human thinking and decision-making.

Manual Calling Is Slowing Down Modern Businesses

Phone communication remains one of the most effective ways to connect with customers, but managing every call manually has become increasingly difficult. Growing businesses often receive inquiries throughout the day, making it challenging for support teams to respond quickly. It is possible for customers to become frustrated and miss out on opportunities if responses are delayed. By introducing an AI Calling Agent, businesses can answer common questions instantly, collect customer details, and manage routine conversations without increasing the workload of their employees. This creates a smoother experience for both the business and its customers.

AI Calling Agents Are Smarter Than Traditional Phone Systems

Older automated phone systems relied on fixed menus that asked callers to press different numbers before reaching the correct department. These systems often felt slow and frustrating because they could not understand natural conversations. Modern AI voice agents work differently. They listen to spoken language, understand customer intent, and provide responses that feel conversational instead of robotic. This makes interactions faster, more natural, and far more helpful, improving the overall experience while reducing the need for human intervention during routine calls.

Saving Time Starts with Automating Repetitive Conversations

Every business has repetitive tasks that consume valuable hours. Appointment confirmations, order updates, lead qualification, payment reminders, and frequently asked questions usually follow predictable conversation patterns. Instead of assigning employees to repeat the same information throughout the day, businesses can automate these interactions using an AI phone assistant. The system delivers accurate responses consistently, works without breaks, and remains available outside regular business hours. Employees gain more time to solve complex customer issues, develop stronger relationships, and focus on activities that contribute directly to business growth.

Industries Already Benefiting from AI Calling Technology

The adoption of AI-powered calling is expanding across multiple industries because every sector faces similar communication challenges. Healthcare providers use AI to confirm appointments and reduce missed consultations. Real estate companies qualify buyer inquiries before connecting them with sales teams. Financial institutions automate routine account-related calls, while e-commerce businesses keep customers informed about deliveries and returns. Even educational organizations are using intelligent calling systems to communicate with students and parents more efficiently. These practical applications demonstrate that business process automation is no longer limited to large enterprises but is becoming accessible to organizations of every size.

Better Productivity Without Expanding Your Workforce

Business growth often brings higher communication demands, but hiring additional support staff is not always the most practical solution. Recruitment, training, and ongoing management require both time and financial investment. An AI Calling Agent helps businesses scale customer communication without proportionally increasing operational costs. It can manage multiple calls simultaneously, respond immediately, and transfer only complex cases to human representatives. This balanced approach improves productivity while ensuring employees spend their time where they add the greatest value.

Connecting AI Calling Agents with Everyday Business Tools

The true value of an AI Calling Agent extends beyond answering phone calls. Modern businesses rely on CRM platforms, scheduling software, help desk systems, and customer databases to manage daily operations. When an AI calling solution connects with these tools, every conversation becomes more productive. Customer details can be updated automatically, appointments can be scheduled instantly, and follow-up tasks can be created without manual effort. This seamless workflow reduces repetitive administration and allows teams to focus on delivering better customer experiences instead of managing paperwork.

AI Is Becoming a Valuable Sales Assistant

Sales teams often spend hours contacting leads that may never become customers. An AI Calling Agent can simplify this process by making the first contact, collecting essential information, identifying customer requirements, and qualifying potential leads before they reach a sales representative. This approach ensures that sales professionals spend more time speaking with genuinely interested prospects instead of filtering large volumes of inquiries. As a result, businesses improve productivity while creating a faster and more organized sales process that benefits both employees and customers.

Why 2026 Is the Right Time to Adopt AI Calling Agents

Customer expectations continue to evolve every year. People expect immediate responses, accurate information, and support that is available beyond traditional working hours. At the same time, businesses are under constant pressure to improve efficiency while controlling operational costs. These changing expectations make 2026 the perfect time to adopt AI Calling Agents. Advances in conversational AI, cloud technology, and voice recognition have made intelligent calling solutions more reliable, affordable, and accessible than ever before, allowing businesses of every size to benefit from automation.

Final Thoughts

Time is one of the most valuable resources in any business, and repetitive phone conversations often consume more of it than organizations realize. An AI Calling Agent helps reduce this burden by automating routine communication, improving response times, supporting sales teams, and integrating smoothly with existing business systems. Rather than replacing employees, it enables them to focus on meaningful customer interactions and strategic work. As businesses continue embracing intelligent automation in 2026, AI-powered calling solutions will become an essential part of delivering faster service, improving productivity, and building stronger customer relationships.


How AI Calling Agents Can Save Your Business Time in 2026 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Junior Developers Write Code — Senior Engineers Design Outcomes

6 July 2026 at 01:52

Your code works.

That is the problem.

It runs. It passes tests. It gets merged. Everyone moves on.

Three months later, someone rewrites it.

Six months later, it becomes a production issue.

One year later, nobody wants to touch it.

This is the moment most developers never question. The quiet success that hides a louder failure. Because working code is not the finish line. It is the starting point.

The difference between a junior developer and a senior engineer is not intelligence. It is not years. It is not even skill.

It is perspective.

The Illusion of “Done”

A junior developer solves the ticket.

A senior engineer solves the problem behind the ticket.

On paper, both deliver the same feature. A button works. An API responds. Data flows.

But under the surface, they are building very different systems.

A junior thinks in terms of output.

A senior thinks in terms of impact.

Here is a simple example.

// junior approach
public int total(List<Integer> nums) {
int sum = 0;
for (int n : nums) sum += n;
return sum;
}

It works. Clean. Simple. Nothing wrong.

Now look at the same logic from a different angle.

// senior mindset
public int total(List<Integer> nums) {
if (nums == null || nums.isEmpty()) return 0;
int sum = 0;
for (int n : nums) {
if (n < 0) throw new IllegalArgumentException();
sum += n;
}
return sum;
}

The difference is not the loop.

The difference is awareness.

Edge cases. Data integrity. Future misuse. Silent failures.

A senior engineer writes code that defends itself.

Code vs Outcome

Junior developers ask:

What should I write?

Senior engineers ask:

What will this change cause?

That question reshapes everything.

A small feature is never just a feature. It touches performance, cost, reliability, and people.

Consider a simple API.

@GetMapping("/orders")
public List<Order> get() {
return repo.findAll();
}

It works perfectly in development.

Then production happens.

Ten thousand records. One lakh. Ten lakh.

Memory spikes. Latency explodes. Database struggles.

Now look at the same endpoint designed with outcome in mind.

@GetMapping("/orders")
public Page<Order> get(Pageable p) {
return repo.findAll(p);
}

One small decision.

Massive difference in behavior.

Senior engineers think about scale before scale arrives.

The Invisible Work

The most valuable engineering work is often invisible.

No one celebrates removing complexity.

No one applauds preventing a future bug.

No one writes a Slack message saying, “Nothing broke today because of you.”

But that is exactly where senior engineers live.

They reduce risk before it appears.

They simplify systems before they collapse.

They design paths that others can walk without fear.

Think of architecture like this:

Junior mindset:
[ UI ] --> [ Service ] --> [ DB ]
Senior mindset:
[ UI ]
|
v
[ API Layer ] --> [ Service Layer ] --> [ Domain Rules ]
|
v
[ Data Layer ]
|
v
[ DB / Cache ]

It looks similar at a glance.

It behaves very differently over time.

The first one delivers speed.

The second one survives growth.

Speed Is Easy. Sustainability Is Rare.

Anyone can ship fast.

Very few can keep shipping without breaking everything.

That is where real engineering begins.

Junior developers optimize for today.

Senior engineers optimize for change.

Because change is the only constant in software.

Requirements change.

Traffic changes.

Teams change.

And code that cannot adapt becomes a liability.

A senior engineer writes with future readers in mind.

Not just the compiler.

Not just the reviewer.

But the unknown developer six months later who will try to understand the intent behind every decision.

Thinking in Trade-offs

There is no perfect code.

Only trade-offs.

Junior developers look for the right answer.

Senior engineers look for the least harmful compromise.

Performance vs readability.

Speed vs safety.

Flexibility vs simplicity.

Every decision costs something.

The skill is knowing what to spend.

The Shift That Changes Everything

The transition from writing code to designing outcomes does not happen with a promotion.

It happens with a question.

Not “Is this correct?”

But “What happens next?”

That question turns code into responsibility.

It forces you to think beyond your screen.

Beyond your task.

Beyond your sprint.

It connects your work to the system, the business, and the people using it.

Final Thought

Writing code is a skill.

Designing outcomes is a mindset.

One makes features.

The other builds systems that last.

If your code works, that is good.

If your code continues to work, scale, and remain understandable long after you wrote it, that is engineering.

That is the difference.

And that is the level worth aiming for.


Junior Developers Write Code — Senior Engineers Design Outcomes was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Junior Developers Write Code — Senior Engineers Design Outcomes

6 July 2026 at 01:52

Your code works.

That is the problem.

It runs. It passes tests. It gets merged. And yet, three months later, someone rewrites it. Six months later, it becomes a production issue. One year later, nobody wants to touch it.

This is the uncomfortable truth no one tells early in a developer career.

Writing code is not the job.

Designing outcomes is.

Early in a career, success feels simple. A ticket comes in. You write a function. You fix a bug. You see green checks. You feel productive.

That feeling is addictive.

But it is also misleading.

Because the real world does not reward code. It rewards impact.

A junior developer asks:
“What should I write?”

A senior engineer asks:
“What problem are we actually solving?”

That one shift changes everything.

Take a simple example.

A junior developer might implement an API like this:

@GetMapping("/user/{id}")
public User getUser(int id) {
return repo.findById(id).get();
}

It works. It returns data. Done.

A senior engineer looks at the same requirement and sees something else entirely.

What happens if the user does not exist?

What about latency?

What about caching?

What about abuse?

What about future scale?

The code becomes:

@GetMapping("/user/{id}")
public ResponseEntity<User> getUser(int id) {
User u = cache.get(id);
if (u == null) {
u = repo.findById(id).orElse(null);
if (u != null) cache.put(id, u);
}
return (u != null) ? ok(u) : notFound();
}

Still simple. Still readable.

But now it reflects thought.

That is the difference. Not complexity. Not cleverness. Thought.

Junior developers optimize for completion.

Senior engineers optimize for consequences.

Before writing a single line, a senior engineer maps the system in their head.

Something like this:

Client
|
v
API Layer
|
v
Service Logic
|
v
Database
|
v
External Services

But they do not stop there.

They ask:

Where will this break?

Where will this slow down?

Where will this be abused?

Where will this need to evolve?

That is how outcomes are designed.

There is also a hard truth that stings a bit.

More code does not mean more value.

In fact, the best engineers often write less code.

Because they remove unnecessary work before it begins.

A junior developer might build a feature in five days.

A senior engineer might spend two days questioning it, then solve it in one.

Or decide it should not be built at all.

That is not laziness. That is leverage.

Another difference shows up during incidents.

When production breaks, junior developers search for the bug.

Senior engineers search for the system failure.

A null pointer is not the problem.

The absence of validation is.

A timeout is not the problem.

The lack of retries, backoff, or circuit breaking is.

A crash is not the problem.

The lack of observability is.

Senior engineers think in layers.

They design systems that fail gracefully, not systems that hope to never fail.

Let us talk about ownership.

Junior developers often feel ownership over code.

Senior engineers feel ownership over outcomes.

If a feature fails in production, it does not matter who wrote it.

It matters that it failed.

This mindset changes behavior.

Documentation improves.

Monitoring gets added.

Edge cases are considered.

Communication becomes clearer.

Because the goal is no longer to finish work.

The goal is to make things work in the real world.

So how does someone make this shift?

Not by learning another framework.

Not by memorizing more syntax.

But by asking better questions.

Before writing code, pause and ask:

What happens if this grows 10x?

What happens if this fails at midnight?

Who depends on this?

What is the simplest version that solves the real problem?

And most importantly:

Is this even the right problem to solve?

There is a moment in every developer’s journey where things click.

You stop thinking in methods.

You start thinking in systems.

You stop chasing tickets.

You start shaping outcomes.

That is when growth accelerates.

That is when people trust your decisions, not just your code.

Writing code is a skill.

Designing outcomes is a responsibility.

One gets you started.

The other makes you indispensable.

If your code works, that is good.

If your system works under pressure, that is engineering.

And that is the difference that separates a developer from an engineer.


Junior Developers Write Code — Senior Engineers Design Outcomes was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Meta's Un-Stable Signature

30 June 2026 at 09:50
I'm wrapping up my investigation into invisible watermark algorithms and I am extremely disappointed. Not only do none of the modern AI-based algorithms work as they claim, it turns out that they are all making the same fundamental mistake.

I previously evaluated Google's SynthID and Adobe's TrustMark algorithms. Both of them claim to have incredibly accurate results.
  • According to Google's peer-reviewed and published paper, they claim to have a true positive rate (TPR) above 99.97% -- meaning that they will miss their own watermarks less than 1 in 10,000 times. However, my own empirical testing found that is it much closer to 1 in 20. Moreover, SynthID is proprietary and only accessible through Google's "Gemini" AI system. Gemini has been observed hallucinating results and providing contradictory conclusions depending on how the question is phrased.

  • According to Adobe's Content Authenticity Initiative, their TrustMark "can exceed 96% bit accuracy at around 42-45dB PSNR quality under severe noise degradations". However, that statistic focuses on resilience and not accuracy. In my empirical tests, I found that TrustMark has a 10%-20% false positive rate, effectively making it useless. (If you see a TrustMark signature, then it is very likely random noise and not an actual signature.)
This time, I evaluated Meta's "Stable Signature" algorithm. (Their paper and code are in GitHub.) This system encodes a 48-bit sequence into the picture's visual content. The idea is that you can encode a unique 48-bit sequence as your watermark. If your decoder finds the same 48-bit sequence, then it can identify your own watermark.

WARNING: This blog entry leans heavily into math and statistics to prove that Stable Signature, TrustMark, and SynthID are nowhere near as reliable as their developers claim.

The Basic Algorithm

Traditional (non-AI) invisible watermarks typically hide in subtle locations, such as the least significant bits, changes in brightness (e.g., Digimarc) or the frequency spectrum (DCT or FFT). There is always the risk that image encoding could corrupt the hidden data, so these algorithms typically rely on repetition over the image to help identify the true signal. In addition, they may include error correction code (extra bits in the data) to fix any minor data errors.

However, there is a problem with the traditional approaches: injecting hidden data in the image could create visible distortions. The modern approach uses an AI system to better hide the data with less added distortion.

As with SynthID and TrustMark, Stable Signature encodes binary data and uses an AI-model to decide where to hide it in the image. The AI is tuned to minimize visible distortions when embedding the data. Later, an AI-based decoder looks at the image and identifies the likely location where bits are stored, then it extracts the data.

There is always the case that the data may be mixed with noise. Different AI-based watermarking systems rely on different techniques for reducing the noise. For example:
  • Google's SynthID only stores a few bits of data (effectively a flag or version number). This allows them to use a lot of data as repetition and to increase the accuracy rate.

  • Adobe's TrustMark uses the Bose-Chaudhuri-Hocquenghem (BCH) algorithm. This acts as a combination of checksum and error correcting code that should reduce the number of errors.
Meta's Stable Signature uses a simple Hamming distance.



The Hamming distance measures the number of bits that need to be swapped in order to correct the code. In effect, it defines a set of stable states (e.g., 10110 and 11000) and places a ring around each state that represents the single bit changes. If you change enough bits, then you will reach a different stable state.

According to Meta's Stable Signature research paper, the 48-bits should be uniformly distributed and cites a "false positive rate below 10-6", or 1 in one million. This means you can choose a 48-bit sequence to use as your signature. Every picture will generate a 48-bit sequence, and the sequence can vary a little based on noise in the picture. However, if you find a code that is within a short Hamming distance of your code (e.g., within 6 bits difference), then you can determine that it is the same code with a high reliability.

At least, that's the theory.

Empirical Testing

I went into this experiment assuming that everything works like they claim. I want to be able to reliably identify invisible watermarks associated with Meta. What I don't know is what sequence they use, or whether they use multiple codes depending on whether it comes from Meta's AI system, Facebook, Instagram, WhatsApp, etc.

Fortunately, this is something I can test! I grabbed an uncurated sample of pictures from FotoForensics: the first 10,000 unique images uploaded last month (May 2026). If the bit sequences are uniformly distributed with a "1 in 1 million" collision rate, then I should see a huge number of unique bit sequences and a few small clusters around pictures from Meta (Meta AI, Facebook, Instagram, etc.). Those clusters will represent the invisible watermarks used by Meta.

The results from my empirical test were definitely not what I expected. I found:
  • No clusters associated with any Meta images. This suggests that Meta does not use their own Stable Signature watermarking software found on GitHub.

  • With a random distribution, there should be no clusters. However, I had 25 different pictures that had the exact same bit sequence: 110110100111111011101001111000100111011000011101. With a 1 in a million collision rate, this should not happen! These pictures came from very different sources. Here's four of the 25 pictures (ranging from planets to light bulbs to text with a transparent (black) background):



    All of these pictures have dark/black backgrounds and something bright in the middle. This suggests that Stable Signature operates more like a perceptual hash than an invisible watermark.

  • Stable Signature uses a Hamming distance to identify a cluster. If I assume the 25 pictures are the center (centroid) of the cluster and use a 6-bit Hamming distance, then there are 356 pictures that are similar. And if I assume that the 25 pictures are not the center but part of a cluster, then a Hamming distance of 6 has a cluster of 450 pictures centered 3 bits away, at 110110000111111011101011111000100111001000011101. This cluster represents 4.5% of the uncurated image data set! Here are a few samples from this larger cluster:



    (I'm explicitly not sharing pictures with personal information, like invoices, recognizable people, and GPS information.)
It's not just one random cluster that is massively large (450 pictures out of 10,000). There's a cluster of 184 pictures at 110101001011001011001011111000100111001000011101, 58 pictures at 110100000011111010001001111000100111011000011101, etc. I found over 60 clusters with more than 10 pictures each at a Hamming distance of 6. That should not happen with a "1 in 1 million" collision rate.

Independent Analysis

I went back to Meta's research paper to see if I could find the discrepancy. And there it was, in section 3.1: They tested their system against the hypothesis that the 48-bits are each independent and uniformly distributed. The problem is, they use one neural network to generate the bits. That explicitly means that the bits are dependent, not independent.

Their paper assumes a binomial distribution. That is, given an arbitrary image, the 48-bits represent a random coin flip. The math becomes:
P(XT)=Tk=0(48k)(0.5)k(0.5)48k

This computes the probability of 48 random bits being within a Hamming distance (T). The probabilities table becomes:

Hamming Distance Threshold (T)Bit Error Rate (BER)Probability of a Random Image Matching by Chance
14 bits or fewer≤ 29.17%1 in 362.63
13 bits or fewer≤ 27.08%1 in 957.81
12 bits or fewer≤ 25.00%1 in 2,788.35
11 bits or fewer≤ 22.92%1 in 8,999.08
10 bits or fewer≤ 20.83%1 in 32,416.80
9 bits or fewer≤ 18.75%1 in 131,390.28
8 bits or fewer≤ 16.67%1 in 605,094.89
7 bits or fewer≤ 14.58%1 in 3.20 Million
6 bits or fewer≤ 12.50%1 in 19.83 Million
5 bits or fewer≤ 10.42%1 in 146.19 Million
4 bits or fewer≤ 8.33%1 in 1.32 Billion
3 bits or fewer≤ 6.25%1 in 15.24 Billion
2 bits or fewer≤ 4.17%1 in 239.15 Billion
1 bit or fewer≤ 2.08%1 in 5.74 Trillion
0 bits (perfect match)= 0.00%1 in 281.47 Trillion

Meta's paper says that they use a Hamming distance of 7 bits (requiring 41 of 48 bits), which matches their claim of a "false positive rate below 10−6". However, I'm seeing problems at a Hamming distance of 6 (should be 1 in 20 million) and even collisions at 0 (1 in 281 trillion)!

The Core Problem

There is clearly a discrepancy between the theoretical probabilities and the empirical testing. When I looked back over Meta's research paper, I saw the problem:

According to Meta's paper, each of the 48-bits are independent. In a perfectly independent 48-bit hypercube, un-watermarked images should scatter uniformly across all 248 possible values. However, neural networks map a non-linear manifold (a multi-dimensional wavy surface) through this hypercube. This mathematical landscape is warped with its own peaks, ravines, and valleys. It has attractors that form clusters, and repulsers that form voids where stable values can never exist; this is a feature of a neural network. And most importantly, the output bits are explicitly not independent.



The left diagram illustrates an expected uniform distribution if all of the bits were independent. The right diagram are the types of theoretical clusters that form when the bits are dependent. There should be clusters around attractors and voids (areas with no dots) from the repelling regions.

Moving from theoretical to empirical, I graphed the data. The 48 bits can be represented as bytes. I took the first 24 bits and converted them into 8-bit red, green, and blue pixel colors. If the data is truly random, then the colored dots should be distributed across the RGB cube. However, if the bits are dependent, then there should be very clear clusters, structures, and voids. Here's the graph:



Yes, there are very clear structures that look like planes and lines. Within the planes are clusters, and outside the planes are very large voids -- areas where there are no dots at all. The data generated by Meta's Stable Signature implementation fails this basic test for independence.

The biggest cluster that I found represents a Zero Signal Bias (ZSB). When their neural network doesn't find a watermark, it moves the 48 bits toward a strong attractor, like a massive gravitational well. At 6 bits error, it should have a collision of around 1 in 20 Million. But in reality, my 10,000 pictures had a cluster of 450 images within 6 bits due to the ZSB. That's an error rate of around 1 in 22 with the ZSB alone. If we add in all of the other clusters that contain at least 10 pictures, then 2327 pictures are in various clusters; we're looking at an error rate around 1 in 4 -- and that's at a Hamming distance of 6, which is more conservative than their paper's Hamming distance of 7. (In AI terms, this is a representation collapse or structural bias that is typical for deep neural networks.)

(As an aside: Given their "1 in 1 million" claim, I could look for any clusters of 2 or more pictures. At clusters of 2 or larger, 5,237 of the 10,000 test images were in clusters, or 52%. If you show their algorithm 10,000 pictures, then there is a better-than 50% chance of a false positive match.)

Less Than Random

It's one thing for me to claim that there are visible clusters and to show pictures of clusters, but another to prove it mathematically. (Time to dust off my college textbooks from "Introduction to Statistics"...)

I fed Meta's code the first 10,000 images from May 2026. A few of the images were in unsupported formats (HEIC, WebP, and a few corrupted JPEG files), resulting in 9,847 viable pictures. I evaluated this data with elements from the NIST Statistical Test Suite (SP 800-22) for randomness, including a monobit test and Chi-Squared (χ2) test for independence.

The monobit test determines if the baseline frequency of adjacent bits seems independent.
  • Total Bits Processed: 9,847 pictures × 48 bits per signature = 472,656 bits
  • Observed Count of Ones ('1'): 266,419
  • Observed Count of Zeros ('0'): 206,237
  • Expected Count (E): 236,328 for each.
Running a simple standard Chi-Square Goodness-of-Fit test for this bit balance:
χ2=(266419 − 236328)2236328+(206237 − 236328)2236328= 3816.14 + 3816.14 = 7632.28
  • In mathemat-ese: with 1 degree of freedom, a χ2 statistic of 7,632.28 yields a p-value infinitely close to 0.0 (p &Ll; 10-100). (As an aside, most Chi-square tables usually evaluate the 1 degree of freedom up to around χ2=10. This χ2 value is so astronomically high that the probability p effectively becomes zero.)

  • In English: That's definitely not random or independent.
The watermark extraction is strongly biased toward producing 1s over 0s across global arbitrary images (roughly 56% ones to 44% zeros). This immediately violates the uniform distribution assumption.

The second test is the Chi-Square (χ2) Test for Serial Independence. If the bits were independent, the transition probability between adjacent bits would just be the product of their individual probabilities. This table shows the occurrence rate of the transition pairs across all of the observed 10,000 (well, 9,847) pictures:

Transition PairObserved Count (O)Expected Count under Independence (E)
0 to 0106,75090,051
0 to 195,296116,186
1 to 095,302116,186
1 to 1165,461149,976

χ2=(OE)2Eχ2=16699290051+(−20890)2116186+(−20884)2116186+154852149976=3096.7 + 3756.2 + 3754.0 + 1599.0=12,205.9
  • In mathemat-ese: With 1 degree of freedom for the transition contingency table (accounting for fixed margins), a χ2 value of 12,205.9 gives a p-value of 0.0.

  • In English: Ain't no way this is random or independent.
And as if this wasn't conclusive enough, there are other tests we could apply:
  • Static Tail Patterns: Looking closely at the end of the 48-bit sequences, a massive cluster of strings end explicitly in ...111101 or ...00111101. Additionally, bit position 46 is nearly always "1" (228 zeros vs 9619 ones, or 97.7% of the time it is "1"), position 47 is "0" (8958 of 9847 images, or 90.97%), and position 48 is "1" (found with 9696 images, or 98.5%) across thousands of uncurated, real-world images.

  • Structural Clustering: Certain bit columns share an extraordinarily high Mutual Information score (I(X;Y)). For example, knowing the output of bit position 12 gives you better than an 80% accuracy in predicting bit position 28.
The assumption of a "uniform distribution over arbitrary pictures" relies on the idealistic premise that random natural image features project uniformly across the decision boundaries of a network. However, because the extraction network maps inputs to a constrained, highly continuous hyper-dimensional manifold, the network's latent layers natively enforce structural smoothness.

For the TL;DR crowd:
Meta's researchers made a fundamental mistake when computing their accuracy rates. It's not a "1 in 1 million" chance of a false match, it's closer to 1 in 4 -- because the 48 bit values per signature are not independent.

As I re-read Meta's research paper, I realized that the statistical error wasn't an oversight; Meta's researchers explicitly acknowledged the problem. In their paper (Section 4.1), they wrote:
Second, we observed that W’s output bits for vanilla images are correlated and highly biased, which violates the assumptions of Sec. 3.1 [the section about independent statistical test methods].
In other words, they recognized that the extracted bits are not independent. Despite this, their published false-positive analysis still relies on the assumption that the bits are independent.

Widespread Problems

Knowing that Meta's accuracy rate is grossly inflated due to assuming bit-wise independence when there is none, I looked back over Google's and Adobe's papers for their own watermarks. Did Google's and Adobe's researchers make this same mistake?
  • Google's SynthID research paper talks in terms of True Positive Rates (TPR). They do make this same "bit-wise independent" mistake, but it's obfuscated in the paper. You can see the error in their Equation 3 (PDF page 8), where they assume there is a uniform (independent) distribution. Their paper hyperfocuses on the true positive rate and never addresses the false positive distribution. (Either they didn't know to look, or they knew and decided to not report it because it would expose a serious weakness in their solution.)

  • Adobe's TrustMark research paper also makes assumptions of independence. You can see this in their PDF with the binary cross-entropy loss in Section 3.1.4. This mathematically treats each bit position as an independent Bernoulli trial. (By definition, a Bernoulli process strictly requires independence.) In their experiments (Section 4.1), they wrote "At test time, every image is associated with a random watermark", but they never tested if the random watermarks were similar to each other.
This introduction-to-statistics mistake is found in all three of these invisible watermarking technologies. The detections produced by these systems are so unreliable that an analyst cannot determine whether a reported detection is real or a false positive, or whether a reported non-detection is genuine or a false negative.

It's also worth noting that, shortly after releasing Stable Signature, Meta developed another algorithm: Pixel Seal. (Not to be confused with my own Secure Evidence Attribution Label / SEAL technology.) Pixel Seal moves to a 256-bit payload to increase the capacity, and their related model, Chunky Seal, pushes up to 1024 bits. While Meta's approach focuses heavily on addressing the invisibility side using an adversarial-only discriminator, the underlying approach still uses a neural network mapping. Using more bits only exacerbates this flaw.

Potential Uses

Algorithms can have uses. For example, Meta, Google, and Adobe are training their own AI models on images that they encounter. To prevent poisoning their training sets, they want to exclude images generated by their own systems. In this regard, watermarking does help them. For example, if Meta excludes an extra 25% of images (from false positives), then they still have a lot of images that they can train on.

However, that same usage does not work with legal cases. For example, consider an insurance company. Most insurance claims today include photographic evidence. The company wants camera-original photos, but have to use whatever the customer submits. The problem is that there is a lot of insurance fraud. In theory, seeing a watermark from an AI system like Meta, Google, or Adobe, should be great for identifying and ruling out fraud. Unfortunately, Stable Signature, SynthID, and TrustMark are so inaccurate that none of them can be trusted; it's not even worth testing to see if customer photos contain these invisible watermarks.

For these watermarking systems, I'm talking about very high error rates: roughly 1-in-4 for Meta, 1-in-5 for Adobe, and 1-in-20 for Google. But let's pretend that they work much better, like a 1-in-20,000 false positive rate. An insurer processing 100,000 claims per month would expect to accuse around 5 completely honest customers of fraud each month. Falsely denying 5 out of 100,000 claims? That creates a toxic customer service nightmare, severe legal liability, and fines from regulatory bodies for bad-faith claim denials. This could even become a class-action lawsuit that they couldn't win.

As bad as it is for insurance and financial institutions, there are much higher stakes at play. The EU AI Act (Article 50(2)), China's GB 45438-2025, California SB 942, and similar legislation are moving toward mandating AI content watermarking.

The failure of these three leading systems, from three Fortune-500 companies, to meet their own claimed accuracy rates is not just an academic curiosity. Regulators and courts will employ these systems for attribution and fraud detection. Reliable AI-based watermarking technology is not ready.

Three companies. Three algorithms. Three different research teams. The same fundamental error. The false positives won't go on trial. People will.
❌
❌