CommunityRecherche & Datenanalysegithub.com

Excavate (Ausgraben)

Benutzergesteuerter Seitenpfad zum Onboarding in ein Legacy-Repository ohne Dokumentation, Lösungsordner, Recherche-Archiv oder schriftliche Entscheidungen. Durchsucht die letzten 12 Monate der Git-Historie (und, wenn verfügbar, GitHub-PR-Bodies und Review-Threads) und erstellt eine Rangliste der Hotspots, zitiert wiederhergestellte Entscheidungen und eine „Wen-fragen“-Karte. Anschließend wird ein PR mit docs/solutions/-Einträgen angeboten. Nicht für Repos, die bereits compoundieren, nicht zur Beurteilung von Personen, nicht modellgesteuert.

Was ist Excavate (Ausgraben)?

Dieses Skill, genannt „Excavate“, ist ein spezialisiertes Werkzeug für das Onboarding in Legacy-Repositorys, denen Dokumentation, Lösungsordner, Recherche-Archive oder schriftliche Entscheidungen fehlen. Es wird ausschließlich vom Benutzer über den Befehl `/excavate` gestartet und ist nicht modellgesteuert (`disable-model-invocation: true`). Das Skill extrahiert die letzten 12 Monate an Git-Versionsgeschichte (begrenzt auf ein festes Zeitfenster) und, wenn GitHub-CLI (`gh`) verfügbar ist, auch PR-Bodies und Review-Threads. Als Ergebnis erstellt es einen „Off-Tree-Dossier“ (außerhalb des Baums), der eine Rangliste der Hotspots (basierend auf Änderungshäufigkeit und Codekomplexität), Kopplungen zwischen Dateien, wiederhergestellte Entscheidungen mit nachvollziehbaren Zitaten und eine „Wen-fragen“-Karte enthält. Zudem generiert es optional einen PR mit Einträgen im `docs/solutions/`-Format, die dann von verwandten Skills wie `/research`, `/write-a-prd` und `/execute` gelesen werden können. Das Skill folgt strengen Methodenregeln (z.B. basierend auf Adam Tornhill’s Arbeit) und stellt sicher, dass alle extrahierten Fakten durch Git-Hashes, PR-Nummern und direkte Zitate belegt sind, nicht durch Modellraten. Es ist ideal für Teams, die ein neues Legacy-Repository verstehen müssen, bevor sie erste Features entwickeln. Das Dossier hilft, Risiken zu identifizieren und fundierte Entscheidungen zu treffen.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/chrislacey89/skills/tree/HEAD/excavate

Installed? Explore more Recherche & Datenanalyse skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Excavate (Ausgraben)?

Stelle wieder her, was ein Legacy-Repository bereits über sich selbst weiß, bevor die erste Funktion blind darauf losgelassen wird. Die Ausgabe ist ein dossier außerhalb des Baums (Hotspots, Kopplungen, wiederhergestellte Entscheidungen, eine „Wen-fragen“-Karte und ein Coverage-Block, der sagt, was die Historie dir sagen konnte und was nicht) plus ein opt-in PR von docs/solutions/-Einträgen im Format von /compound, sodass /research, /write-a-prd und /execute sie durch den Keyword-Grep, den sie bereits ausführen, lesen können.

Zwei Dinge halten dieses Vorgehen ehrlich. Tornhills Methode betrachtet die Versionskontrolle als ein verhaltensorientiertes Protokoll: Ein Hotspot ist die Schnittmenge von Änderungshäufigkeit und Komplexität, keine der beiden Achsen allein, begrenzt auf ein festes Zeitfenster, und es ist eine Wahrscheinlichkeit zu überprüfen, kein Urteil, nach dem gehandelt werden muss. Und die Grounding-Regel (references/visual-rendering-core.md § 1) trennt jedes Artefakt: SHAs, PR-Nummern, Pfade, Zählwerte und zitierte Begründungen werden aus der git- und gh-Ausgabe kopiert, niemals neu getippt; das Modell schreibt nur die Prosa darum herum. Eine Entscheidung, deren „Warum“ eine Schätzung des Modells ist, ist nicht wiederhergestellt, sondern erfunden, und sie bleibt außerhalb des Repos.

