Panout review packOverviewFinal memoMVPLive outputsJudge roundsAppendicesDecisions

Source: docs/research/2026-09-03-defensibility/appendices/G-public-repo-rework-map.md

Does the rework map print the same story on strangers' repos?

Measured 2026-09-03 on 11 public GitHub repositories. Read-only: every repo was cloned into /tmp/panout-ideas/public-repos/, nothing was pushed, no issue or PR was opened, no maintainer was contacted.

Question: on repos the founder has never touched, is the share of commits reworked within 30 days higher for agent-authored commits than for human-authored ones, and is the gap positive, negative, or noise?

Scripts: classify.py (discovery/attribution), measure_pub.py (rework measurement), report.py (tables). Raw per-commit output in raw/*.json.


1. Method

Ported from /tmp/panout-ideas/backtest/measure.py; the R0 definition is byte-for-byte the same test, so public numbers are directly comparable to the founder-repo numbers in /tmp/panout-ideas/backtest/REPORT.md.

Clones. git clone --shallow-since=2026-02-01 --single-branch (full blobs, ~214 days of history โ€” deeper than the 180-day window so that every measured commit has its parent present). Discovery used cheap treeless clones (--filter=tree:0 --no-checkout).

Agent classification (trailer/marker). A commit is agent-authored if subject or body matches Co-authored-by: (Claude|Codex|Cursor|Copilot|Devin), a Co-authored-by: line whose address contains claude|copilot|codex|cursoragent|devin-ai-integration, Generated with [Claude Code], or ๐Ÿค– Generated with; or if the git author is the Copilot bot (198982749+Copilot@users.noreply.github.com) or literally named Copilot/Claude/Codex. Everything else is human. This is the same trailer-only rule as the founder backtest.

Population. Default branch (HEAD), commits authored in the last 180 days (since 2026-03-07), merge commits excluded from measurement.

Sample. Commits between 180 and 30 days old, so every commit has a complete 30-day forward window. Stratified: up to 100 most recent agent commits and 100 most recent human commits per repo (the founder backtest used a single un-stratified cap of 400; stratifying guarantees both classes are measurable in repos where one class is rare). Reduced from 300 to 100-per-class to hold total runtime under the budget โ€” this is the one deliberate deviation from the brief, and Section 6 shows what it costs.

Rework test. For commit C: added line ranges from git diff C^ C --unified=0, skipping lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, Cargo.lock, poetry.lock, uv.lock, go.sum, composer.lock, Gemfile.lock), minified bundles, binaries, images, fonts, snapshots, and .sha256; top 20 files by added lines. E = newest descendant of C on the default branch within 30 days. Then:

Reverse blame attributes each line to the last commit in which it survived; any attribution other than E means the line was changed or deleted inside the window. C counts as reworked if any added line fails to survive to E.

Time to first rework. Hours from C to the earliest last-surviving commit. As in the founder backtest this is a lower bound (the edit lands at that commit's child); 0 h means "the next commit touched it".

Path class. Each commit is assigned the class of the bucket holding most of its added lines, using path rules evaluated in order: ci (.github/workflows, .circleci, .gitlab-ci, azure-pipelines, Jenkinsfile, โ€ฆ) โ†’ tests (tests/, __tests__/, spec/, e2e/, *_test.go, *.test.ts, test_*.py, *Tests.cs) โ†’ docs (.md/.mdx/.rst/.adoc, docs/, website/) โ†’ src (known code extensions) โ†’ config (.json/.yaml/.toml/.csproj/Dockerfile/โ€ฆ) โ†’ other.


2. Selection

Discovery started from gh searches (gh search prs 'Co-authored-by: Claude' --merged, gh search prs --author app/copilot-swe-agent --merged, gh search prs 'head:codex/' --merged, and gh api search/commits with the cloak-preview header). Those searches are not usable for this selection: sorted by recency they return an almost pure long tail of one-person hobby repos (the top hit across 100 merged Claude-trailer PRs had 15 PRs; nothing in the first 40 rows had the commit volume required), and the GitHub search API secondary rate limit repeatedly blocked pagination. So discovery was flipped: 48 well-known, high-traffic public repos were treeless-cloned and their agent share was computed from the commit history itself, which is both cheaper and the same measurement used downstream.

Candidates with โ‰ฅ300 commits in the last 180 days (48 probed, 44 qualified). Agent share is by the trailer rule above:

RepoCommits 180dAgentShareRepoCommits 180dAgentShare
microsoft/aspire1911131768.9%supabase/supabase334835910.7%
github/spec-kit133170052.6%Skyvern-AI/skyvern25462379.3%
n8n-io/n8n5487221040.3%block/goose17921508.4%
mastra-ai/mastra5526179532.5%cloudflare/workers-sdk1335977.3%
Azure/azure-sdk-tools121438431.6%All-Hands-AI/OpenHands19271367.1%
elizaOS/eliza20648638830.9%langflow-ai/langflow16971106.5%
microsoft/typescript-go84723227.4%openai/codex58823075.2%
gradio-app/gradio42510324.2%microsoft/playwright1498654.3%
temporalio/temporal122520716.9%cline/cline2216863.9%
microsoft/vscode-copilot-chat5268616.3%open-webui/open-webui27161033.8%
pydantic/pydantic-ai112117115.3%danny-avila/LibreChat1530573.7%
denoland/deno220233115.0%apache/airflow43911353.1%
PostHog/posthog22010330615.0%coder/coder35311042.9%
BerriAI/litellm11801170814.5%pola-rs/polars1070312.9%
grafana/grafana619286213.9%browser-use/browser-use1430402.8%
crewAIInc/crewAI78010613.6%zed-industries/zed3969671.7%
12 more (ollama, sst/opencode, immich, astro, dagger, MoviePilot, spring-ai, google-cloud-go, genai-toolbox, openai-agents-python, charmbracelet/crush, QuantumNous/new-api)560โ€“56590โ€“290.0โ€“1.7%

Selected 11 (bold above; the brief asked for 10, temporalio/temporal was added for a second Go/server-side data point). Selection rules applied: โ‰ฅ300 commits/180d, both classes present, prefer 20โ€“80% agent share, real software, language spread.

#RepoPrimary languageCommits 180dAgent shareDominant agent markerMerge style
1microsoft/aspireC#192269.0%Co-authored-by: Copilotsquash (25 merge commits)
2github/spec-kitPython + templates133152.6%Co-authored-by: Copilotsquash
3n8n-io/n8nTypeScript548640.3%Co-authored-by: Claudesquash
4mastra-ai/mastraTypeScript553032.5%Claude / Codex mixsquash
5Azure/azure-sdk-toolsC# + Python + TS121131.5%Copilot bot authorsquash (0 merge commits)
6elizaOS/elizaTypeScript2064131.0%Generated with [Claude Code]merge + squash
7microsoft/typescript-goGo84727.4%Copilot / Claudesquash
8gradio-app/gradioPython + Svelte42524.2%Co-authored-by: Claudesquash
9temporalio/temporalGo122416.8%Claude / Copilotsquash
10microsoft/vscode-copilot-chatTypeScript52716.3%Co-authored-by: Copilotsquash
11denoland/denoRust + JS220115.0%Co-authored-by: Claudesquash

Only 6 of 11 land inside the 20โ€“80% target band. That band is scarce in public code: of 44 qualifying repos, 8 exceeded 20% and 26 were below 8%. The remaining slots were filled from the 13โ€“17% tier, choosing for language spread (Go, Rust) rather than share.

Excluded despite qualifying: PostHog/posthog, BerriAI/litellm, grafana/grafana (all โ‰ฅ6k commits in 180 days โ€” clone and measurement cost outside the runtime budget), and repos below ~8% agent share where the agent cell would be too thin to read.


3. Squash merges and PR-level attribution

Nine of the eleven repos squash-merge; Azure/azure-sdk-tools has zero merge commits in 180 days and microsoft/aspire has 25 in 1,922. Every agent contribution therefore lands as one linear commit on the default branch, and the co-author trailer survives into that squash commit โ€” so trailer classification works without PR lookups.

For the three Copilot-agent repos the brief asked for PR-level attribution, so it was done: gh search prs --repo <R> --author app/copilot-swe-agent --merged gave the set of PR numbers opened by the Copilot coding agent (805 / 314 / 71), matched to commits by the trailing (#NNNN) in the squash subject. Result on the measured samples:

Repotrailer=agent AND PR opened by Copilottrailer=agent, PR opened by a humantrailer=human, PR by Copilotboth human
microsoft/aspire1384097
Azure/azure-sdk-tools2536060
microsoft/vscode-copilot-chat580095

The trailer rule has zero false negatives against PR-level authorship, but it is far broader than it: 84โ€“94% of trailer-flagged commits come from PRs a human opened, that merely carry a Co-authored-by: Copilot trailer. The trailer measures "an agent was in the room", not "an agent shipped this". Section 6 shows the two definitions disagree on sign.


4. Results

4.1 Rework within 30 days, agent vs human

RepoCommits 180dAgent sharen agentn humanR0 agentR0 humanR0 gapR1 agentR1 humanR1 gap95% CI (R1 gap)
microsoft/aspire192269.0%979753.6%48.5%+5.247.4%42.3%+5.2โˆ’8.8 โ€ฆ +19.1
github/spec-kit133152.6%1009638.0%56.2%โˆ’18.238.0%56.2%โˆ’18.2โˆ’32.0 โ€ฆ โˆ’4.5
n8n-io/n8n548640.3%999955.6%57.6%โˆ’2.054.5%56.6%โˆ’2.0โˆ’15.9 โ€ฆ +11.8
mastra-ai/mastra553032.5%999998.0%89.9%+8.198.0%89.9%+8.1+1.5 โ€ฆ +14.6
Azure/azure-sdk-tools121131.5%626038.7%41.7%โˆ’3.035.5%38.3%โˆ’2.8โˆ’20.0 โ€ฆ +14.3
elizaOS/eliza2064131.0%879882.8%86.7%โˆ’4.081.6%86.7%โˆ’5.1โˆ’15.7 โ€ฆ +5.4
microsoft/typescript-go84727.4%1009923.0%24.2%โˆ’1.221.0%22.2%โˆ’1.2โˆ’12.7 โ€ฆ +10.2
gradio-app/gradio42524.2%769996.1%86.9%+9.296.1%86.9%+9.2+1.2 โ€ฆ +17.1
microsoft/vscode-copilot-chat52716.3%869555.8%30.5%+25.354.7%29.5%+25.2+11.2 โ€ฆ +39.1
denoland/deno220115.0%1009855.0%14.3%+40.753.0%10.2%+42.8+31.3 โ€ฆ +54.3
temporalio/temporal122416.8%1009631.0%49.0%โˆ’18.028.0%47.9%โˆ’19.9โˆ’33.2 โ€ฆ โˆ’6.6
pooled1006103656.5%53.8%+2.754.7%52.1%+2.5โˆ’1.8 โ€ฆ +6.9

CI is a normal-approximation interval on the difference of two proportions; it accounts for sampling only, not for the confounds in Section 6.

4.2 Direction of the gap

R0R1
Repos with gap > +5 pts (agent reworked more)55
Repos with gap < โˆ’5 pts (agent reworked less)23
Repos within ยฑ5 pts (noise)43

R1 gaps, sorted: deno +42.8, vscode-copilot-chat +25.2, gradio +9.2, mastra +8.1, aspire +5.2, typescript-go โˆ’1.2, n8n โˆ’2.0, azure-sdk-tools โˆ’2.8, eliza โˆ’5.1, spec-kit โˆ’18.2, temporal โˆ’19.9.

Pooled gap is +2.5 points with a CI spanning zero. -w -M -C (R1) barely moves anything: the largest R0โ†’R1 change is 2.1 points (deno). Whitespace and rename insensitivity is not what drives these numbers.

For contrast, the founder-repo backtest reported pooled agent 64.6% vs human 51.4% (+13.2), and +21.7 on the founder-only slice. The public pooled gap is one fifth of that and not distinguishable from zero.

4.3 Median hours to first rework (R1, lower bound)

Repoagent reworked nagent median hhuman reworked nhuman median h
microsoft/aspire46213.141170.5
github/spec-kit38135.45438.2
n8n-io/n8n5468.75698.1
mastra-ai/mastra9714.68994.2
Azure/azure-sdk-tools22124.82397.8
elizaOS/eliza7119.8858.8
microsoft/typescript-go21143.922184.2
gradio-app/gradio7347.88621.3
microsoft/vscode-copilot-chat4752.62816.4
denoland/deno53228.110193.3
temporalio/temporal28133.64691.6
pooled55076.554067.7

Agent rework arrives 9 hours later than human rework at the median (76.5 h vs 67.7 h), and the per-repo sign splits 5 slower / 6 faster. No usable signal. The founder backtest saw a much larger separation (17.1 h agent vs 1.2 h human), which is a property of a single-committer repo where the author's own next commit lands minutes later.


5. What a maintainer would see: top task classes

Top two path classes by agent rework rate per repo (R1, classes with nโ‰ฅ5 agent commits):

Repoclass 1class 2rest
microsoft/aspiretests 51% (n=59)other 50% (n=6)src 47% (n=15); ci 33% (n=9)
github/spec-kitconfig 85% (n=20)tests 25% (n=68)docs 22% (n=9)
n8n-io/n8ntests 56% (n=63)src 55% (n=31)โ€”
mastra-ai/mastradocs 100% (n=15)tests 100% (n=54)src 96% (n=27)
Azure/azure-sdk-toolsother 57% (n=7)docs 50% (n=6)src 42% (n=12); tests 29% (n=21); config 27% (n=15)
elizaOS/elizaconfig 84% (n=19)src 80% (n=30)tests 79% (n=33)
microsoft/typescript-gosrc 24% (n=33)tests 22% (n=36)other 15% (n=26)
gradio-app/gradiosrc 100% (n=44)tests 100% (n=18)docs 83% (n=6); ci 60% (n=5)
microsoft/vscode-copilot-chattests 67% (n=24)src 53% (n=53)config 43% (n=7)
denoland/denosrc 60% (n=70)tests 36% (n=28)โ€”
temporalio/temporaltests 28% (n=71)src 26% (n=27)โ€”

Pooled, by class:

classagent nagent reworkhuman nhuman reworkgap
src34560.9%33041.8%+19.1
tests47550.5%43857.5%โˆ’7.0
docs5156.9%12571.2%โˆ’14.3
config7065.7%8046.2%+19.5
ci2347.8%3256.2%โˆ’8.4
other4233.3%3119.4%+14.0

Read as a maintainer would: in 9 of 11 repos the two named classes are simply tests and src, which are also the two largest classes by volume. In 4 repos the top class is a class with fewer than 25 agent commits (other n=6/7, docs n=6/15, config n=20). In mastra and gradio the top classes are pinned at 96โ€“100% for both agent and human commits โ€” the ranking there carries no information because nothing survives 30 days untouched in those monorepos.

The one pooled cut that looks non-obvious is src (+19.1) and config (+19.5) positive while tests (โˆ’7.0) and docs (โˆ’14.3) are negative. That is the most defensible finding in this report, but it is pooled across repos whose individual gaps run from โˆ’20 to +43, so it is an artifact of which repos contribute volume to which class as much as it is a property of agents.


6. Sensitivity: the gap does not survive two obvious controls

6.1 Calendar-period matching

Sampling the 100 most recent commits of each class independently means the two samples cover different calendar periods whenever one class is rarer. The gap is largest exactly where the offset is largest:

Repoagent sample median datehuman sample median dateoffsetR1 gap
denoland/deno2026-04-242026-07-2693 d+42.8
temporalio/temporal2026-06-242026-07-2430 dโˆ’19.9
microsoft/typescript-go2026-06-102026-07-1535 dโˆ’1.2
gradio-app/gradio2026-06-092026-07-0425 d+9.2
microsoft/aspire2026-07-092026-06-2613 d+5.2
others (n8n, mastra, eliza, spec-kit, azure-sdk-tools, vscode-copilot-chat)โ‰ค9 dโˆ’18.2 โ€ฆ +25.2

Recomputing the gap within calendar-month strata (strata needing โ‰ฅ10 agent and โ‰ฅ10 human commits, weighted by stratum size):

Reporaw R1 gapmonth-stratified gap
microsoft/aspire+5.2โˆ’2.1
github/spec-kitโˆ’18.2โˆ’18.7
n8n-io/n8nโˆ’2.0โˆ’2.0
mastra-ai/mastra+8.1+9.2
Azure/azure-sdk-toolsโˆ’2.8โˆ’2.9
elizaOS/elizaโˆ’5.1โˆ’4.5
microsoft/typescript-goโˆ’1.2โˆ’4.4
gradio-app/gradio+9.2+11.0
microsoft/vscode-copilot-chat+25.2+11.2
denoland/deno+42.8+19.7
temporalio/temporalโˆ’19.9โˆ’27.2
pooled (size-weighted)+2.5โˆ’1.3

Time-matching cuts deno's gap by more than half and flips the pooled gap from +2.5 to โˆ’1.3.

6.2 Trailer attribution vs PR-level attribution

Using the strict definition (agent = PR opened by app/copilot-swe-agent) instead of the trailer, on the same measured commits:

Repostrict-agent nstrict-agent reworkeverything else nreworkgaptrailer gap
microsoft/aspire137.7%18147.5%โˆ’39.8+5.2
Azure/azure-sdk-tools2520.0%9741.2%โˆ’21.2โˆ’2.8
microsoft/vscode-copilot-chat520.0%17642.0%โˆ’22.0+25.2

The sign flips in all three repos. Commits from PRs the coding agent itself opened are reworked less than everything else; commits merely carrying an agent co-author trailer are reworked more. Cell counts are small (13/25/5), so this is not a claim that agent PRs are better โ€” it is a demonstration that the two attribution rules produce opposite answers on identical commits.

6.3 Within-author

Authors with โ‰ฅ10 agent-trailer and โ‰ฅ10 human commits in the same sample (holds the person fixed):

Repoauthoragent nagent reworkhuman nhuman reworkgap
elizaOS/elizashawgotbags@โ€ฆ3976.9%4292.9%โˆ’15.9
elizaOS/elizashawmakesmagic@โ€ฆ2792.6%2892.9%โˆ’0.3
gradio-app/gradioabubakar@huggingface.co4295.2%1573.3%+21.9
microsoft/vscode-copilot-chatdon.jayamanne@โ€ฆ2774.1%1258.3%+15.7
denoland/denobiwanczuk@gmail.com4763.8%2910.3%+53.5
pooled18279.7%12668.3%+11.4

Only five author-repo cells qualify, and they disagree in sign. denoland/deno's entire +42.8 repo-level gap is one contributor: 47 of the 100 sampled agent commits and 29 of the 100 human commits are the same person, whose agent-trailer commits are reworked 63.8% vs 10.3% for their non-trailer commits. Whether that is "the agent produced worse code" or "this person uses the agent on the churny parts (perf work on ext/node stream paths) and hand-writes the stable parts" cannot be separated from git.


7. Sampling detail

Repoeligible window (30โ€“180 d, non-merge)agent in windowsampled agentsampled humanmeasured (both)
microsoft/aspire15951073100100194
github/spec-kit1108555100100196
n8n-io/n8n43041610100100198
mastra-ai/mastra41371308100100198
Azure/azure-sdk-tools1076353100100122
elizaOS/eliza99225181100100185
microsoft/typescript-go777212100100199
gradio-app/gradio3457777100175
microsoft/vscode-copilot-chat5278686100181
denoland/deno2060331100100198
temporalio/temporal1019161100100196

"Measured" is below "sampled" where a commit had no descendant within 30 days or touched only skipped files (lockfiles, binaries, minified assets). Azure/azure-sdk-tools loses 78 of 200, mostly dependabot lockfile-only commits.


8. Caveats

  1. Attribution is by commit trailer. On the three Copilot repos where it could be checked, the trailer rule flags 5โ€“7ร— more commits than PR-level agent authorship, and the two rules give opposite signs (6.2). Nothing in git separates "the agent wrote this" from "the agent was open in another pane".
  2. Squash merges collapse the unit of work. Nine of eleven repos squash. A squash commit is a whole reviewed PR, so "one commit" means very different amounts of work in deno (one PR โ‰ˆ one fix) than in eliza (thousands of small direct commits). Rework rates are not comparable across repos, only within.
  3. Reverse blame is line identity, not semantics. A reformat, an unmatched rename, or a neighbouring edit that shifts a line counts as rework; a semantically wrong line nobody touched for 30 days counts as survived. R1 (-w -M -C) was meant to test how much of the signal that explains: it moves nothing (โ‰ค2.1 pts anywhere), which means the proxy's noise is not mostly whitespace and renames โ€” it is genuine co-location of edits.
  4. Ceiling saturation. In mastra (98%/90%) and gradio (96%/87%) almost every commit is "reworked" within 30 days. In high-churn monorepos the metric has almost no dynamic range, and the per-class ranking in Section 5 is unreadable there.
  5. Sample is 100 per class, not 300. Reduced to hold runtime under the budget, as the brief permitted. Per-repo CIs are consequently ยฑ13 points wide on average; only 4 of 11 repos have a CI excluding zero, and month-stratification (6.1) drops several repos to a single usable stratum.
  6. The 20โ€“80% agent-share band is rare in public code. Only 8 of 44 qualifying repos reached 20%. Five of the eleven selected sit at 15โ€“17%, so their agent samples reach further back in time than their human samples โ€” the exact confound measured in 6.1.
  7. Shallow clones. --shallow-since=2026-02-01 on the default branch only. Commits reachable only from other branches, and the pre-February history, are absent. This affects nothing in the 30โ€“180-day window but means -C (copy detection) cannot see pre-February sources.
  8. Bot traffic is in the human class. dependabot, renovate and repo-maintenance bots are not agent-flagged and land in "human". Azure/azure-sdk-tools (240 dependabot commits in 180 days) and github/spec-kit (147 github-actions commits) are the most affected; both show negative or near-zero gaps.
  9. Single 30-day window, single snapshot. Measured once, on 2026-09-03. No repeat run, so run-to-run stability of these numbers is unknown.
  10. Path classes are heuristic. spec-kit's templates and eliza's generated files land in config/other in ways a maintainer might not agree with.

9. What the numbers say