Emma Irwin

@sunnydeveloper.mastodon.social.ap.brid.gy

Open Everything, Canada sunnydeveloper.com 🌉 bridged from ⁂ https://mastodon.social/@sunnydeveloper, follow @ap.brid.gy to interact

A year of AI disclosure in critical packages: https://nesbitt.io/2026/08/06/a-year-of-ai-disclosure-in-critical-packages.html

A year of AI disclosure in critical packages

Stephen O’Grady’s RedMonk analysis of who is writing open source code looked at commits to fifteen large projects during the first half of 2026 and counted two forms of declared AI involvement: a known autonomous agent as the commit author, or a known AI identity in a `Co-Authored-By` trailer. The result was under one percent, framed as a floor. I ran a wider version of the same measurement over the packages.ecosyste.ms critical set: 5,682 GitHub repositories behind the most-depended-on packages across sixteen registries, using the CHAOSS disclosure library to detect four kinds of explicit signal instead of two. Over the same six months the rate was 4.13%. Over the year ending 29 July 2026 it was 2.93% (17,279 of 589,798 non-merge commits), rising from 0.48% last August to 5.32% this July. These are counts of commits where someone left an explicit marker in git metadata. Undeclared use is not measured, and a commit is one unit regardless of whether it changed one line or ten thousand. ## Sample selection versus detector choice Running my scanner against RedMonk’s fifteen repositories with only their two signals found 94 matches in 23,346 first-half commits including merges, or 0.40%, against RedMonk’s “~24K commits” and a match count “in the dozens”. Excluding merges leaves 17,323 commits and the same 94 matches, or 0.54%; `espressif/esp-idf` and `openssl/openssl` supply 71 of them, matching RedMonk’s reported 73% concentration in two projects. sample and signals | commits | marked | share ---|---|---|--- RedMonk 15, agent author or known AI co-author | 17,323 | 94 | 0.54% RedMonk 15, all validated disclosure signals | 17,323 | 182 | 1.05% Critical GitHub set, agent author or known AI co-author | 308,354 | 11,002 | 3.57% Critical GitHub set, all validated disclosure signals | 308,354 | 12,720 | 4.13% Adding the two extra signal types moved the rate by about half a percentage point on either sample. Changing the sample moved it by three points. RedMonk’s fifteen were chosen by contributor-base size with, in O’Grady’s words, a deliberate bias towards C; the critical package set is whatever sits at the top of each registry’s dependency graph, which pulls in a lot of smaller, newer, company-run repositories. ## What I counted The critical snapshot contained 8,605 packages, with repository URLs and metadata pulled from the same package cache I built for Weekend at Bernie’s. Merging packages that share a repository, following renames, restricting to GitHub, and dropping malformed URLs left 5,707 candidates. 5,682 cloned successfully; the other 25 were deleted or private. 3,533 had at least one non-merge commit in the year ending 29 July 2026. Each repository was cloned bare with a tree filter and a shallow date boundary, streamed through the disclosure library, and deleted. The full pass transferred about 1 GB and the retained checkpoint is 16 MB of per-repository summaries and matched commit SHAs. Rename following checks GitHub’s stable repository ID as well as the redirect. The npm package `base` still lists `node-base/base` as its repository. GitHub reused the org name, so that path now redirects to the Base blockchain monorepo, which would have contributed 3,135 commits and 273 AI signals to a nine-year-old npm utility. The ID check excluded it. Every non-merge commit was checked for: * a known AI agent as author or committer * a known AI identity in `Co-Authored-By` * an `Assisted-By` trailer naming an AI tool or model * a tool-specific attribution format that disclosure supports Merges are excluded so projects that squash, rebase, or merge count on the same basis. Commits are bucketed by committer time, when the change landed on the current branch. Mentions of tool names in ordinary commit prose are ignored. `Assisted-By` values are validated because the trailer is also used for people: raw matches included `Assisted-By: Daniel Stenberg` and `Assisted-By: Automated Tooling, Human Reviewed.` The clones did not fetch `refs/notes/ai`, so declarations recorded as git notes are absent. ## Over the year The monthly rate passed 3% in February and 5% in March, then held between 4.58% and 5.32% through July. Counting repositories instead of commits, a signal appeared in 41 of the 1,734 repositories with commits in August 2025 (2.4%) and 276 of 1,793 in July 2026 (15.4%). Of the 17,279 findings, 4,625 carry only an autonomous-agent identity, 12,628 carry only a declared-assistance signal, and 26 carry both. Declared assistance went from 0.08% of commits in August to 4.92% in July. Agent authorship started at 0.40% and ended at 0.41%, peaking at 1.33% in between; 4,613 of those commits have GitHub Copilot’s agent as author, 38 have Devin’s, and Claude, Cursor, Codex, and Amazon Q account for 25 between them. Copilot agent commits reached 745 in March across 85 repositories and fell to 208 across 35 in July, with individual projects running the agent in short bursts: `pycqa/isort` had 49 in March and none after, `azure/azure-sdk-for-net` had 275 in February and 28 in March. The February and March step in the total is Claude Code `Co-Authored-By` trailers. Those went from 97 commits in December to 325, 753, and 2,037 over the following three months, and from 39 distinct repositories to 190. Cursor’s co-author trailers rose from 1 to 48 over the same months and Copilot’s from 1 to 2, so the step is specific to one tool rather than a general change in disclosure practice. Anthropic released Claude Opus 4.6 on 5 February and Sonnet 4.6 on 17 February; March is the first full month with both available. The findings carry 231 distinct declared tool strings across 17,392 occurrences. Grouping them by client family, and separately by model or provider where no client is named: declared as | occurrences | share ---|---|--- Claude Code | 9,974 | 57.35% GitHub Copilot | 4,857 | 27.93% Cursor | 773 | 4.44% Codex | 236 | 1.36% OpenCode | 69 | 0.40% Claude or Anthropic (model only) | 1,135 | 6.53% OpenAI or GPT (model only) | 118 | 0.68% Gemini or Google (model only) | 70 | 0.40% The raw declared strings are in the summary JSON; the grouping is mine and a value naming two clients counts in both. At the repository level, 687 of the 3,533 active repositories recorded at least one signal over the year, so the median active repository’s rate is zero. The ten repositories with the most findings account for 40.8% of the total and the top hundred for 84.9%. ## By ecosystem `go-git` shows what the extra detectors add in one repository: 269 of its 731 commits carry a validated signal, 12 of which match RedMonk’s narrow rules. The rest are `Assisted-By` trailers and tool attributions. Nine of the sixteen ecosystems had at least 30,000 commits in the window: package ecosystem | commits | validated share | repositories | with instructions ---|---|---|---|--- NuGet | 41,523 | 6.84% | 74 | 40.54% npm | 87,357 | 3.72% | 1,578 | 3.11% RubyGems | 40,889 | 3.59% | 670 | 6.12% Conda | 144,227 | 3.31% | 264 | 12.12% Go | 34,117 | 3.07% | 545 | 5.87% PyPI | 124,641 | 2.57% | 451 | 12.42% Cargo | 30,620 | 1.96% | 570 | 2.46% Packagist | 37,267 | 1.73% | 547 | 10.24% Maven | 100,539 | 1.60% | 273 | 16.12% The other seven, from CocoaPods at 13,581 commits down to Julia at 682, are in the summary JSON. Julia’s 51 findings in 682 commits give it the highest rate in the set at 7.47%, on the smallest sample. NuGet’s 6.84% is a Microsoft deployment. Repositories under `aspnet`, `azure`, `azuread`, `dotnet`, `microsoft`, and `nuget` supplied 2,716 of the 2,842 NuGet findings (95.6%), and 2,634 of those are autonomous-agent identities. Remove those owners and NuGet falls to 126 findings in 14,283 commits, or 0.88%, below Maven. I have only run that owner exclusion for NuGet; the per-repository CSV has what’s needed to do it for the others. ## Instruction files A separate pass over the same 5,682 default-branch heads checked for committed instructions to coding agents: `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, and the documented Copilot, Cursor, Cline, Windsurf, and Continue rule paths. 353 repositories (6.21%) have at least one, holding 1,091 files between them. A file’s presence records that someone set up guidance for an agent; it attributes nothing to any commit. instruction type | repositories | share of scanned repositories | files ---|---|---|--- `AGENTS.md` | 240 | 4.22% | 571 `CLAUDE.md` | 204 | 3.59% | 340 GitHub Copilot instructions | 84 | 1.48% | 154 Cursor rules | 11 | 0.19% | 14 `GEMINI.md` | 8 | 0.14% | 8 Cline rules | 1 | 0.02% | 4 Windsurf rules | 0 | 0% | 0 Continue rules | 0 | 0% | 0 Each repository is counted once, in the month its earliest surviving instruction file was added, so Cypress with 118 files counts the same as a project with one. Only files present on current heads are visible, so anything added and later deleted is absent from the timeline. 228 of the 353 repositories also have a disclosed commit in the year. 94 of those added their earliest instruction file before their first disclosed commit, 98 added it after, and 36 on the same day; the median gap is zero. The other 125 have an instruction file and no disclosed commit in the window. ## Data The scanner and report generator are at andrew/critical-ai-scan. The summary JSON has the overall, monthly, ecosystem, signal, tool, and leading-repository counts. The repository CSV has one row per successful scan with the exact default-branch head used, so individual cases can be checked without recloning. The instruction-file report lists every matched path with its category and the commit that added it.