Aufrufposition

Seitenpfad, nur benutzergesteuert. Es wird ausgelöst, wenn ein Mensch /excavate eingibt; disable-model-invocation: true hält seine Beschreibung aus dem Kontext jeder anderen Sitzung heraus, weil es einmal pro Repo beim Onboarding eingegeben wird und nie einen Grund hat, sich selbst auszulösen. Planungsmodus, HITL (Human-in-the-Loop) während des gesamten Prozesses; es gibt keinen AFK-Pfad, weil jedes committgebundene Element einen Menschen braucht, der das Zitat liest, auf dem es beruht.

Sende es als eigene Nachricht, nicht als erste Nachricht eines neuen Workspace. Ein verstecktes Skill, das in eine erste Nachricht getippt wird, der der Host eine Präambel voranstellt, wird als Prosa gelesen und nie geladen; /lfgs Aufrufposition dokumentiert den Vorfall vor Ort (chrislacey89/skills#383). Gib es als zweite Nachricht erneut ein.

/help Schritt 2 gibt das Signal für den Start damit an. Verwende es nicht auf einem Repo, das die Pipeline bereits compoundiert (führe dort /compound aus), nicht als Leistungsbeurteilung von jemandem (siehe § 5) und nicht als Fehlersucher (/qa und /triage-issue sind dafür zuständig).

Es steht neben der Hauptpipeline und verbindet sich bei /shape wieder: Die erste Funktion wird mit dem Dossier und den Einträgen in der Hand geformt. Es kann stattdessen an /request-refactor-plan übergeben werden, wenn der Top-Hotspot die Arbeit ist, oder an /qa, wenn die Historie ein fix-gekennzeichnetes Cluster zeigt, das nie geschlossen wurde.

Methodenregeln

Dies sind die Regeln, die der folgende Prozess operationalisiert. Jede zeigt, woher sie kommt; keine wird an anderer Stelle in dieser Datei wiederholt.

  • Rangordnen nach Revisionen, qualifizieren nach Codezeilen, niemals eine Achse allein. Häufigkeit ohne Größe markiert Konfigurationsdateien; Größe ohne Häufigkeit markiert Code, der vor Jahren durch Debuggen korrigiert wurde und seitdem nicht mehr angefasst wurde (Tornhill, Kap. 1-4). LOC via wc -l ist der Komplexitätsproxy: Es wird kein cloc vorausgesetzt, und LOC ist der Proxy, auf den das Buch standardmäßig zurückgreift.
  • Auf ein festes Zeitfenster begrenzen. Eine rohe Revisionsanzahl ist ohne Bezugszeitraum bedeutungslos. Zwölf Monate sind der Standard; verkürze es für Repos mit hoher Änderungsgeschwindigkeit. Gib das tatsächliche Fenster an.
  • Erwarte ein Potenzgesetz und schneide am Knick ab. Eine Handvoll Dateien trägt den Großteil der Kosten. Höre auf, wo die Kurve abflacht, niemals bei einer runden Zahl.
  • Ein Trend braucht Komplexität und Größe. Verschlechternd bedeutet, dass die Einrückungskomplexität schneller steigt als LOC; Refaktoriert bedeutet, dass beide fallen; Stabil bedeutet, dass beide flach sind (Tornhill, Kap. 5-6). LOC allein kann diese Bezeichnungen nicht liefern.
  • Filtere Nicht-Domänen-Dateien vor der Kopplung; klassifiziere jede Kopplung, bevor du sie meldest. Lockfiles, Manifeste, generierter und ausgelagerter Code sind falsch positive Ergebnisse. Ein Test, der an sein Subjekt gekoppelt ist, ist beabsichtigt und wird fallengelassen; Kopieren-Einfügen, nicht-unterstützende-Grenze und Produzenten-Konsumenten-Kopplungen werden behalten und gekennzeichnet (Tornhill, Kap. 8-9). Zusammengequetschte Historie zerstört Kopplungen auf Commitebene; verwende Änderungssätze auf PR-Ebene oder sage, dass der Abschnitt nicht verfügbar ist.
  • Hotspots sind Wahrscheinlichkeiten. Öffne die Datei, bevor du einen Mechanismus benennst, und biete keinen Eintrag für eine Datei an, die du nicht geöffnet hast.
  • Eigentumsdaten haben vier legitime Verwendungen: Einen Reviewer finden, Onboarding, Entscheiden, wo Tests hingehören, und Beurteilen, ob eine Struktur zum Team passt. Sie werden niemals verwendet, um Personen zu bewerten oder zu beurteilen, und sie werden durch .mailmap gelesen, wobei Bots und der initiale Import ausgeschlossen sind (Tornhill, Kap. 12-14).
  • Vorhandene Dokumentation ist zukunftsorientiert. Eine Behauptung in einem ADR, README oder CHANGELOG wird anhand des aktuellen Baums überprüft, bevor sie als gültige Entscheidung aufgezeichnet wird (Spinellis, Code Reading).
  • Der erste Schritt auf einem Hotspot ist ein Charakterisierungstest an einer kritischen Stelle, keine Refaktorisierung (Feathers, Working Effectively with Legacy Code). Der Abschnitt „Vorgeschlagene erste Schritte“ des Dossiers sagt dies pro Hotspot.
  • Ein Hotspot wird dafür ausgewählt, dass er extrem ist, also ist ein Teil seines Rangs Rauschen. Regression zur Mitte ist die Nullhypothese: Eine Datei, die in einem Zeitfenster ganz oben steht, kann im nächsten durchschnittlich sein, ohne dass etwas daran getan wurde, und eine Datei, die sich nach einer Refaktorisierung abgekühlt hat, hätte sich sowieso abgekühlt (Galton; Kahneman). Bewerte basierend auf der Beständigkeit über beide Hälften des Zeitfensters, kennzeichne jeden Hotspot als persistent oder single-window und leite nur persistente an die Liste der ersten Schritte weiter. Die Rangliste ist eine Diagnose, niemals ein Ziel; ein Team, das sich Ziele darauf setzt, bekommt Spielchen, keine Qualität (Goodhart).
  • Halte die Annahme neben der Entscheidung fest. Begründungen werden am schnellsten vergessen, und nicht festgehaltene Annahmen verhärten sich zu Zahlen, die niemand zu ändern wagt (Leveson, Engineering a Safer World, Kap. 10). Jede wiederhergestellte Entscheidung trägt die Einschränkung, die ihr Zitat angibt („habe X gewählt wegen Y, angenommen Z“), und ob Z immer noch im Baum gilt, ist der Umkehrdetektor.
  • Ein Entscheidungseintrag hat die Form eines ADR und eine Compliance-Zeile. Titel, Status, Kontext, die Entscheidung mit ihrem Warum, Konsequenzen und wie sie verifiziert wird; ohne das Letzte ist eine Aufzeichnung Archäologie und keine Governance (Richards & Ford, Fundamentals of Software Architecture, Kap. 19). Die Verifizierung hier ist der Grep oder der Pfad-Check, der gegen den aktuellen Baum ausgeführt wird.
  • Das Dossier wird von einem Neuling unter dem Fluch des Expertenwissens gelesen. Führe mit einem kurzen Glossar und den Hotspots am Knick, halte die vollständigen Tabellen dahinter und mache die erste Begrüßungsaufgabe zu verstehen und zusammenfassen eines wiederhergestellten Entscheidungs-Hotspots, anstatt ihn zu beheben (Hermans, The Programmer's Brain).

Prozess

Jeder untenstehende Code-Block wird wie geschrieben ausgeführt. Jeder Bash-Tool-Aufruf ist eine frische Shell, also überlebt keine Variable von einem Aufruf zum nächsten. Der Variablenblock in Schritt 0 wird einmal ausgeführt; der Block danach schreibt jeden aufgelösten Wert in $WORK/vars.sh, und jede spätere Shell (deine oder die eines Miners) beginnt mit . "$WORK/vars.sh" anstatt Schritt 0 erneut auszuführen, was SINCE auf seinen Standard zurücksetzen und ein --since oder eine NONDOMAIN-Erweiterung verwerfen würde. Eine Shell, die die Datei überspringt, schlägt ohne Fehler fehl: git log --since="" gibt keine Commits zurück und grep -Ev "" gibt nichts aus, und eine leere Ausgabe wird als die gültige Antwort „keine Reverts“ gelesen. WORK ist ein Pfad, der aus dem Repo abgeleitet wird, sodass eine neue Shell ihn mit dem WORK= Ausdruck aus Schritt 0 neu ableitet und die Datei darunter sourced; den Minern wird der absolute Pfad zu vars.sh in ihrer Arbeitsanweisung übergeben, anstatt dass sie eine Variable erben. <path> ist der einzige Platzhalter, der pro Hotspot ersetzt wird. Die Semantik der Flags ist die eigene Dokumentation des Tools (git-log, git-shortlog, git-rev-parse, gh pr list); diese Datei paraphrasiert sie nicht. scripts/test-documented-git-commands.sh führt jeden Git-Block gegen eine eingepflanzte Testumgebung aus, sodass ein Block, der keine gültige Invokation mehr ist, in CI fehlschlägt.

0. Vorabprüfung

Analysiere die Argumente: --since <datum> (Standard 12 months ago; jede Form, die git log --since akzeptiert) und --paths <pathspec>... (ersetzt den . in jedem Block unten). Setze dann die gemeinsamen Variablen:

SINCE='12 months ago'
WORK="${TMPDIR:-/tmp}/excavate-$(git rev-parse --show-toplevel | cksum | cut -d' ' -f1)"
mkdir -p -m 700 "$WORK"
START=$(git log --since="$SINCE" --no-merges --format=%cs HEAD </dev/null | tail -1)
NONDOMAIN=(':(exclude)*.lock' ':(exclude)*package-lock.json' ':(exclude)*pnpm-lock.yaml' ':(exclude)*yarn.lock' ':(exclude)*.min.*' ':(exclude)*.snap' ':(exclude)*.generated.*' ':(exclude)CHANGELOG.md' ':(exclude)*/vendor/*' ':(exclude)*/node_modules/*')
BOTS='[[]bot[]]|dependabot|renovate'
MAXFILES=30
export GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.quotePath GIT_CONFIG_VALUE_0=false

Der GIT_CONFIG_* Export setzt core.quotePath=false für jeden Git-Aufruf in diesem Durchlauf (siehe git-config, Umgebung), sodass ein Pfad mit Nicht-ASCII-Bytes als sich selbst ausgegeben wird und nicht als quoted escape, das wc und die folgenden Joins nicht öffnen oder abgleichen können.

START ist das erste Commit-Datum innerhalb des Fensters, abgeleitet von git und nicht von date, weil date -d nur unter GNU und date -v nur unter BSD verfügbar ist. NONDOMAIN ist eine Startliste: Erweitere sie um die generierten, ausgelagerten, Snapshot- und gespiegelten Pfade dieses Repos vor Schritt 1 (überprüfe git check-attr linguist-generated linguist-vendored bei allem Verdächtigen). MAXFILES ist die Obergrenze für die Änderungssatzgröße, oberhalb derer ein Commit als Massendurchlauf (Neuformatierung, Import, Massenumbenennung) behandelt und von der Häufigkeits- und Kopplungszählung ausgeschlossen wird. Das gemeinsame Log in Schritt 2 wendet es einmal an, wenn das Log erstellt wird; kein späterer Block wiederholt es.

WORK ist an den Top-Level-Pfad des Repos gebunden, nicht an HEAD, weil Schritt 8 HEAD auf den Docs-Branch verschiebt; es bleibt über Shells hinweg gültig und wird in Schritt 9 entfernt. Wenn ein Verzeichnis von einem unterbrochenen Durchlauf bereits vorhanden ist, lösche es vor dem ersten Block von Schritt 2, damit veraltete Dateien nicht als Ausgabe dieses Durchlaufs durchgehen können.

Persistieren die aufgelösten Werte, sobald NONDOMAIN erweitert ist (und erneut nach der Gate-Prüfung in Schritt 1, wenn der Benutzer das Fenster ändert: source die Datei, setze SINCE, führe die START= Zeile von Schritt 0 erneut aus, dann führe diesen Block erneut aus):

{
  declare -p SINCE START NONDOMAIN BOTS MAXFILES WORK
  declare -px GIT_CONFIG_COUNT GIT_CONFIG_KEY_0 GIT_CONFIG_VALUE_0
} > "$WORK/vars.sh"

Messe dann die Abdeckung, in einer Shell, die mit . "$WORK/vars.sh" beginnt:

git rev-parse --is-shallow-repository
git rev-list --count --since="$SINCE" --no-merges HEAD
git log --max-parents=0 --format=%cs HEAD </dev/null | sort | head -1
git log --since="$SINCE" --no-merges --format=%s HEAD </dev/null | awk '{ t++ } /\(#[0-9]+\)$/ { s++ } END { printf "%d of %d subjects end in (#N)\n", s, t }'

Die vier Zeilen sind: shallow oder nicht, Commits im Fenster, Root-Commit-Datum (die Shallow-Grenze, wenn shallow, also sage dann „unbekannt“) und das Squash-Verhältnis. Ein hohes Squash-Verhältnis bedeutet, dass jeder Commit ein ganzer PR ist, also ist Kopplung auf Commitebene bereits PR-Ebene-Kopplung; ein niedriges Verhältnis mit Squash-Merged PRs woanders ist der zu beobachtende Fall.

Zähle dann die Commits, die eine Änderung, die bereits im Fenster ist, erneut einbringen, weil ein Repo, das über Release-Branches ausliefert, dieselbe Änderung als Original, Cherry-Pick und als Release- oder Sync-Rollup trägt, und jede Anzahl unten sieht jede Kopie als separate Revision:

git log --since="$SINCE" --no-merges --reverse -p --format='commit %H' HEAD -- . "${NONDOMAIN[@]}" </dev/null \
  | git patch-id --stable | awk 'seen[$(1)]++ { print $(2) }' > "$WORK/dups.txt"
wc -l < "$WORK/dups.txt" | tr -d ' '

dups.txt listet jeden Commit auf, dessen Patch-ID (git-patch-id) ein früherer Commit im Fenster bereits hatte, sodass die älteste Kopie diejenige ist, die nicht auf der Liste steht. Es liest dasselbe Fenster und denselben Pathspec wie das gemeinsame Log in Schritt 2, sodass es Kopien unter den Commits zählt, die die Rangliste liest; ein gemergter Branch, dessen Änderungen bereits auf der Hauptlinie sind, wird von der History-Vereinfachung von git log in beiden übersprungen. Die Anzahl geht in den Coverage-Block, und Schritt 3 bewertet den Knick ohne diese Commits neu. Sie werden gezählt, nicht ausgeschlossen: Eine erneut eingebrachte Änderung ist immer noch Arbeit, die jemand geleistet hat, ein Rollup kann die einzige Aufzeichnung der Änderungen sein, die es trägt, und jeder spätere Block liest die Historie durch sein eigenes git log oder git rev-list, sodass ein Filter, der nur auf das gemeinsame Log angewendet wird, dazu führen würde, dass die Schritte nicht übereinstimmen. Benenne alle Release- oder Sync-Rollups, die du in den Betreffzeilen bei der Scope-Gate siehst; sie werden ebenfalls nicht ausgeschlossen.

Überprüfe gh auth status und ob das Remote GitHub ist; zeichne gh: yes oder gh: no auf. Löse das Dossier-Verzeichnis auf mit bash "$SC" path research, wobei SC der absolute installierte Pfad des mitgelieferten Resolvers dieses Skills ist, references/sidecar.sh; berechne niemals selbst einen Sidecar-Pfad. Bei SIDECAR MISS beendet sich der Resolver mit Exit 1 und gibt einen init-Befehl aus: Zeige ihn dem Benutzer und fahre fort, sobald dieser ihn ausgeführt hat, weil das Erstellen eines Sidecars eine menschliche Handlung ist. Suche in diesem Verzeichnis nach einem früheren excavation-*.md und nach einem vorhandenen docs/solutions/; eine erneute Ausführung aktualisiert Einträge, anstatt sie zu duplizieren, und bewertet die persistent-Tags des vorherigen Dossiers gegen das neue Fenster (wie viele heiß geblieben sind), sodass der Coverage-Block eine Trefferquote für seine eigenen Vorhersagen trägt.

Wenn das Repo shallow ist, sage, wie viel Historie fehlt, und biete git fetch --unshallow an; führe es niemals aus, da es .git neu schreibt.

1. Scope-Gate (HITL)

Gib den Coverage-Block genau so aus, wie er das Dossier anführen wird:

Fenster:        <START> → heute (<SINCE>)
Commits:        <N> Non-Merge (<M> ausgeschlossen als Bulk > MAXFILES Dateien)
Shallow:        ja | nein
Squash-Verhältnis: <s>/<t>
Duplikate:      <d> Commits wiederholen eine frühere Patch-ID (gezählt, nicht ausgeschlossen)
gh:             ja (<geholt> von <gesamt> gemergten PRs; <geschlossen> geschlossen ungemergt) | nein
Fix-Label:      <k> von <N> Commits entsprechen dem Fix-Muster (eine Untergrenze; wird in Schritt 3 ausgefüllt)
Ausgeschlossen: <NONDOMAIN-Liste, eine Zeile>
Nicht sichtbar: geschlossen-unmergte PRs, force-gepushte oder gequetschte Historie, gelöschte Dateien, ausgeschiedene Mitwirkende

Die Zeile Nicht sichtbar ist keine Standardfloskel. Alles unten bewertet s

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

chrislacey89/closeout

Primary pipeline tail step after /pre-merge, when a reviewed PR is ready to land and you want the workspace back to a clean base. Use to merge, switch off the worktree before removing it, prune the merged branch, pull base, and verify a clean end state. Triggers on 'close out', 'merge and clean up', 'get back to a clean main/base', 'tear down the worktree'. Not for capturing lessons (that's /compound), or closing the PRD and any other open slices and research-artifact hygiene (that's the cleanup prose in SYSTEM-OVERVIEW Step 9).

chrislacey89/compound

Primary pipeline knowledge-capture step that closes the compounding loop. Capture a durable lesson in docs/solutions/ onto the open PR before /closeout merges (the default), or post-merge when the lesson only surfaces during/after merge. Use so future /research and /write-a-prd runs improve. Not for trivial edits with no reusable project-level learning, and not for the merge/teardown itself (that's /closeout).

chrislacey89/execute

Primary pipeline execution step after /prd-to-issues or for clearly scoped implementation work. Use to build, verify, and commit a concrete slice, delegating to /tdd for backend work and behavior-heavy frontend logic when red-green-refactor will reduce risk. Not for shaping or pre-merge review.

chrislacey89/pre-merge

Primary pipeline review step after verified implementation. Use to create a PR with lineage and run architectural review before merge. Not for QA intake, planning, or implementation work.

Verwandte Skills