evolution-scan
Skill3 starsChanged 31 days agoMITView on GitHub
Explains how a codebase evolved from its git history: eras and what each was about, growth and origin of the code, the shift of activity between areas, who arrived and left, parts born, rewritten or abandoned, the work mix now, and the trajectory. Use for a project's history or timeline, momentum, stagnation, contributor turnover, "what changed last year", or the story behind Sokrates' churn and age numbers. Needs git-history.txt.
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 35
Write findings, validate, render the explorer, and report per the core workflow.
- Distinctive: line 83
Use the core scale, driven by *what the trend costs if nobody reacts*:
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Evolution scan
Sokrates measures churn, file age, and contributor counts as of today. This scanner reads the history behind those numbers and tells it as a story: what the project was at each stage, which decisions the commits reveal (rewrites, migrations, abandoned directions), how the team changed, and which way the code is heading. A tech lead should finish the report knowing what "this codebase" meant a year ago, what it means now, and what it is turning into.
First read sokrates-scan-core/SKILL.md (sibling skill) — output format, evidence rules, validate/render scripts, _sokrates data layout. This file adds only what is specific to evolution.
Workflow
- Orient per the core skill (config.json, unzip
data.zipto a scratch directory). Read prior findings if present:architecture-scan(components, migrations in progress) andrisk-synthesis-scan(hotspots, knowledge risk) name the areas whose history matters most;tech-stack-scantells you what the technologies in old commit messages are. Run the timeline script — never derive periods, shares, or turnover by hand; the script keeps them deterministic and re-runnable:
python3 <this-skill-path>/scripts/evolution_timeline.py \ --src-root <src-root> --data <scratch>/sokrates-data -o <scratch>/evolution.jsonIt reads Sokrates'
git-history.txt+git-commits.txtat the source root (falling back tozips/git-history.zipinsidedata.zip) and returns:stats(span, commits, authors, busiest period, overall and recent commit themes, 90-day activity trend),periods(per month or quarter: commits, authors, new authors, new files, files since gone, lines added/removed, top areas with shares, theme mix, and the notable commits — the largest by lines changed, with messages and sample paths),focus_shift(share of commits per period for the top areas — the table that shows the center of gravity moving),areas(per path-prefix area: commits all-time / 365d / 90d, authors, first and last commit, current size, and flagsemerging,accelerating,cooling,dormant,no-history),people(top contributors with tenure, 90-day vs. previous-90-day commits and status active/fading/gone; arrivals in the last year; departures; fading major contributors whose 90-day output halved; rising ones), andlifecycle(files seen vs. current, deletions vs. estimated moves/renames, deletions by area, file-age quantiles, oldest surviving, most committed, most rewritten files). Per period you also get author concentration (top3_authors_share_pct), the e-mail-domain mix (in-house vs. community), the count and top three of newly arrived authors, and two notable-commit rankings — by meaningful lines changed (lockfiles, snapshots, fixtures and generated files excluded) and by files touched.--depthsets what an "area" is (2 =codex-rs/core);--periodforces month or quarter (auto: months under two years of history).No-history degradation: if the script exits 3, no git history export exists. Write a single
infofinding intrajectoryexplaining that evolution cannot be measured, setstats.history_data: "absent", and stop — never reconstruct history from file dates or guesswork.Trust but verify the digest — and know its blind spots:
- Themes come from commit-message keywords.
stats.theme_other_pcttells you how much the vocabulary missed; whentheme_trend_reliableis false (over 30 % unclassified) do not narrate the theme trend as fact — say the messages are unprefixed imperatives and judge the work mix from the notable commits instead. - Area flags are threshold heuristics.
not-inventoriedmeans the area is still committed to but absent from Sokrates' file inventory (usually ignored byconfig.json) — never report it as shrunk or gone.single-ownerpairs withemerging/acceleratingto answer the medium-severity calibration below;areas[].top_author_share_pctis there for every area. - Percentages in
focus_shiftandtop_areasare "share of the period's commits that touch this area"; a commit touching three areas counts in all three, so shares do not sum to 100. Say "touched by 45 % of commits", never "45 % of the work". - Files gone are split into
files_deletedandfiles_moved_estimate(same basename reappearing in the same commit); wholesale renames still inflate deletion counts for the old path, so confirm a "deleted" claim by checking the new location. - Identities are merged when several e-mails share one author name (
stats.identity_mergeslists them) — mention a merge when it matters ("the maintainer under two addresses"), and treat remaining same-person-different-name cases with suspicion when two "contributors" hand over seamlessly. people.departuresusesgone_threshold_days— the larger of 180 days and a quarter of the history; on a young projectfadingis the more telling list.drive_by_authors_single_commitqualifies raw author counts — "581 authors" with 329 one-commit authors is a different team than it sounds.- Periods flagged
low_sample(under 10 commits) have meaningless shares and theme mixes — describe them as quiet, not by their percentages. - Without
--data,files_deleted,files_moved_estimateandcurrent_filesare null anddormant/not-inventoriednever fire; say so in the summary if you had to run without it. The script narrows the reading; the reading is the finding.
- Themes come from commit-message keywords.
- Read the history behind the numbers. For each era you intend to describe, skim that period's notable commits and open
git-commits.txtaround them (the file is in the source root — it is citable evidence; it carries no dates, so take dates from the digest's notable commits or grep the sha ingit-history.txt). Draw era boundaries at the structural events the notable commits reveal — an import or deletion of a whole implementation, the birth of the component that becomes the top area, a rewrite landing — not at calendar quarters; when releases or tags exist inCHANGELOG.md/release notes use them, but most exports have none, so a one-line pointer changelog is normal and the commit messages are the primary source. For each area you call emerging, dormant, or rewritten, open the current code (or confirm its absence) and find the commit messages that created, replaced, or abandoned it. For people findings, look at what the arriving or departing contributors actually worked on (the script'stop_areasper author) and whether their areas have other owners now.CHANGELOG.md, release notes, ADRs, anddocs/are first-class sources for why things changed — cite them when they exist. Write findings, validate, render the explorer, and report per the core workflow. Scanner id:
evolution-scan, version1.0. Forstats, use the script'sstatsobject (it already carrieshistory_data: "present") plus atimeline_paramskey recordingdepth,period, andtop.Stable ids. Era slugs are topical, never positional or dated:
eras/typescript-cli,eras/rust-workspace,eras/app-server-platform— a re-run a quarter later keeps the same eras (their end dates may move) and adds a new one, which the differ then reports as new. The same rule applies to rewrites (lifecycle/tui-to-tui2) and people (people/core-ownership-shift). See the fixed-slug table under Stable ids below — most of this scanner's findings answer a recurring question and take a fixed slug; only eras and named migrations get a free, topical one.Evidence for pure-history facts. Growth curves, team-size series, velocity comparisons and share tables have no single citable line. Such findings may carry an empty
evidencearray withconfidence: likelywhen they are wholly grounded in the digest and cite it viasokrates_refs(metric:commits,metric:contributors,metric:churn,metric:file_age); do not pad them with the first and last line ofgit-commits.txt. Whenever a claim can be pinned to a line — the commit that started a growth burst, the message that announces a rewrite — cite that line and keepcertain.
Group taxonomy
| group | contents |
eras | The timeline as chapters: 3–6 eras with their date range, what the project was in that era (purpose, shape, main technologies), what the big commits were about, and what closed the era. A long quiet stretch is an era too — describe what maintenance it did and did not do. One finding per era, ordered oldest first, plus at most one finding for a singular turning point that deserves its own entry (a rewrite, a repository merge, a change of ownership); a turning point that opens an era is told inside that era's finding, not separately |
growth | How the codebase got its size: growth curve in commits/files/lines per period, where the bulk came from (organic feature work, bulk imports, generated code, vendored trees, test fixtures), and how much of what was ever written is still there (files seen vs. current, most rewritten files) |
focus-shift | Where the center of activity moved: which areas dominated each period and which dominate now, areas that are emerging or accelerating (with what they are), areas cooling or dormant (and whether dormant means finished or neglected) |
people | The team over time: size per period, concentration, arrivals and what they brought, departures and what they left behind (single-owner areas that lost their owner), whether ownership of the core has moved between people |
lifecycle | Births, rewrites, deaths: modules that were created and later replaced (tui → tui2 → …), migrations completed or stalled mid-way (both old and new paths still alive), directories deleted wholesale, the oldest surviving code and whether it still matters |
trajectory | The synthesis: velocity trend (accelerating / steady / decelerating, with the 90-day comparison), what kind of work dominates now versus a year ago (feature vs. fix vs. refactor mix), what the last quarter says about direction, and the risks the trajectory implies — plus the no-history statement when applicable |
Tie-breakers: a rewrite is told once, in lifecycle (the mechanics: what replaced what, when, is the old path gone), and referenced from the era it closed or opened; focus-shift describes activity distribution, not module births; people findings are about humans, ownership consequences go in people even when the area is also discussed elsewhere; trajectory never introduces a new fact, it interprets facts established in the other groups.
Stable ids
Every re-run of this scanner on the same project must produce the same ids for the same subjects — sibling scanners reference them (finding:evolution-scan/...), and a renamed slug silently breaks those references. The first re-run of this scanner persisted 1 of 19 ids because every slug was free-text; the rule below is the fix.
Most findings answer a recurring question and take a fixed slug regardless of the answer's wording. Only two kinds get a free slug: an era (named for what the project was then) and a named migration (lifecycle/<old>-to-<new>, from the code's own names).
| group | fixed slugs |
eras | free topical slug per era (typescript-cli, maintenance-plateau), plus turning-point-<topic> for a singular turning point that earns its own finding |
growth | growth-curve (the shape over time), code-origins (where the bulk came from — imports, generated, vendored), survival (how much of what was written still exists, most-rewritten files) |
focus-shift | center-of-gravity (which area dominates now and which used to), <area> — the bare area name the script uses, one finding per area that deserves a verdict (focus-shift/codeexplorer), with the verdict (emerging, cooling, dormant, accelerating) in the title and description, never in the slug: an area whose verdict moves from cooling to dormant is the same subject and must keep its id so the differ reports a change rather than a deletion plus an addition |
people | team-shape (size and concentration over time), ownership (who owns the core and whether it moved), arrivals, departures, rising (a dormant contributor returning at volume is rising, not arrivals) |
lifecycle | <old>-to-<new> per migration (free, from the code's names), oldest-code (what survives from the start and whether it still matters), deletions (directories removed wholesale) |
trajectory | velocity (the trend and the 90-day comparison), work-mix (feature vs fix vs refactor, now vs a year ago), direction (what the last period implies and the risks that follow), no-history (when the history is absent) |
Naming a migration. lifecycle/<old>-to-<new> takes the names from the code, not from prose: when a side is a package, module or directory, use that identifier verbatim (statichtml-to-client-rendered, not server-to-client-rendering); when both sides are named tools, use the tool names (graphviz-to-mermaid). If one side has no name in the code, name it for the mechanism it replaces (iframe-to-native), and say in the description what you named it after — that sentence is what keeps the next run consistent.
Where measurability goes. Whether the history is legible enough to trust (commit messages that became classifiable, a git export that starts mid-life) is not a finding of its own: state it inside trajectory/work-mix (for theme mix) or growth/growth-curve (for volume), as the caveat on the number it qualifies.
What a good finding looks like
An era finding reads like the opening of a chapter: dates, then what the project was in one sentence, what happened in three or four (name the largest commits and what they built — "the app-server JSON-RPC layer appears in 2025-09 with 962 new files in one month"), and what it left behind (a module, a convention, a debt). Quote the script's numbers via sokrates_refs (metric:commits, metric:contributors, metric:churn, metric:file_age, component:<name>); put the numbers in the description, not in evidence.
Evidence for history claims is the history itself: git-commits.txt:<line> for the commit message that did the thing, CHANGELOG.md/release notes lines, and for "this still exists" / "this is gone" claims the current file (a mod declaration, a manifest entry, a README sentence naming the new component); for binary or unreadable survivors (a zip, an image) the git-history.txt line that last touched them is the acceptable citation. git-history.txt lines are valid evidence too but rarely readable — prefer the message. A finding with only script-derived numbers and no citable line is possible (see the core evidence rules).
Not every trend is a problem. A cooling area that finished its job is good news; say so with severity: info. Reserve low–high for trajectory facts that call for action: an accelerating area with a single owner, a migration stalled with both halves alive, a departure that orphaned a load-bearing module, velocity collapsing while open scope grows.
Severity calibration
Use the core scale, driven by what the trend costs if nobody reacts:
high— the history shows an active hazard: a half-done rewrite where both generations are load-bearing and diverging; the core's only long-term owners gone in the last year; velocity dropping sharply while the codebase keeps growing.medium— a trend that will hurt within a few quarters: an emerging area accelerating under one contributor; dormant code that other active areas still depend on; work mix drifting to fixes-only (feature work stopped, maintenance burden rising).low— worth knowing and cheap to address: stale directories to delete, a completed migration whose old path lingers, a peripheral single-owner departure.info— chapters of the story, growth facts, and healthy trends.
Weigh recency heavily: the last two periods matter more than the first ten, and a claim about "now" must be backed by 90-day figures, not all-time ones.
In this repository27 other files it gives its agents.
- sokrates-decompositionsSkill
- sokrates-features-of-interestSkill
- sokrates-landscape-configSkill
- sokrates-people-configSkill
- sokrates-repo-configSkill
- sokrates-virtual-landscapesSkill
- sokrates-improveSkill
- architecture-scanSkill
- cicd-scanSkill
- configuration-scanSkill
- domain-language-scanSkill
- full-scanSkill
- functionality-scanSkill
- iac-scanSkill
- landscape-synthesis-scanSkill
- maintainability-scanSkill
- network-scanSkill
- observability-scanSkill
- performance-scanSkill
- reliability-scanSkill
- risk-synthesis-scanSkill
- security-scanSkill
- sokrates-scan-coreSkill
- storage-scanSkill
- tech-stack-scanSkill
- testing-scanSkill
- sokratesSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