nesbitt.io

Why npm Dependency Trees Are So Big https://nesbitt.io/2026/07/28/why-npm-dependency-trees-are-so-big.html

Why npm Dependency Trees Are So Big

Every major release of Rails sets off a wave of releases across the rest of the gem ecosystem. An application that tries to upgrade runs `bundle update rails` and Bundler refuses, because some gem in the tree only allows activesupport up to the previous major. The error names the gem, an issue gets filed on its tracker, and a maintainer who had nothing to do with the Rails release widens a version range and ships. Multiply that across every gem with a Rails constraint and the upgrade arrives as dozens of small releases from maintainers who mostly don’t know each other, each responding to errors their own users are hitting. Bundler refuses because it picks one version of every gem for the entire application. Every constraint in every gem is a claim on that shared choice, and finding a set of versions that satisfies all of them at once is NP-complete in the general case. Sometimes no set exists, and Bundler refuses to install, listing the gems whose constraints collided. That makes every constraint a cost that other people pay: a gem that pins a dependency tightly will block someone’s upgrade and get issues filed about it, so gem authors keep dependency lists short and ranges wide. All of it runs through the conflict error, which names the packages whose constraints disagree, so the problem reaches the maintainers who can fix it. That error has no equivalent in npm, which starts with the runtime. Ruby loads one copy of each gem per process, Python keys imported modules by name, and a JVM classpath resolves each class name once. You can get a second version into any of them if you work at it, but one version per program is the working assumption, so their package managers all resolve each library to a single version, and disagreements have to be settled somewhere. JavaScript module loading keys on file paths, not package names: two copies of the same package in different `node_modules` directories are just two different files, and Node’s module resolution loads whichever copy sits closest to the code requiring it. A resolver on top of that runtime could still pick one shared version per package and error when constraints can’t agree, but when two packages want different versions of a shared dependency, npm gives each its own copy. Ordinary dependency resolution has no conflict error in it at all: whatever constraints the packages in your tree declare, install succeeds. Which means a constraint in npm costs its author nothing: a library can pin an exact version of everything it uses and no downstream install will ever fail because of it. Your choice of range never collides with anyone else’s, so there is no occasion to talk to another maintainer about what you both should support, and no prompt to look at what your tree has accumulated. A dependency on a ten-line package is as free as any other too, which is the condition the micro-package habit needed. The costs show up elsewhere: npm’s dependency network was already the largest and fastest growing of the seven ecosystems Decan, Mens and Grosjean measured in 2017, and installing an average npm package means trusting 79 other packages and 39 maintainers. Every duplicated copy gets installed, bundled, and added to the surface you have to audit, so everyone pays a little of it and nothing like the Rails upgrade wave follows. Two copies of the same package do break things when the package holds module-level state: each copy gets its own singletons, and `instanceof` checks fail when an object from one copy reaches the other. The famous case is React, where two Reacts in one app break hooks, so a component library has to run against the application’s copy. `peerDependencies` exists for that case: a declaration that this package must share one version with the rest of the tree rather than getting its own. For years npm only warned when peer ranges couldn’t agree. When npm 7 started enforcing them, the resulting `ERESOLVE` errors were unpopular enough that npm added `--legacy-peer-deps`, a flag for turning the conflicts back off. Cargo runs both designs at once, and within a semver-compatible range it behaves like Bundler: every crate that depends on `bitflags` 1.x shares a single version. If the requirements can’t unify, say one crate pins `=1.2.3` while another needs a later patch, the resolver backtracks and errors rather than take two copies. Incompatible ranges get the npm treatment: 1.x and 2.x of the same crate coexist in one build with no error. And because a caret requirement on a 0.x crate only spans that minor, every 0.x minor is its own compatibility range, which puts a large share of the crate ecosystem on the npm side of the line. Rust’s coordination culture lives on the strict side, where foundational crates sit on the same major for years because a breaking release would split the single version every dependent has to share. serde has been on 1.x since 2017. When a crate that far down the stack does have to break compatibility, there’s the semver trick, where the outgoing major gets one final release that depends on the new major and re-exports its types, so the resolver treats the two as one while the migration rolls through, a contortion maintainers only accept under real pressure. On the loose side of the line, a demo web service at Tweede golf came to 141 crates, with base64, socket2, syn and time each present in two incompatible major versions, and Armin Ronacher counts a basic Rocket web project at 172 crates. Run `cargo tree --duplicates` in any sizeable project: every incompatible version it lists was resolved the way npm resolves everything. Dependency trees grow to the size their resolver permits: where every package must share one version, constraints put costs on other people, and those costs get maintainers talking to each other. npm settles every disagreement with another copy instead, and each copy makes the tree bigger.

