4031 stories
·
4 followers

Resisting Cognitive Surrender

1 Share

Working Notes: a commonplace notebook for recording & exploring ideas.
Home. Site Map. Subscribe. More at expLog. — Kunal

This particular note is around exploring cognitive surrender: uncritically accepting whatever agents output without actually thinking, exploring or considering alternatives. Working this way is extremely fast, not particularly taxing, and unsurprisingly seductive.

And yet I find myself repeatedly questioning if this is actually a good way to apply agents: often enough I find myself making suboptimal decisions, accruing technical debt and reducing my familiarity with the system I’m working on instead of improving it.

As we collectively rethink how we work I’ve been finding it useful to read and share other people’s workflows, and consciously write about and examine my own. This particular post focuses on finding the right balance of trust while working with agents.

managing complexity

Cognitive surrender is seductive

One of the virtues of being a great programmer is to be lazy. After more than a decade of training myself to look for the shortest and simplest path it’s rather attractive to be able to simply hand over the problem. If I can spin up a software factory, why wouldn’t I?

There’s also a lot of peer pressure (or game theory) at work: if any of my colleagues have seemingly surrendered, then I’m only going to look worse if I spend too much time trying to do silly things like understanding what I’m working on. And, of course, while everyone else is a slop-cannon generating code faster than they can read it I can build a meticulously designed software factory manufacturing perfect designs. The sheer volume of work also appears remarkably productive – we’ve all talked about just how many more PRs we ship every day.

This tends to get compounded by the agents’ expressed confidence & conviction. Perhaps an inadvertent consequence of RLHF, but models tend to be astonishingly confident in what they recommend (and perhaps even more blasé while admitting they made a mistake). This makes it too easy to take their answers at face value, with whatever social programming I seem to have evolved with.

OSS projects – particularly those facing time pressure – seem to accrue tremendous complexity quickly, to the point that it feels like the only way to interact with a project in any sane time frame is by heavily relying on agents to navigate and modify and test the code. This is also a self-reinforcing feedback loop: broken windows multiply rapidly with agents on the loose. [1]

Technical debt and incidental complexity have a fairly attenuated feedback loop: complexity introduced by slop doesn’t bite immediately; it’s far more subtle and compounds over time when I’m not paying attention.

Beyond all of that, I have to mention the hype cycle. We all should be skipping Netflix to watch talks by Anthropic engineers on making loops (or the agentic workflow du jour). [2]

Why not surrender?

It’s not entirely obvious that it’s a bad idea to surrender: if it’s easier and better, then why not take that path? So far, my personal answer is that I need to take the easier path consciously and intentionally, with enough effort to mitigate downsides.

Part of what makes me deeply uncomfortable is suffering from a form of Gell-Mann amnesia while working with agents. When I have expertise and the overall design direction I can generally simplify the output significantly, controlling for complexity. When I don’t they seem to be the smartest engineers in existence – far beyond the more squishy, organic variety – and all I can do is follow in awe. And then the agent gets stuck creating a directory and I have to reset all my assumptions.

For the current state of the art (October 2026) I generally find maximal use of agents leads to a significant explosion in complexity: something that mostly works, with extremely surprising edge cases and bugs. These are generally the projects with hundreds of thousands of lines of code shipped rapidly, breaking the scale supported by most software development tools, so you also need to revisit those – and this compounds rapidly.

I have a strong aversion to incidental complexity, and generally refuse to build, maintain or extend it: it’s fine for a proof-of-concept, but it must end there. For systems that need to keep working, steering the design aggressively towards simplicity and modularity is what lets me build something I can actually operate (with and without agents).

As models continue to improve rapidly, I expect the previous argument to go away as the models learn and can express a broader sense of engineering taste, good design and quality. The other reason – which I unfortunately expect to persist – is that my personal understanding and mechanical sympathy for systems I maintain erode extremely rapidly, or never get a chance to develop.

In the early days when I would build things by hand I’d be able to quickly diagnose any bug or misbehavior based on my familiarity with building and maintaining the code: the more I rely on agents, the more my only option is to spin up one more session and hope; and the automated fix then further reduces my understanding in a self-reinforcing loop. Without context, I no longer have much meaningful judgement and can’t engage – or handle it in context.

The Ironies of Automation (1983) is referred to often in articles similar to this one. I’d recommend directly reading the paper if you haven’t: it’s fully relevant to the decisions we have to make today. The paper warns that it becomes even harder to deal with tasks an agent fails at because we never manage to get any practice with the easier tasks; nor do we get a chance to internalize what a system feels like under standard operating circumstances.

