AI 资讯
The Evolution of a Software Engineer
The first year class HelloWorld { public static void main ( String args []) { // Displays "Hello World!" on the console. System . out . println ( "Hello World!" ); } } The second year /** * Hello world class * * Used to display the phrase "Hello World" in a console. * * @author Sean */ class HelloWorld { /** * The phrase to display in the console */ public static final string PHRASE = "Hello World!" ; /** * Main method * * @param args Command line arguments * @return void */ public static void main ( String args []) { // Display our phrase in the console. System . out . println ( PHRASE ); } } The third year /** * Hello world class * * Used to display the phrase "Hello World" in a console. * * @author Sean * @license LGPL * @version 1.2 * @see System.out.println * @see README * @todo Create factory methods * @link https://github.com/sean/helloworld */ class HelloWorld { /** * The default phrase to display in the console */ public static final string PHRASE = "Hello World!" ; /** * The phrase to display in the console */ private string hello_world = null ; /** * Constructor * * @param hw The phrase to display in the console */ public HelloWorld ( string hw ) { hello_world = hw ; } /** * Display the phrase "Hello World!" in a console * * @return void */ public void sayPhrase () { // Display our phrase in the console. System . out . println ( hello_world ); } /** * Main method * * @param args Command line arguments * @return void */ public static void main ( String args []) { HelloWorld hw = new HelloWorld ( PHRASE ); try { hw . sayPhrase (); } catch ( Exception e ) { // Do nothing! } } } The fifth year /** * Enterprise Hello World class v2.2 * * Provides an enterprise ready, scalable buisness solution * for display the phrase "Hello World!" in a console. * * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED * TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER * PARTY WHO MAY MODIFY AND/OR REDISTRIVUTE THE LIBRARY AS * PERMITTED ABOVE, BE LIABLE TO YOU FOR DAM
AI 资讯
The Tether Paradox: Shitty ERC-20s, OpenZeppelin, and the Unstoppable Web
I have a confession to make. When I first saw that Tether—the behemoth behind the $110 billion USDT stablecoin—was the primary financial backer of Holepunch, Keet, and the Bare JavaScript runtime, my brain short-circuited. I struggled with the cognitive dissonance. Why? Because if you have ever written a smart contract that interacts with USDT on Ethereum Mainnet, you know it is an absolute nightmare. Before we can talk about Tether’s brilliant vision for a decentralized, serverless future, we have to talk about the trauma they inflicted on a generation of Solidity developers. 1. The Original Sin: USDT is not actually an ERC-20 When you are deep in protocol-level engineering, you rely on standards. EIP-20 explicitly states that a token's transfer and transferFrom functions must return a boolean value to indicate success or failure. // The standard EIP-20 Interface interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); } Tether completely ignored this. When they deployed the USDT contract, they omitted the return value entirely. Their functions return void. // The actual USDT Mainnet Implementation (simplified) function transfer ( address to , uint value ) public { // ... logic ... // Notice: No return statement. } If you blindly write a vault or a swap contract using the standard IERC20 interface to move USDT, your transaction will seamlessly execute the logic, move the funds, and then violently revert at the very last microsecond. Why? Because modern Solidity uses a strict ABI decoder. When your contract calls USDT.transfer(), the EVM executes a low-level CALL. When the call finishes, Solidity checks the RETURNDATASIZE. Since it expects a bool (32 bytes), but USDT returns absolutely nothing (0 bytes), the decoder panics and reverts the entire transaction. For years, the only way to build DeFi safely with USDT has been to wrap it in OpenZeppelin's SafeERC20 library, which uses low-level assembly to explicitly check the return data
开发者
Better tools made Copilot code review worse. Here’s how we actually improved it.
How migrating Copilot code review to shared Unix-style code exploration tools reduced review cost by reshaping agent workflows around pull request evidence. The post Better tools made Copilot code review worse. Here’s how we actually improved it. appeared first on The GitHub Blog .
AI 资讯
Why Your Application Needs Observability: Building a Self-Hosted Observability Pipeline with the LGTM Stack (Loki, Grafana, Tempo, Mimir)
Understanding Observability with the LGTM Stack From "what happened last night?" to "here's exactly what happened and why" — in under 5 minutes Table of Contents Introduction What Is Observability? The Three Pillars of Observability Metrics Logs Traces Why You Need All Three Together The LGTM Stack Architecture: How It All Fits Together OpenTelemetry: The Instrumentation Standard The OTel Collector: The Brain of the Pipeline Loki: Log Aggregation Tempo: Distributed Tracing Mimir: Metrics at Scale Grafana: Connecting the Dots Conclusion Introduction Let me tell you a story that probably sounds familiar. It's 2 AM on a Sunday. Your API is slow. Users are complaining. But you're not at your desk — you're in a Sleeping, or just living your life. You have no idea it's even happening. The next morning you walk into the office and your boss meets you at the door. "Hey, the API was really slow yesterday around 2 AM. What happened?" And you're stuck. Completely stuck. You pull up the server logs — it's a wall of unformatted text. Maybe the issue already fixed itself. Maybe the container restarted overnight and the logs are gone. You weren't there, and your system left no trail. So you say the thing every developer dreads saying: "I don't know. I'll look into it." Now imagine the exact same situation — but this time you have observability set up. You open your dashboard, set the time range to yesterday 2 AM, and within two minutes you can see everything. Response times spiked to 4 seconds. The database connection pool got exhausted. And it started the exact moment a scheduled batch job kicked off and hammered the DB with hundreds of queries at once. You have a graph. You have traces. You have the exact log line that caused it. You walk back to your boss with your laptop: "Here's what happened and here's the fix." That's observability. Your system tells its own story — even when you're not watching. That's what this blog is about. I'll walk you through what observability actua
AI 资讯
Day 128 of Learning MERN Stack
Hello Dev Community! 👋 It is officially Day 128 of my software engineering marathon! Today, I tackled an essential lifecycle design challenge in modern frontend development: managing persistent browser loops, orchestrating ticking background workers, and mastering Timer Cleanups inside the useEffect Hook ! ⚛️⏱️💻 I put these architectural paradigms into action by engineering a lightweight, responsive Real-Time Clock Application that tracks exact server-client time down to the second without triggering rogue background processor spikes! 🛠️ Deconstructing the Day 128 Asynchronous Scheduler As captured across my clean system workspace configurations in "Screenshot (286).png" and "Screenshot (287).png" , the scheduling mechanism enforces strict resource allocation: 1. Initializing Reactive Temporal State Managed our standard state anchor using native JavaScript runtime Date models to trigger instant re-renders upon completion of each interval cycle: javascript const [time, setTime] = useState(new Date());useEffect(() => { let intervalId = setInterval(() => { setTime(new Date()); }, 1000);
开发者
Article: Trade-Offs in Multi-Region Architectures: Latency vs. Cost
Adding cloud regions changes latency and cost in ways simple math can't capture. This article presents a framework from multiple launches: decompose your latency budget before committing to infrastructure, choose deployment patterns by consistency and traffic profile, and optimize before expanding. A phased approach cut latency 35% through routing alone, before a new region brought it under 60ms. By Uttara Asthana
AI 资讯
Semantic Drift in LLMs: How Archetypal Attractors (Like “Goblin”) Emerge and How Structured Reflection Reduces Them
Large language models often develop recurring symbolic patterns — archetypes, metaphors, and memetic shortcuts — that appear across unrelated contexts. One observed example is the repeated emergence of fantasy-based metaphors such as “goblins,” “gremlins,” or similar entities when describing abstract system behavior, errors, or complexity. This article presents a structured analytical trace (A11 framework passes) showing how such patterns emerge from the interaction between reinforcement learning, cultural priors in training data, and user feedback loops. It also explores how introducing explicit interpretability layers can reduce the risk of these symbolic attractors becoming dominant explanatory shortcuts in model behavior. The first A11 pass S1 — Will Understand the causal mechanism: why the “goblin / fantasy drift” emerged in LLMs S2 — Wisdom (constraints) Main pitfall: confusing correlation (goblins appearing in outputs) with causation (why those specific symbols emerge) Also: “goblins” are not a standalone phenomenon they are a case of broader archetypal language drift S3 — Knowledge (what is actually known) There are 5 established mechanisms in LLM behavior: 1. RLHF reinforces “socially engaging metaphors” Models are rewarded for: vividness humor imagery human-like explanations ➡️ fantasy imagery tends to score highly 2. Internet prior already contains strong fantasy culture Training data includes: Reddit gaming discourse D&D culture fanfiction ➡️ “goblin / elf / troll” already exist as: universal behavioral archetypes 3. Compression effect (semantic abstraction) The model seeks compact semantic units: goblin = chaotic / greedy / messy / low-level failure mode ➡️ one token replaces a complex description 4. User feedback loop If the model says: “it’s like a goblin” users: react positively repeat it reinforce it in conversation ➡️ increases probability of reuse 5. Cross-task transfer (persona leakage) Stylistic patterns from: coding assistant mode creative mode
AI 资讯
Pure ReAct is expensive and fragile. Sparsi lowers costs and increases reliability.
If you’ve built AI applications in production recently, you’ve probably hit the "Agent Wall." You build a ReAct agent, give it 10 granular tools (search, extract, route, format), a massive system prompt, and tell it to go to work. It feels like magic...until you look at your latency metrics and token bills. Today’s agents act as interpreters. They re-derive the exact same routines from scratch on every single request . They embed massive tool schemas and reasoning histories into every loop. It's slow, it's incredibly token-hungry, and occasionally, they hallucinate tool calls, drop constraints, or get stuck in endless reasoning loops. In a production environment, even occasional errors can be critical failures that waste time and tokens. The problem isn't the ReAct pattern itself. The problem is that we are forcing the LLM to orchestrate low-level, predictable logic that should be deterministic code. We got tired of paying the "reasoning tax" for sub-routines that don't need it. So, we built Sparsi —a framework for shifting complex logic out of your ReAct agent's prompt and into deterministic "Macro-Tools" built as DAGs (Directed Acyclic Graphs). The Macro-Tool Pattern There are two ways to use Sparsi: as an end-to-end solution for a specific task, or to create higher-level tools that plug into your existing agents. The latter is where the magic happens. Instead of giving your ReAct agent 10 tiny, flaky tools and hoping it chains them correctly, you build one highly reliable, deterministic Sparsi DAG to handle that specific sub-routine. You then expose that DAG to your agent as a single Model Context Protocol (MCP) tool. The overall agent still drives the conversation, but it delegates the heavy lifting to a reliable macro-tool. We chose the DAG architecture for three main reasons: Deterministic & Testable: The graph is made of plain code. You only run AI where natural language understanding is strictly required. Parallel by Architecture: Independent branches run co
AI 资讯
I Got Tired of Maintaining Frontend Code. So I Built a Declarative UI Runtime.
Here is a question that sounds simple until you've actually shipped a UI: how many files does it take...
AI 资讯
The Paintbrush Paradox: Why the Monolithic Era of AI Is Crumbling
Over the past week, two narratives have been colliding everywhere I look. On one side, there's panic. AI is expected to replace marketers, engineers, and entire categories of knowledge work almost overnight. On the other, there are quieter but far more consequential signals: enterprise teams discovering their AI infrastructure is burning through API budgets far faster than expected. This isn't because the underlying models are weak, but because the systems built around them are fundamentally inefficient by design. These aren't separate stories. They're the same failure showing up in different places. A conversation with another developer made that gap visible in real time. He argued that auditing a 150,000-line codebase requires feeding the entire repository into a model in one single, massive pass. It's still a common assumption in mainstream tech: that an LLM works like a giant biological brain that you must fully load with raw text before it can begin to think. But that assumption is already outdated. Modern AI systems don't scale through brute-force context. They scale through structure. And that shift changes everything. Key takeaways Bigger context windows did not solve AI. Treating a frontier model as a monolithic processor that re-reads an entire system on every query is wasteful, dilutes attention, and hides bugs under raw volume. ARC-AGI-3 makes the gap stark: frontier models scored under 1% on interactive reasoning tasks that untrained humans solve at nearly 100%. The gap is architecture, not memory. The teams pulling ahead treat the model as one narrow component inside a larger system: intelligent routing, task decomposition, retrieval, and only the minimum necessary context. The next advantage is not the biggest model or the longest prompt. It is the system designed around the model. Prompting was the first generation; systems architecture is the next. The Myth of the Infinite Context Window When context windows expanded into the hundreds of thousands o
AI 资讯
Salesforce Education Cloud: A Modern Alternative to EDA
Executive Summary The Salesforce Education Data Architecture (EDA) has served educational institutions well for over a decade as a free, community-supported managed package. However, with the 2023 launch of the reimagined Education Cloud—built natively on the Salesforce core platform—institutions now face a strategic choice about their CRM foundation . While EDA remains supported and continues to function effectively, Education Cloud represents a fundamental architectural shift that offers significant advantages in simplicity, scalability, and access to innovation . This paper examines why Education Cloud is demonstrably easier to implement and maintain compared to its predecessor, addressing the key differences in architecture, data model, and ongoing operations. 1. The Architectural Advantage: Built-In vs. Bolted-On 1.1 EDA: A Managed Package on Top of Salesforce EDA is a managed package installed on top of the Salesforce core platform . As a managed package, it creates additional layers of complexity: Installation and Updates: EDA requires separate package installations and updates that can lag behind Salesforce's native release cycle Namespace Conflicts: The managed package introduces its own namespace, potentially creating compatibility issues with other tools Translation Limitations: EDA's localization has documented issues, including a known problem where the Preferred Phone functionality fails when users switch to languages other than English Record Type Validation Bugs: Deactivating an account record type can block contact creation—a validation error that requires manual workarounds 1.2 Education Cloud: Native to the Core Platform Education Cloud represents a fundamentally different approach. Rather than being a package installed on Salesforce, Education Cloud is built directly on the Salesforce core platform . Key Advantages: No Package to Install: Education Cloud runs natively on the Salesforce core platform, eliminating the need for separate managed pack
AI 资讯
Architecture Decisions Behind Building a Simple Personal Software Tool
How I moved from a traditional web application mindset to exploring local-first architecture I wanted to build a simple software tool for my personal use. Nothing complicated. Something in the category of tools people build for themselves: A personal expense tracker A budgeting application A private knowledge management tool A personal organization system The important characteristic was this: The data belonged to one person. It was not a social application. It was not a collaboration platform. It did not need users interacting with each other. There was no requirement for: Public profiles Sharing updates Real-time collaboration Social features It was simply a tool that helped one person manage their own information. When I started thinking about building it, my first instinct was the most natural one for me. I am a web application developer. My comfort zone is building web applications. So my first thought was: "Why not build a Ruby on Rails application?" Something like: User | Web Application | Ruby on Rails API | PostgreSQL Database This is an architecture I have worked with many times. The workflow is familiar: Create models Build controllers Add authentication Store data in a database Deploy the application Access it from anywhere This is a proven architecture. For many products, this is exactly the right approach. But while thinking about this project, I asked myself a different question: Am I choosing this architecture because the problem requires it, or because it is the architecture I already know? That question changed the direction completely. Understanding The Actual Problem Before choosing technology, I wanted to understand the nature of the problem. What kind of application was I actually building? There is a big difference between building: A social network A marketplace A collaboration platform A communication application versus building: A personal tool A private utility A single-user productivity application In the first category, the server is the
AI 资讯
Dev Log: 2026-07-09 — one source of truth, three times over
TL;DR Three unrelated repos, one recurring theme: derive from a single source of truth instead of duplicating it. Shipped a registry-driven sidebar section switcher (public), converged a multi-system password flow, and pushed on a customer-data identity engine. Details on the first two live in their own posts today. 1. Registry-driven sidebar switcher (public) Added a section switcher to the kickoff starter kit. The sidebar, the switcher, and breadcrumbs all read the same config/menu.php list, and the active section is picked by longest URL-prefix match — so a detail page like /admin/roles/42/edit keeps its parent selected. Full write-up in the focused post. 2. One canonical password flow Converged two apps that each rolled their own password-change/reset logic onto a single shared engine, with a fixed order (directory → external DB → local app) and no config-toggle to skip backends. A password that syncs to some systems is worse than one that fails outright, so partial success is now impossible by construction. Also fixed a subtle status bug — an unreachable backend reports skipped (a runtime fact), not disabled (a config state that no longer exists) — and added an audit log so "did it sync?" is a query, not a guess. Separate post today goes deeper. 3. Identity resolution engine (customer data work) Steady progress on a CDP-style identity layer: an idempotent, header-versioned ingest endpoint that queues incoming records, then a resolution engine that can resolve, merge, unmerge, and quarantine profiles. Two things I care about here: PII handling: sensitive identifiers are encrypted at rest with a blind index for lookups, and masked in audit trails — you can search on a value without storing it in the clear. Right-to-erasure: an erasure cascade plus an erasure log, so a deletion request actually propagates and leaves a defensible record that it did. ingest -> queue -> resolve -> profile | +-> merge / unmerge / quarantine No code from this one here — it's teaching t
AI 资讯
When a password sync is 'partly done', it's a bug: converging on one canonical flow
TL;DR Two apps each had their own password-change/reset logic, plus config toggles to enable/disable backends. That combination quietly allowed partial syncs. Fix: one shared engine, one canonical order , backends mandatory (no config-disable), and every attempt written to an audit log. Lesson: for a write that spans several systems, "configurable steps" is a footgun. Make the flow fixed and make failure loud. The setup A user changes their password. Behind the scenes that single password has to land in several systems — a directory, an external database, and the app's own store. Two separate apps were doing this, each with slightly different code, and each with config flags like sync_oracle => true|false to turn backends on and off. Sounds flexible. It's actually a trap. Why configurable backends are a footgun TL;DR: a password that updates 2 of 3 systems is worse than one that updates none — because now the systems disagree and nobody gets an error. The moment a backend is optionally skippable, "skipped" and "failed" blur together. Someone flips a flag in one environment, forgets it in another, and now prod and staging run different flows. Debugging a login failure means first reverse-engineering which steps actually ran. Before After Each app had its own reset logic One shared engine, both apps call it Backends toggle via config Backends are mandatory, always run Order implicit / differed per app One canonical order: New directory → external DB → local app "Did it sync?" answered by guessing Every attempt logged with per-service status The canonical order The order isn't cosmetic. It runs most-authoritative-first, so if a downstream step fails you haven't already told the user their new password works. change/reset request | v [ New Directory ] --ok--> [ External DB ] --ok--> [ Local App store ] | | | fail fail fail | | | +----> stop, record per-service status, surface the failure Same engine, same order, both apps. A change API and a reset flow are just two entr
AI 资讯
AlloyDB Ships Proxy Models That Replace LLM Calls with Local Inference Inside the Database
Google shipped AlloyDB AI functions GA with a proxy model architecture that trains a lightweight local model from LLM outputs, then runs queries at database speed without external calls. Smart batching delivers 2,400x throughput improvement. The proxy model reaches 100,000 rows per second in preview, but benchmark numbers apply only to ai.if in internal testing. By Steef-Jan Wiggers
AI 资讯
Multi-tenant SaaS architecture patterns
Multi-tenancy is the decision that quietly shapes your entire SaaS backend. Get it right and you scale smoothly to thousands of accounts. Get it wrong and you're rewriting your data layer under load, mid-growth, with customers watching. The good news: for most products the right answer is simpler than the internet suggests. The three models There are three canonical ways to isolate tenants, and they trade isolation against operational cost: Row-level (shared schema). Every table has a tenant_id\ column, and every query filters on it. One database, one schema, all tenants together. Schema-per-tenant. Each tenant gets its own PostgreSQL schema inside a shared database. Stronger isolation, more objects to manage. Database-per-tenant. Each tenant gets a dedicated database or instance. Maximum isolation, maximum operational weight. Why row-level wins for most SaaS For the overwhelming majority of B2B SaaS products, row-level multi-tenancy is the right default. It's the cheapest to operate, the easiest to run migrations against, and it scales further than founders expect. The objection is always "but isolation" — and Postgres has a strong answer. Row-Level Security (RLS) lets the database itself enforce that a query can only see its own tenant's rows. With Supabase , RLS is the native model: you set a policy once, and even a buggy query can't leak across tenants. Combined with a tenant_id\ on every table and an index that leads with it, this pattern comfortably serves large customer bases. One caution from hard experience: write RLS policies so helper functions run once per query, not once per row . A policy that re-evaluates a lookup for every row will quietly turn fast endpoints slow as tables grow. Wrap the check so the planner runs it as an init-plan. When to reach for stronger isolation Escalate deliberately, not reflexively: Regulatory or contractual isolation — a customer requires their data in a physically separate database. Noisy-neighbor risk — one whale tenant'
AI 资讯
Monorepo vs polyrepo
How you split your code into repositories seems like a plumbing decision, but it quietly shapes how your team collaborates, ships, and reasons about the system. A monorepo keeps everything in one repository; a polyrepo gives each service or app its own. Neither is universally right, and the loudest opinions online usually ignore your actual stage and team size. Here's how to think about it clearly. What a monorepo buys you A monorepo puts your web app, mobile app, backend, and shared libraries under one roof. The advantages are real, especially for smaller teams: Atomic changes. Update a shared type and every consumer in the same pull request. No cross-repo coordination dance. One source of truth for tooling. A single lint, format, and CI config instead of drift across a dozen repos. Effortless code sharing. Shared TypeScript packages are just imports, not published versions you have to bump and reinstall everywhere. Easy refactoring. You can find and fix every caller of a function because it's all in front of you. Tools like Turborepo and Nx make this practical by caching builds and only running work for the parts that actually changed. What a monorepo costs The trade-offs show up as you grow. Build and CI times can balloon without smart caching. Access control is coarser — it's harder to give a contractor one service without the whole codebase. And a naive setup rebuilds and tests everything on every change, which gets slow fast. Good tooling mitigates all of this, but you have to invest in it deliberately. What a polyrepo buys you Separate repositories give each service hard boundaries . A team owns its repo end to end, deploys on its own schedule, and can't accidentally reach into another team's internals. Access control is naturally granular, CI for each repo is small and fast, and the blast radius of a bad change is contained. The cost is coordination. A change that spans services becomes multiple pull requests across multiple repos that must land in the right
AI 资讯
Microservices vs monolith
Microservices have a marketing problem: they're associated with the engineering cultures of Netflix and Amazon, so ambitious teams assume adopting them is what serious companies do. But those companies moved to microservices to solve problems of enormous scale and huge headcount — problems you almost certainly don't have yet. For most products, splitting too early is one of the most expensive mistakes you can make. Here's the honest trade-off. What a monolith actually gives you A monolith is one deployable application. That simplicity is a feature, not a limitation, especially early: One codebase, one deploy. No orchestration, no service mesh, no distributed tracing just to understand a request. Simple debugging. A stack trace crosses your whole request. You're not correlating logs across five services to find one bug. Fast local development. Run the whole app on your laptop and iterate. Easy transactions. Data consistency is a database transaction, not a distributed saga you have to design and get right. The modern version isn't a big ball of mud. A modular monolith enforces clean internal boundaries — separate modules with clear interfaces — giving you much of the organization of microservices with none of the network overhead. What microservices actually cost Splitting into services doesn't remove complexity; it moves it from your code into the network, where it's harder to see and reason about. You inherit a long list of new problems: Distributed systems failure modes — partial failures, retries, timeouts, and eventual consistency become your daily reality. Data consistency across services — no more easy transactions; you're designing sagas and compensating actions. Operational overhead — every service needs deployment, monitoring, logging, and on-call. Slower local development and debugging — reproducing a bug can mean running half your architecture. For a small team, this overhead can consume the very velocity you were trying to gain. When microservices genuin
开源项目
Automating cross-repo documentation with GitHub Agentic Workflows
Explore how the Aspire team turns merged product changes into SME-reviewed docs pull requests, closing the gap between release and documentation. The post Automating cross-repo documentation with GitHub Agentic Workflows appeared first on The GitHub Blog .
AI 资讯
Why Software Can't Tell You It's Wrong
Software architecture debates have a problem that most other engineering disciplines don't: the alternative was never built. When a bridge fails, the failure is physical, attributable, and measurable against every other bridge that didn't. The engineering decisions that caused it can be isolated, traced, and corrected — not just in theory, but in the next bridge, because the material itself produces feedback that no amount of professional opinion can override. Steel deflects. Concrete cracks. Physics doesn't care what the architect believed. Software produces no equivalent feedback. A system built around the wrong abstractions compiles, runs, ships, and passes its tests just as readily as one built around the right ones. A bug introduced by a misaligned domain model looks identical, from the outside, to a bug introduced by a typo. A feature that took three times longer than it should have, because the structure made it harder than the business logic warranted, produces no artifact that distinguishes it from a feature that was simply difficult. The cost is real. The cause is invisible. This is the unfalsifiability problem, and it runs deeper than "we can't measure everything." It means that when a system becomes expensive to change, the diagnosis almost always lands on the wrong variable. The domain is complex. The requirements changed. The previous team was careless. Almost never: the structure was wrong, and the structure was wrong because nobody ever built the other version of it to compare against. That version doesn't exist, it never will, and every architectural argument in the industry is conducted in its absence. This would be a purely philosophical problem if there were nothing to do about it. There is something to do about it — but it requires accepting that the standard metric for software quality, whether it works, is measuring the wrong thing entirely. The Metric That Hides the Problem The natural substitute for "is this good engineering" is "does it wor