nesbitt.io

This is so well done. What resonated msot for me was "we're losing trust in each other". I would add, and in organizations and companies that continue to ignore that fact. New leaders emerge in the ecosystem... https://blog.codeberg.org/protecting-our-floss-commons-from-llms.html #foss #opensource

Protecting our FLOSS commons from LLMs — Codeberg News

.codeberg-design ul { padding-left: revert !important; } In Brief: Two...

blog.codeberg.org

RE: https://mastodon.social/@andrewnez/116838649962117499 Andrew's post, is as usual - spot on, what needs to happen. Yet, I'm skeptical that beyond theater, companies will take ownership, and believe government beaurocracy will drown sincere attempts (with some exceptions of course). It's like […]

Original post on mastodon.social

mastodon.social

Andrew Nesbitt@andrewnez.mastodon.social.ap.brid.gy · last mo.

Taking Roads and Bridges literally - Reflections on UN Open Source Week 2026 https://nesbitt.io/2026/06/30/taking-roads-and-bridges-literally.html

Taking Roads and Bridges literally - Reflections on UN Open Source Week 2026 https://nesbitt.io/2026/06/30/taking-roads-and-bridges-literally.html

Taking Roads and Bridges literally

I spent last week at UN Open Source Week, where officials from a dozen governments stood up in turn and described open source as critical infrastructure. That framing has been the standard one since Nadia Eghbal’s _Roads and Bridges_ report for the Ford Foundation in 2016, and after ten years it has finally reached the audience it describes. Sitting in a UN conference room full of people whose job is public infrastructure, I started wondering what it would mean to stop treating the title as a metaphor and look at how bridges are actually maintained. _Roads and Bridges_ was pitched at the audience that was listening in 2016, technology companies and philanthropic foundations, neither of which maintains bridges: they drive over them for free, pay for them through tax, and leave the upkeep to the state. Spelling out the National Bridge Inspection Standards and the Highway Trust Fund to that room would have meant describing a government programme to a non-government audience, so the report stopped at the analogy and asked the people present to help. The decade since produced GitHub Sponsors, Open Collective, corporate OSPO budgets, and foundation grants: voluntary contributions from users of the infrastructure. The civil-engineering equivalent is Adopt-a-Highway, where a local business pays to pick litter from a stretch of road and gets its name on a sign. Adopt-a-Highway is a real programme that does some good, and no state relies on it to keep a bridge from falling into a river. ## The National Bridge Inspection Standards In the United States, every public-road bridge with a span longer than twenty feet is maintained under a federal regime that has been running since 1971, set up after the Silver Bridge collapse killed 46 people in 1967. The National Bridge Inspection Standards are codified at 23 CFR 650 Subpart C and they specify, among other things: * **Mandatory inspection.** Every bridge is inspected on a fixed cycle by a certified inspector, regardless of who owns it or whether the owner consents: 24 months is the default routine interval, with shorter cycles for higher-risk structures and longer risk-based intervals where the data supports it. * **Component condition ratings.** Each inspection produces a 0–9 rating for the deck, the superstructure, and the substructure. “Poor condition,” and the older “structurally deficient” label it replaced in 2018, are defined terms tied to those numbers rather than a judgement call. * **Load posting.** A bridge that has degraded below its design load is legally derated: a sign goes up restricting the weight of vehicles that may cross, so the bridge stays open at reduced capacity instead of being either ignored or closed. * **An inventory of record.** Every bridge has a structure number in the National Bridge Inventory, with an owner of record, and the whole dataset is public and queryable. * **Formula funding.** Federal fuel tax flows into the Highway Trust Fund and is allocated to states by formula. The money is recurring and predictable, not at the discretion of whoever happens to be feeling generous this quarter. * **Post-incident investigation.** After a major collapse the NTSB produces a formal accident report with findings of probable cause and recommendations: I-35W in Minneapolis, Fern Hollow in Pittsburgh. Recognising a structure as a public bridge switches all of that on automatically: the inventory entry, the inspection cycle, the condition ratings, the funding line, the closure authority. For an open source project, the same recognition currently switches on a speech. The government action that has followed regulates the _consumers_ of open source rather than the infrastructure. The EU Cyber Resilience Act, US Executive Order 14028, and the various SBOM mandates put obligations on companies that ship products containing open source, which in bridge terms is requiring haulage firms to certify which bridges their trucks crossed while not employing any bridge inspectors. ## Ownership Critical open source projects generally have identifiable owners (named maintainers, a foundation, a company), and the single-maintainer statistic is alarming because the number is one rather than because it is unknown. What they lack is a _state_ owner of record, but the bridge regime does not require one. The Ambassador Bridge between Detroit and Windsor carries around a quarter of road-borne US–Canada merchandise trade, is owned by a private company, and is still subject to federal inspection because the regime attaches to the function the structure performs, not to who holds the title. We know exactly who owns it, and we have left them to it. ## Null results The part of NBIS with the least open source equivalent is the most boring: an inspection that finds nothing wrong is filed with exactly the same formality as one that finds a crack in a girder. The inspector records a 9 for the deck and a 9 for the superstructure, dates and signs it, and it goes into the National Bridge Inventory next to all the others, with date of last inspection a queryable field in its own right. In open source, a review that finds nothing wrong is almost never published, because the only outputs with anywhere to go are findings: issues, pull requests, CVEs. The absence of a CVE against a project cannot distinguish “someone competent checked this and it was fine” from “nobody has looked.” Bug bounties, CVE credit, advisory acknowledgements, and conference talks all pay out on findings, and time spent confirming that a library is sound earns nothing and leaves no trace, which makes a clean review economically irrational to perform. A bridge inspector is paid the same for a 9 as for a 3, and that flat rate is what makes routine inspection a job rather than a hobby. A certified inspector’s “found sound” is a legal record because the state has defined who counts as an inspector and what an inspection consists of, whereas a drive-by GitHub comment saying “I looked at this and it seems fine” is correctly discounted to zero because there is no way to know who looked, how hard, or at what. Without a definition of what an inspection is and who is qualified to perform one, a clean report has no weight, so nobody bothers to write one. ## Procurement Germany’s Sovereign Tech Agency is the clearest example I know of a government treating open source as infrastructure it has some responsibility for, and the telling detail is the legal form. It was set up in 2022 as the Sovereign Tech _Fund_ and renamed in 2024 to the Sovereign Tech _Agency_ , a shift from a thing that disburses money to a thing that does work, and it pays maintainers under service contracts rather than grants, because German public-spending law makes it difficult for the government to give money away without defined consideration in return. That constraint is usually described as a bureaucratic obstacle, but it is doing the same job here that it does in civil engineering, where state departments of transportation procure inspection and repair from contractors under agreements specifying scope, deliverables, schedule, and acceptance criteria. A contract casts the maintainer as a professional the state is buying from because it needs the work done, which is a more accurate and more dignified relationship than the grantee-and-benefactor one that most open source funding has settled into. The procuring agency writes its own scope of work (which project, which components, what methodology, what gets published and by when), so a review delivered against that scope to a public agency carries weight because of who commissioned it and what they specified, not because of any certification the reviewer holds. Engineering standards have generally propagated this way, from large public buyers writing down what they will pay for and contractors converging on whatever wins the work, which also avoids the argument about who has the authority to set norms for open source: a scope of work claims no authority over the ecosystem, only over the purchase order. ## Scope of work A maintenance contract for an open source project has an obvious scope, and most of it is work maintainers already do unpaid: * Test coverage * Documentation * Performance benchmarks * Security review * Compatibility matrices against supported language and platform versions * Dependency updates Every item on that list produces an artifact whether or not it turns up a problem, since coverage is a percentage regardless, a compatibility matrix has a value in every cell, and a security review conducted on a given date against a stated methodology is a record even when the finding count is zero. Those artifacts map onto component condition ratings, a dated profile across several dimensions instead of a single health score, each of which can be re-measured on a cycle. A profile can also carry the equivalent of a load posting, where the report records that the project is sound within stated limits (“maintained for LTS platforms only,” “not hardened against untrusted input”) without having to choose between a clean bill and a warning label, which is a state open source currently has no way to express. Aggregate the reports across enough contracts and the result is an inventory with a structure number, an owner of record, a date of last inspection, and a condition by component. Documentation goes stale, dependencies become outdated, and CI matrices stop matching the platforms people use, on a shorter cycle than concrete weathers because the environment a library runs in is other software that is also changing. The right instrument is a maintenance contract on a term, not a one-off grant or a bounty, and “we funded that project in 2024” should sound as odd as “we inspected that bridge in 2024.” The boundary of that contract is condition assessment and upkeep rather than feature development, so the state is buying “keep it standing and report its condition,” which answers in advance the worry that government money would put government hands on a project’s roadmap. The institution the _Roads and Bridges_ metaphor pointed at already exists, with fifty years of regulation, case law, and procurement practice behind it, and none of it was built by asking trucking companies to sponsor their favourite overpass.

nesbitt.io