The Ironies of Automation

At the end of the day, I’m responsible and accountable for what I build, not the agents. Surrendering agency and not thinking basically makes me accountable without any meaningful ownership. There’s also the small matter of pride in the quality of my work.[3]

Solutions

The sombre opening shouldn’t lead you to believe that I’m not excited about the sheer potential unlocked by AI, and the opportunities to build things that I would never have been able to without it. It’s more about resetting expectations, explicitly working through the tradeoffs involved and choosing which ones are acceptable. And finding ways to maintain the quality and craftsmanship I care about.

There are still tradeoffs

The first step for me has been to internalize that I can’t truly have my cake and eat it: I can go terribly, inhumanly fast at building things but I need to accept that there’s no way to retain the mechanical sympathy, depth and confidence I used to have without putting in the effort. Time that used to be only counted as building a system also involved comprehension; agents can drive the time to build to zero but the next bottleneck – comprehension – hasn’t moved much so far.

The hype cycle occasionally can make it hard to communicate this explicitly: a lot of the communication around agentic loops tends to assume that there are no downsides whatsoever.

Choose your vibe limit & triage

Several months ago I defined my vibe limit as the complexity of the change I can make with sufficient confidence using agents. I like the risk/complexity curve enough to post it again:

Vibe Limits

The next step is figuring out where I land: there are several projects where good enough is fine, or the problem is sufficiently sandboxed that I’m happy to live with whatever the agents generated. On the other hand, if the system is important, fragile, can’t be sanity checked easily or isn’t particularly well isolated I need to directly spend my time.

Aggressive prioritization, triage, and constantly recalibrating myself become really important in this ecosystem: I should explicitly choose where to surrender agency and where to spend my time (not unlike leading a team, except the pace is much faster). Constantly reviewing my predictions and the outcomes helps a lot in recalibrating, particularly with new model drops.

Watch out for automation bias

I also find myself needing to be much more mindful while working. A warning sign I watch out for these days is if I find myself repeatedly tapping “yes, continue” in a session. At that point either I should figure out what it would take to completely delegate the problem to Claude instead of trying to micro-manage the agent – or realize that I stopped thinking and I need to check the decisions being made.

Completely delegating the problem generally means building a better sandbox or feedback loop, or figuring out ways to be able to sanity check much more easily before shipping to production. Alternatively, if I need to engage much more deeply I’ll use some of the other tactics described below.

Force yourself into the loop

The premise of augmenting myself by working in the loop with powerful thinking machines was a large part of my decision to join my current company. This generally comes down to directions you can give the model to reduce the size of the steps it takes, or explicitly choosing to drive instead of passively observing.

For projects I deeply care about, choosing to drive instead of letting the model drive is one way to intervene in every single decision. It’s much slower to type things out, but it does force me to engage with every decision and gives me an opportunity to override it. In fact, for this post I’m using a Codex session to edit: help me tighten the post, point out the small typos, punctuation errors, or half-finished sentences that tend to embarrass me after I explicitly share a post publicly – but I make all changes by hand.

In the AGENTS.md for the notebook:

Never edit files directly, always wait for the author to request or confirm changes, or let him make the edits directly.

This is reminiscent of how I used to work with Stack Overflow: never copy-paste code; instead write it out explicitly while cross-checking with documentation. Either I’d learn and internalize something new or I’d realize the Stack Overflow answer was suboptimal or outdated.

Force comprehensibility

We don’t need to limit ourselves to existing interfaces anymore: with agents it’s also possible to have them build a tremendous amount of scaffolding to support comprehension and make changes in ways that are digestible.

Often enough for larger, complex stacks I have the agents build me a custom view for the Pull Request with 4 columns: the standard 2 for the diff, a 3rd column with running commentary from the agent on why it made a particular change and finally the 4th column as a place for me to add comments and directions.

Getting the agents to make stacks of changes with the explicit direction to “Make the change easy, then make the easy change” works really well. I used to spend a lot of time trying to make my diffs easily reviewable to respect the reviewers’ time – now I can ask the agents to do the same for me.

It’s also very valuable to dive into actual execution with a debugger (or have an agent manipulate the debugger on your behalf) till you get a deep sense of how things are flowing through the program, with the confidence that this is the real execution path.

Another example is to make harnesses explain what they’re doing: I’ve built several variations of command-line helpers that transparently fit into my shell sessions (x being the last public version). In my most recent iteration, I explicitly ask the model to explain any obscure flags and commands used so that I can learn as I go.

When you do decide to delegate

Sometimes, it does make sense to hand over the problem to an agent: it could be too big, not valuable enough, time could be too short, or you just want to get a first prototype out to explore a problem end-to-end.

This one is probably an essay by itself: adapting old-school best practices when you have infinitely fast stochastic intelligence on top. The idea here is to reduce the risk in making changes, flattening the vibe-limit curve and making it possible to make bigger changes safely.

Beyond giving the agent some means to verify itself against the goal you’re aiming for, I find it very useful to:

  • Observability: Invest heavily in observability, both black-box and white-box, and make sure to keep a direct handle on the metrics instead of solely relying on the agents’ view. As a habit I prefer to triangulate onto a behavior with multiple sources of metrics, and that becomes even more important with systems rapidly becoming opaque.
  • Non-functional requirements: Don’t forget to observe resource utilization and other non-functional requirements: these can be canaries for unexpected behavior.
  • Deterministic validation: Build mechanical straitjackets for the model: have held-out pieces of code or deterministic tools for validation and observations as a hold-out against the model misunderstanding or glitching.
  • Shadow Traffic: Make it possible and cheap to run a deployed candidate against shadow traffic with no side effects: keep it as similar to production as possible, and this can be the final gate to prevent surprises.
  • Style guides: Give the model a style guide based on your existing code and work. I’ve found Claude’s output far more to my taste after having the models generate a style guide based on all the code and blog posts I’ve written in the past.
  • Fast deploys: An often maligned motto at Facebook used to be Move Fast & Break Things: that, too, is an intentional tradeoff to make. If you can’t be sure of quality, make it very easy to deploy code as well – so changes can be shipped and reverted extremely rapidly.
  • Rethink what’s possible: It’s surprisingly easy to write and rewrite systems from scratch rapidly as you learn. Build to throw, evaluate, and repeat to get something knocked into great shape – I’ve built projects in multiple iterations, giving the agent the previous iteration and its limitations as initial context and constantly finding myself able to deeply increase the quality. This doesn’t work as well when you’re punishing your code reviewers though, so make sure to align with your team, or simply don’t get the first several iterations reviewed.

Good design is a force multiplier

In Notes on the Synthesis of Form Christopher Alexander has a wonderful example demonstrating the value of decomposition – or building a lightly coupled, cohesive system to be able to succeed quickly.

No complex adaptive system will succeed in adapting in a reasonable amount of time unless the adaptation can proceed subsystem by subsystem, each subsystem relatively independent of the others.

Screenshot 2026-11-01 001757

Whether agents or humans are doing the work, a good design makes the system much easier to understand, iterate on, validate and extend. As you learn the limitations of the design, you also now have the ability to redo it much more rapidly than ever before. Regardless of how much depth you decide to maintain in your projects, I’d make sure the broader structure continues to make sense.

Additional reading

There are several interesting articles, talks and books that are relevant:

  • Addy Osmani with several additional techniques
  • Guy Levi recommending leaning into critical thinking
  • Cory Doctorow talking about handling being forced to use AI
  • Stuart Halloway emphasizing that AI is automation, and the importance of friction to build metis.
  • Elizabeth, SigNoz on skills atrophying.
  • Ricard Solé et al. on LLMs as a cognitive virus, modeling the interaction and consequences of cognitive offloading.

I’m curious if you have any other recommendations around effectively leveraging agents without losing context – I’d love to hear about additional experiments to try or workflows to adopt! Particularly if you’ve successfully recovered projects that collapsed into slop. Discuss on Hacker News.


  1. I have constantly been expecting more software to fail under the weight of its own complexity. One of my hot takes is that this hasn’t happened at the scale and magnitude I expect yet because agents became smarter fast enough to keep up with the debt introduced by the previous generation. ↩︎

  2. You’ll pry my weekly indulgence in The Great British Baking Show from my cold, dead hands. ↩︎

  3. You could argue that this is a very “Individual Contributor” approach to building things, and that managers deal with this all the time. I’ll quote Andrew Grove on management: “delegation without follow-through is abdication” – you still need to engage to get the outcome you need. ↩︎

Read the whole story
emrox
7 minutes ago
reply
Hamburg, Germany
Share this story
Delete

Introducing Adaptive Dark Mode

1 Share

27.3

Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete

Design the interface for functionality not familiarity

1 Share
Previous: macOS 27.2 fixed 263 CVE, credited 262. Who was uncredited? Me, I think.
Articles index Jeff Johnson (My apps, PayPal.Me, Mastodon)

October 29 2026

This blog post is about touch screen Macs, but I’ll start by talking about touch screen cars. Vehicle manufacturers have increasingly replaced physical controls in cars with touch screens, and it hasn’t gone well, because the touch screens frustrate drivers. As a resident of the Upper Midwest who drives wearing gloves in the winter, I suspect that the idea for touch screens came from somewhere warmer than the traditional home of the automotive industry, Detroit. For further reading on the serious, indeed dangerous problems with touch screens in cars, I found a couple of recent articles from Popular Mechanics and The Conversation.

Smartphones have become ubiquitous, bringing ubiquitous familiarity with touch screen interfaces. Nonetheless, a touch screen is not the best interface for all purposes. In the case of cars, familiarity breeds contempt! The introduction of touch screens to smartphones was inspired by the physical limitations of the devices. The largest iPhone ever made, the new iPhone Duo, is still significantly smaller when unfolded than the smallest MacBook. Needless to say, the original 2007 iPhone was tiny compared to a MacBook. Mobile phones with a physical keyboard must have a correspondingly smaller screen, so manufacturers eliminated the physical keyboard to maximize screen size, relying entirely on a touch screen interface, including a software keyboard. In this case, touch screens were well motivated.

Over the years I’ve owned many different computing devices of various sizes; from Apple: iMac, Mac Pro, Mac mini, MacBook Pro, iPhone, iPad. I’ve never once tried to control a Mac by touching its screen, not even absentmindedly. I simply never developed that habit. Many other people, however, when first introduced to a Mac, having only used touch screen computers such as smartphones and tablets, habitually attempt to control the Mac by touching its screen. This habit or expectation is cited as justification by defenders of touch screen Macs. In a Wired interview yesterday, Apple Senior Vice President of Worldwide Marketing Greg Joswiak said, “There’s a generation of young creators and young people using our MacBook Pros that expect to touch.” In my opinion, such an expectation is a terrible reason to introduce touch screen Macs. The habit of touching Mac screens can be broken and is worth breaking, because for most purposes the traditional Mac interface of a keyboard and indirect pointing device (mouse or trackpad) is so much more powerful and productive than the touch screen of an iPhone or iPad.

Before you cite the ungodly AAPL market capitalization as proof that Joz’s opinion trumps mine, consider how Apple is the same company that gave us howlers such as the trash can Mac Pro, Touch Bar, butterfly keyboard, Liquid Glass, and gave a gold statue to Trump. I’m not even making any claims about the future profitability of touch screen Macs. I just think it’s a poor design.

Ironically, people like me who were introduced to computers before the smartphone era are ridiculed as “resistant to change,” yet I’ve managed to learn how to use iPhones and iPads (the latter without a keyboard), so why can’t people who were introduced to computers during the smartphone era learn how to use Macs? Let me quote from a blog post I wrote earlier this year, If computers are the future, why are computer users expected to be permanently illiterate?

The iPhone seems to have engendered a culture of anti-intellectualism and learned helplessness so pervasive that users have become evangelists for their own disempowerment. They demand that all software be “intuitive,” by which they mean idiot-proof, so simple that a n00b can use the software effortlessly and effectively. A suggestion to read the fine manual is greeted with charges of user hostility. Those who habitually, endlessly scroll YouTube or social media would balk at investing a little time to master the computing tools they use daily. Perhaps they would be surprised to learn that the supposedly intuitive 1984 Macintosh came with 170 page manual. A common conceit is that the Mac was easier to use than other computers out of the box; the reality is that the Mac was easier to use after the initial learning curve. The system went out of its way to establish internal consistency and interoperability, but the user first had to make sense of the system and its principles.

A MacBook Pro is bulkier than an iPhone, can’t fit in your hand or your pocket. That’s a disadvantage. Thankfully, a MacBook Pro has many advantages that outweigh the disadvantages. The larger screen size, the physical keyboard, and the less restrictive operating system allow Mac users to perform the same tasks with vastly greater ease than on iPhone or iPad and, moreover, to perform tasks not even possible on iPhone or iPad. It’s a shame to introduce new users to Mac by telling them to use it in the same way they used their old familiar devices, which are strictly limited by both hardware and software. A Mac is a terrible thing to waste! Not only functionally but also financially, since Macs on average have higher prices and longer effective lifespans than iOS devices. Steve Jobs (long before iPhone) called computers “bicycles for our mind.” I feel that adding touch screens to Macs is like adding training wheels to our bicycles. Some kids are given training wheels temporarily, but the ultimate goal is to outgrow training wheels, not to grow into them. The difficulty of learning to ride a bike without training wheels pays off in short order, giving the rider greater speed and maneuverability. In what dystopia would we consider training wheels the future of biking? (I suppose the same dystopia that would remove the steering wheel from our cars.)

In general, Hacker News comments tend to be appalling. Occasionally, though, there’s a diamond in the rough. I’d like to end by quoting one of those. Admittedly, I haven’t independently verified the veracity of the comment, but it seems truthy enough to cite, at least as fodder for debate:

I bought a laptop for a relative and didn't realise it doesn't have touchscreen. They complained for a day and I often saw them try to touch the screen and then being disappointed it doesn't work. Week later they never mentioned it again and use the laptop just fine.

When I was buying them a second one and asked about touchscreen, they said they don't care anymore for it, so second laptop also was without touchscreen.

Jeff Johnson (My apps, PayPal.Me, Mastodon) Articles index
Previous: macOS 27.2 fixed 263 CVE, credited 262. Who was uncredited? Me, I think.
Read the whole story
emrox
6 days ago
reply
Hamburg, Germany
Share this story
Delete

Beyond API Compatibility: Building a Tool to Measure the Blast Radius of Library Changes

2 Shares

By Roberto Perez Alcolea, Java Platform Team

Quasar connects a proposed API change with observed references in consumer repositories, giving the producer evidence for a release decision

At Netflix, shared Java libraries support applications developed across a large, independently evolving repository ecosystem. A library change begins in one repository, but its impact can reach many others. Producers can see the API diff in front of them. What they often cannot see is who still depends on the symbols that changed.

The need for that visibility grows as coding agents take on more of the software development lifecycle. An agent can accelerate a local edit, but without cross-repository context it cannot judge downstream risk or help plan consumer migrations. The evidence a producer uses to assess a change can also guide the agent working on it.

Consider a common case: removing a deprecated API. Deprecated entry points expand the surface producers must test, document, and support, and they can constrain how a library evolves.

Suppose a replacement has been available for several releases and the old method cannot express options required by new behavior. The library’s tests pass, and a compatibility checker flags the removal. The producer still cannot answer the questions that determine what to do next:

  • Does any consumer still call this method?
  • Are consumers concentrated on one version or spread across several generations?
  • Does another library implement or wrap the API, multiplying its impact?
  • Is direct coordination sufficient, or does this require a deprecation and migration campaign?

At small scale, producers can ask nearby teams or search a handful of repositories. Across many repositories, it is harder to find every caller of a method and the library version each one uses. Those answers are scattered across consumer codebases and builds.

Without that evidence, a producer may release a breaking change and discover the impact through consumer failures, or preserve an old API indefinitely because the risk is unknown. Libraries need to evolve, and their producers need evidence that helps them do so intentionally.

We built Quasar to index symbol definitions and references across Netflix repositories. For library producers, that shared index helps answer two questions:

  1. What changed in the library’s public API?
  2. Which repositories use the exact symbols that changed?

The first identifies a potentially incompatible change. The second estimates its observed blast radius. Together, they turn a generic compatibility warning into evidence a producer can act on before merging or releasing.

From API Changes to Consumer Impact

Existing techniques each see a different part of the problem. Binary and source compatibility tools identify contract changes, but cannot tell who uses the changed API. Dependency graphs show declared reach, but cannot prove that code calls a particular method. Text search may miss overloads, inheritance, or the artifact version behind a call. Consumer builds provide strong validation, but running them across the fleet is expensive.

Quasar builds on SCIP, an open interchange format for semantic code intelligence. Language-specific indexers encode definitions, references, and relationships using stable symbol identifiers. Quasar retains API definitions for library versions and commits alongside references from consumer repositories. That shared identity lets it connect an API change in one repository to exact usages elsewhere, even when those repositories were indexed independently.

On each enrolled CI build, language-specific indexers submit SCIP indexes to Quasar’s ingestion service. It writes API definitions and consumer references as Parquet in Amazon S3, retaining the symbol identity, dependency version, and source location needed to investigate a change.

During pull-request review, Quasar compares indexed base and head definitions and counts direct consumer references with Amazon Athena. Quasar exposes those findings through its REST and GraphQL APIs and MCP server; follow-up usage queries provide dependency-version breakdowns and source locations. A separate compatibility-impact assessment can also follow implementations and their callers when a producer supplies a changed JVM symbol.

Consider this simplified API change:

public interface Client {
- Result getLegacyValue(Request request);
+ Result getValue(Request request, Options options);
}

For a detailed compatibility-impact assessment of this removal, a producer-side tool supplies the old method descriptor. Quasar constructs its canonical symbol identity. This abridged excerpt from the direct-reference portion of Quasar’s Amazon Athena query shows the essential match:

SELECT c.change_id, 'DIRECT_REFERENCE' AS evidence_kind,
r.scm_type, r.org, r.repo, r.dep_version, r.file_path
FROM requested_changes c
JOIN quasar.symbol_refs r
ON r.symbol_canonical = c.target_canonical

requested_changes contains the API changes submitted by the producer. The SQL excerpt finds repositories that call the removed method. Quasar also checks implementations and calls through them, so it can count each affected repository once. It returns sample dependency versions and file locations to help investigate the result.

For the Client change, this tells the producer which repositories still use getLegacyValue, which versions they use, and where some of those calls occur. That helps the producer decide whether to coordinate a migration before removing the method.

Bringing the Analysis Before Release

Version-to-version comparison is valuable when planning an upgrade or writing a migration guide. Producers benefit even more when feedback arrives during code review.

For pull-request analysis, Quasar stores API definition snapshots keyed by commit. Given a base and head commit, it classifies symbols as added, removed, or signature-modified. Removals and modifications then become candidates for consumer-impact analysis.

An incompatible change is not automatically a high-risk change. Quasar reports the observed impact so the producer can decide what to do; it does not enforce a release policy. “No references observed” means only that Quasar found none in the indexed population. Reflection, configuration, dynamic loading, stale branches, or incomplete indexing can hide consumers. The result needs to show whether the requested commits were indexed, how fresh the consumer indexes are, and whether evidence was truncated.

Pull-request review requires indexed snapshots for the exact base and head commits. If either is unavailable, Quasar reports that it cannot compare them; it does not substitute a default-branch snapshot. This keeps a missing comparison from looking like a clean API diff.

Return to our Client change. This illustrative report brings together signals available through Quasar's API comparison, consumer-usage queries, and library-level criticality. It is not a literal response from one API:

{
"change": "REMOVED",
"symbol": "Client#getLegacyValue(Request)",
"affectedRepositories": 137,
"versionDistribution": [
{ "version": "4.2.1", "repositories": 86 },
{ "version": "4.1.7", "repositories": 38 },
{ "version": "3.9.4", "repositories": 13 }
],
"sampleConsumerLocations": [
{
"repository": "checkout-service",
"filePath": "src/main/java/com/example/checkout/CheckoutClient.java",
"lines": [84, 129]
},
{
"repository": "client-wrapper",
"filePath": "src/main/java/com/example/client/ClientAdapter.java",
"lines": [57]
}
],
"libraryCriticality": {
"tier": 1,
"basis": "highest-tier downstream application"
},
"comparison": {
"baseShaFound": true,
"headShaFound": true
}
}
An impact report shows 137 affected repositories distributed across library versions 4.2.1, 4.1.7, and 3.9.4.

The repository count is symbol-specific: in this example, 137 indexed repositories refer to the removed method. The version distribution reveals a dominant cohort on 4.2.1 and a smaller long tail still on 3.9.4. A producer can inspect affected repositories and retrieve indexed file paths, with line numbers where the index provides them. The JSON shows only two sample locations to keep the example readable. The filePath and lines shape mirrors Quasar's query contract. The tier is broader context about the library, inherited from its highest-criticality downstream application; it does not imply that all 137 callers are Tier 1.

Together, those signals change the producer’s plan. Instead of merging the removal and waiting for failures, the producer can retain and deprecate the old method, publish a migration path, coordinate a broader migration, and track the long-tail versions before removal. File paths and available line numbers turn that scope into a concrete work list for engineers or coding agents. The same API diff paired with weak or stale evidence would lead to a different action: refresh the indexes before deciding. The value is not merely detecting the removal; it is choosing a proportionate next step.

A pre-release workflow enriches API changes with consumer impact and evidence quality before the producer decides how to proceed

A Polyglot Foundation with SCIP

The shared SCIP format also lets Quasar index several language ecosystems. Each language indexer resolves its own code, while Quasar can use the resulting symbol identities to find references across repositories.

Conceptually, client-lib indexes Client#getLegacyValue(Request) as a definition, while checkout-service indexes a reference to the same symbol. Quasar can then connect the library API to its consumer across repositories.

Language-specific indexers emit SCIP definitions, references, and relationships into Quasar’s shared semantic graph.

Relationships are especially useful when generated code separates the API a producer owns from the symbols consumers invoke. For example, Quasar can trace a Protobuf definition through its generated Java members to the repositories that use them, even when consumer code never names the .proto element.

SCIP records symbols and their references; it does not determine whether an API change violates an ecosystem’s compatibility rules. Today, Quasar compares indexed JVM and Protobuf API definitions and traces Protobuf changes through generated Java to find affected repositories. A separate JVM compatibility-impact path uses breaks identified by a producer-side tool to query affected repositories. Go, Python, JavaScript/TypeScript, and Rust support usage queries, but Quasar does not yet assess their breaking API changes.

Moving Risk Assessment Earlier

Today, Quasar surfaces API-change findings on pull requests, including observed consumer counts and confidence. Producers can use its other queries to inspect dependency versions and source locations, with library criticality as broader context. Together, those signals support a decision before merge.

We want to move that context earlier. An agent writing library code should recognize when it is changing a public symbol and consult Quasar before the change becomes a pull request. Quasar’s APIs and Model Context Protocol (MCP) integration provide an access path, but access alone does not create awareness. The coding workflow must also recognize public API edits so the agent knows when to query impact and when to involve the producer.

Today Quasar assesses risk on a pull request. The future workflow gives agents consumer-impact context while they write code, before the pull request is opened.

Earlier guidance will not replace pull-request analysis. The PR assessment will still verify the concrete diff and catch changes that were not recognized during coding. Coverage, freshness, ambiguity, unsupported platforms, and truncation must travel through both checks in machine-readable form. An agent should not turn “no observed usages in the available index” into “safe to remove.”

Today, agents can query Quasar through MCP when prompted. We are working toward making that context part of the coding workflow, then using identified call sites to prepare migration changes. Quasar supplies semantic evidence, an agent reduces migration toil, and the library producer remains responsible for API and release decisions.

What We Learned

Building this workflow led us to four practical lessons.

  • Separate compatibility from reach. A removed method can break the API contract even when Quasar finds no callers. A list of affected repositories and their library versions shows the migration work ahead. Producers need both signals to choose a release path.
  • Make the evidence inspectable. A repository count is more useful with sample call sites and a version breakdown. The result also needs to show which commits were indexed, how fresh the consumer indexes are, and whether evidence was truncated. Otherwise, “no usage found” can be mistaken for proof that nobody is affected.
  • Keep usage and compatibility separate across languages. SCIP lets Quasar find symbol references in several ecosystems. Deciding whether an API change is breaking requires compatibility rules or a trusted producer-side signal for that ecosystem.
  • Bring evidence to the producer while choices are open. Pull-request findings can prompt a producer to retain an API, publish a migration path, or coordinate consumers before merge. Moving the same evidence into the coding workflow could shape the edit earlier. After release, it still helps locate consumers that need to migrate.

Today, Quasar indexes JVM, Go, Python, JavaScript/TypeScript, and Rust code for cross-repository usage analysis. It compares JVM APIs and traces Protobuf changes through generated Java. Producers can review change findings through Quasar’s REST and GraphQL APIs or its MCP server, then investigate affected repositories and call sites. We are extending this foundation toward more ecosystem-specific compatibility checks, deeper code-review integration, and agent-assisted consumer migrations that keep release approval with the producer.

Quasar is internal to Netflix, but the pattern is portable: index code semantically, retain API definitions, compare them at the point of change, query affected consumers, and report the quality of the evidence. Library producers need more than a compatibility verdict. They need to know who may be affected and have enough time to act before release.

A huge thank you to the Java Platform team at Netflix. Their expertise, collaboration, and support made this work possible

Related Talks


Beyond API Compatibility: Building a Tool to Measure the Blast Radius of Library Changes was originally published in Netflix TechBlog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
emrox
6 days ago
reply
Hamburg, Germany
alvinashcraft
13 days ago
reply
Pennsylvania, USA
Share this story
Delete

Toxic experts

1 Share

Thursday 2 November 2017 — This is nine years old. Be careful.

I wrote Big-O: how code slows as data grows to explain Big-O notation. My goal was to explain it in broad strokes for people new to the idea. It grew out of thinking I’d been doing about beginners and experts. In the comments, there was an unexpected and unfortunate real-world lesson.

An anonymous coward named “pyon” said I should be ashamed. They pointed out a detail of algorithmic analysis that I had not mentioned. It’s a detail that I had never encountered before. I think it’s an interesting detail, but not one that needed to be included.

Pyon is an example of a toxic expert. People like this know a lot, but they use that knowledge to separate themselves from the unwashed masses of newbs. Rather than teach, they choose to sneer from their lofty perches, lamenting the state of the world around them, filled as it is with People Who Don’t Want To Learn.

The important skill pyon and other toxic experts are missing is how to connect with people. They could use their knowledge to teach, but it’s more important to them to separate themselves from others. Points of correctness are useless without points of connection.

Toxic experts care more about making distinctions between people to elevate themselves than they do about helping people. Beware: they are everywhere you look in the tech world. It’s easy to run into them when you are trying to learn. Ignore them. They don’t know you, and they don’t know what you can do.

Pyon is fixated on a particular detail of algorithmic analysis, and feels that it is essential to understanding Big-O. What I can tell you is that I am doing fine in my 30-year career, and I had never heard that particular detail. My Big-O piece wasn’t meant to be exhaustive. There are entire books written about algorithmic notation. I even wrote at the end, “There’s much more to algorithm analysis if you want to get into the true computer science aspects of it, but this is enough for working developers.”

But pyon can’t see the forest for the trees. Experts have spent a lot of time and energy learning what they know. They love their knowledge. They wouldn’t have been able to get where they are without a passion for the subject. But sometimes they have a hard time seeing how people can be successful without that well-loved knowledge. They’ve lost sight of what it means to be a beginner, and what beginners need to learn.

Toxic experts will latch onto a particular skill and decide that it is essential. For them, that skill is a marker dividing Those-Who-Know from Those-Who-Don’t. These shibboleths vary from expert to expert. In the current case, it’s a detail of algorithmic analysis. I’ve seen other toxic experts insist that it’s essential to know C, or assembly language, or recursion and pointers, and so on.

I’m not saying those aren’t good things to know. The more you know, the better. Every one of these topics will be useful. But they are not essential. You can do good work without them. You certainly don’t deserve to be spat upon.

The ultimate irony is that while pyon and other toxic experts are bemoaning the state of the industry because of missing knowledge, they are highlighting the main skill gap the tech industry needs to fix: empathy.

Read the whole story
emrox
6 days ago
reply
Hamburg, Germany
Share this story
Delete

16colo.rs - ANSI/ASCII archive

1 Share

2022-12-23T22:45:00.000+01:00

TAGS

Check out our tagging system, the best way to categorize content.

tags

SEARCH

Try our advanced text search and find things never found before!

search!

UPLOAD

Have a (new or old) pack to share? Upload and self-publish your pack within minutes.

upload

COLLABORATE

Collaborate with others on one our public PabloDraw or Moebius servers

draw

PASTE

Our very own textmode art and image sharing service for quick sharing through unique (private) URL's

share

SAUCE

A modern SAUCE editor to add meta-data to artwork

SAUCE

CHAT

Chat with ANSI/ASCII artists on IRC, Discord or Messenger.

chat!

About Sixteen Colors:

Sixteen Colors is an online archive for ANSI and ASCII artpacks. The artform was originally intended for display on computer textmode consoles. It gained popularity in the early nineties with the rise of dial-up Bulletin Board Systems (BBS).

At one point artists started to group together and release their work in collections released monthly, these collection are called artpacks. Rivalry resulted in fierce competition between these artgroups which only boosted activity. ACiD and iCE are examples of early prominent groups.

The rise of the Internet in the late nineties started the decline of BBS's and thus also the need and interest for ANSI/ASCII art. And although the need has almost vanished, still today artists are producing artpacks in collectives. Sixteen Colors aims to collect these artpacks as an archive in the public interest.

Want to know more? A good starting point is THE ART OF WAREZ is a short-film about the origins and history of the ANSI art scene.

Read the whole story
emrox
7 days ago
reply
Hamburg, Germany
Share this story
Delete
Next Page of Stories