instructions sync kopiert Skills in eine andere Verzeichnistiefe: 52 von 58 relativen Links brechen
#98
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
tools/wikitool instructions synckopierte jedeSKILL.mdunverändert (shutil.copytree) in ein Verzeichnis anderer Tiefe und ohne ihre Nachbarn. Jeder relative Link, der für den Quellort korrekt geschrieben war, zeigte in der publizierten Kopie ins Leere.Gemessen am 2026-09-12, vor der Reparatur:
instructions/**/SKILL.md(Quelle, 7 Dateien).claude/skills/**/SKILL.md(publiziert)Keiner der 52 war ein Tippfehler — für jeden existierte die Zieldatei im Repo. Die sechs Überlebenden waren zwei Zufälle: Verweise auf ein anderes publiziertes Skill (
../stack-dev/SKILL.md) und../../../docs/model-and-effort-selection.mdaus den Dev-Skills, die in Quelle und Ziel zufällig gleich tief lagen.Zwei unabhängige Ursachen mit verschiedener Reparatur:
../session-setup.md,../gates.md,../issue-tracking.mdinstructions/wurde gar nicht mitpubliziert, das Ziel fehlte unter.claude/skills/in jeder Tiefe../../kb/CONTRACT.md,../../raw/CONTRACT.md../zu wenigIn der ausgelieferten Instanz
nathan(5.0.0): 76 von 386 relativen Links tot, alle 76 in publizierten Skills; der Rest der Instanz war sauber. Die auslösende Meldung kam von dort und war Klasse A — dersession-setup.md-Verweis, den jedes Wiki-Skill vor seinem erstenwikitool-Aufruf ausspricht.Der Schaden war nicht der fehlgeschlagene Read, sondern dass die Sitzung danach weiterarbeitete: ohne Budget-Skalierung, ohne gelesene Gate-Prozedur, ohne die Konventionen der Instanz. Ein toter Link in einer Instruction ist ein still übersprungener Schritt.
Wurzel: Nichts im Stack löste je ein Linkziel auf.
docs verifyregistrierte zehn Checks, keiner las ein Linkziel;instructions verifyprüfte, ob eine Instruction referenziert wird, nie ob die Referenz auflöst. Deshalb konnte der Befund 52-fach und unbemerkt wachsen.Umgesetzt
Regel: repo-root-relative Klartextpfade in
SKILL.md. Alle 58 Verweise in den 7SKILL.mdstehen jetzt als Klartextpfad statt als relativer Markdown-Link —instructions/session-setup.mdstatt[session-setup.md](../session-setup.md),kb/CONVENTIONS.md§ Tone statt eines Anker-Links. Ein solcher Pfad überlebt die Kopie unverändert, weil er nicht von der Position der lesenden Datei abhängt: das Arbeitsverzeichnis einer Sitzung ist die Instanzwurzel, belegt durch die auslösende Fehlermeldung selbst. Damit fielen Klasse A und B zugleich weg, ohne dasssyncetwas Neues tut — die Kopie bleibt byteidentisch,drift()vergleicht weiter mitfilecmp.dircmp.Bewusst in Kauf genommen: aus der Quelle heraus ist ein solcher Verweis nicht mehr klickbar. Betrifft nur die 7
SKILL.md; alle übrigen Instructions werden nicht kopiert und behalten klickbare relative Links.Verworfen, mit Begründung:
syncdie Links umschreiben zu lassen (macht die Kopie nicht-byteidentisch,drift()müsste die Transformation kennen);instructions/mit unter.claude/skills/zu publizieren (löst nur Klasse A, verdoppelt den Instruction-Baum, vervielfacht die Drift-Fläche); führende/-Pfade (lösen gegen die Dateisystemwurzel auf).Zwei mechanische Checks, aufgeteilt nach Besitzverhältnis — das beantwortet die frühere offene Frage nach dem Prüfort mit beiden, nicht mit einem:
instructions verify→check_skill_reference_paths: verbietet jeden relativen Markdown-Link in einerSKILL.md. Ein Verbot statt einer Tiefenarithmetik, weil ein Markdown-Linkchecker Klartextpfade ohnehin nicht sieht — der Rückfallschutz liegt in der Form, nicht im Ziel. Liegt ininstructions_cmd.py, das die Skill/Instruction-Trennung (skill_dirs()vs.instruction_files()) bereits besitzt.docs verify→check_reference_targets: löst jeden relativen Markdown-Link über den Dateisatz vondocs tocauf (AGENTS.md, die Stage-Contracts,kb/CONVENTIONS.md, dieCOLLECTION.md, alle flacheninstructions/**.md) und meldet ein totes Ziel. Anker werden vor dem Auflösen abgeschnitten; Code-Fences und Inline-Code-Spans werden maskiert (markdown_code.strip_code_spans), damit eine Stelle, die Link-Syntax als Beispiel zeigt, nicht als echte Referenz gilt. Ein Ziel, das der Stack nur als<ziel>.templateausliefert, gilt als aufgelöst (siehe Nachbesserung unten).MARKDOWN_LINK_REundis_external_or_anchorleben einmal indocs_verifyund werden voninstructions_cmdimportiert (Invariante 8).CHANGES.mdbleibt außerhalb des Prüfumfangs — die zweite frühere offene Frage, entschieden wie vorgeschlagen: die beiden toten Links dort (instructions/claude-code-model-selection.md,instructions/enable-dev-extras.md) sind Belege für vergangene Zustände, keine Wegweiser, unddist exportersetztCHANGES.mdbeim Export ohnehin vollständig.commonplace/(Vendor) undraw/(Daten, Invariante 4) liegen aus denselben Besitz- bzw. Vertrauensgründen außerhalb.Nebenbefund behoben:
instructions/dev/doc-pull-through.md:36,45trug../tools/CONTRACT.mdstatt../../tools/CONTRACT.md— ein reiner Autorenfehler in der Quelle, unabhängig vom Kopierproblem, und der Fall, an demcheck_reference_targetsnachweislich greift.Dokumentation nachgezogen:
instructions/CONTRACT.md§ "A skill's outbound reference is a plain path, not a link" trägt Regel und Begründung samt der Abgrenzung, warumSKILL.mdanders behandelt wird als eine flache Instruction; § "Reference depth" benennt jetzt eine Referenz statt eines Links.tools/CONTRACT.mdist in beiden Tabellen (§ Commands, § Error contracts) für beide Checks nachgezogen.Nachbesserung: der Check feuerte auf einem frischen Export
Unmittelbar nach dem ersten Schließen dieses Issues gegen einen frischen
dist exportnachgeprüft — was in der ursprünglichen Verifikation gefehlt hatte.check_reference_targetsmeldete dort 13 tote Links (9×kb/CONTRACT.md, dazugerman-terminology.md,kb-profiles.md,link-taxonomy.md), und zwar dafür, dass der Export tut, was er soll:kb/CONVENTIONS.mdund die vierCOLLECTION.mdwerden nur als.templateausgeliefert und erst im Personalisierungsschritt voninstructions/setup-instance.mdübernommen, während die stack-eigenen Dateien sie unter ihrem künftigen Namen verlinken — korrekt, denn so wird sie heißen.Behoben in
c0dc212(6.0.0-beta.2): ein Linkziel gilt auch dann als aufgelöst, wenn daneben<ziel>.templateliegt. Eng gefasst — fehlt beides, bleibt es ein Befund; zwei Tests fixieren beide Richtungen. Damit beschreibt der Check nicht länger "noch nicht personalisiert" als "kaputter Link", einen Zustand, dendoctorunterconventionspräzise und zuständig meldet.CI war davon nie rot: der Replay in
.gitea/workflows/ci.ymlübernimmt die Templates, bevor erdocs verifyaufruft, undsetup-instance.mdstellt die Personalisierung (Schritt 5/6) ebenfalls vor die Verifikation (Schritt 13). Getroffen hätte es jeden, der nach dem Export einmal zur Kontrolledocs verifyaufruft.Versionsteil: MAJOR, nachträglich eskaliert
Zuerst als
--patchgebumpt (5.1.1-beta.2). In der Schlussphase beim Lesen der eigenen Regel intools/README.md§ Adding a command Schritt 5 aufgefallen, dass das falsch war:check_reference_targetsläuft über den Dateisatz vondocs toc, und fünf Dateien darin gehören der Instanz, nicht dem Stack —kb/CONVENTIONS.mdund die vierkb/<collection>/COLLECTION.md. Ein Drop-in-Copy vontools/,types/,instructions/undAGENTS.mdersetzt sie nicht. Ein toter relativer Link darin lässtdocs verifynach dem Update fehlschlagen, wo es vorher durchlief: genau die MAJOR-Zeile jener Regel ("a stricter check that newly fails on shipped content an instance already had"), undinstructions/dev/version-parts.mdentscheidet den Zweifelsfall zugunsten des Grenzübertritts.Gemessen bricht heute nichts —
nathanträgt 25 relative Links in diesen fünf Dateien, davon null tote; dieses Repo ebenso. Die Einstufung folgt der Reichweite des Checks, nicht einem beobachteten Schaden. Der Kandidat wurde nach ausdrücklicher Freigabe des Betreibers auf6.0.0-beta.1eskaliert, mit--breaking(was aufhört zu funktionieren und wie eine Instanz es repariert) und--no-migration(keinekb/-Seite ändert ihre Form).Dass der Fehlgriff von einem Menschen beim Lesen des Diffs gefunden wurde und von keinem Check, ist genau das, was
docs/version-model.mdüber diese Stelle sagt — die Seite ist dadurch bestätigt, nicht veraltet.Akzeptanzkriterien
instructions/**/SKILL.mdenthält noch einen relativen Markdown-Link; alle 58 Verweise stehen als repo-root-relative Pfade..claude/skills/,.agents/skills/) und gegen einen frischendist export, sowohl vor als auch nach der Template-Übernahme: jeweils 0 tote.instructions syncerzeugt weiterhin byteidentische Kopien;drift()ist unverändert und meldet nach einemsyncnichts (instructions verify: 14 Kopien stimmen mit ihrer Quelle überein).wikitool-Check meldet beide Hälften und läuft in CI (docs verifyundinstructions verifysind beide Teil von.gitea/workflows/ci.yml).instructions/dev/doc-pull-through.md:36,45korrigiert.instructions/CONTRACT.mdträgt die Regel;tools/CONTRACT.mdist in § Commands und § Error contracts nachgezogen.test_a_plain_path_resolves_the_same_regardless_of_which_copy_reads_it(die Eigenschaft, auf der die Reparatur ruht) und die zwei Template-Tests aus der Nachbesserung.Verifiziert
tools/wikitool docs verify(56 Kommandos, 38 Referenzdateien, "every link resolving"),tools/wikitool instructions verify(22 Instructions, 7 Skills, 14 Kopien),pytest1244 passed. Außerhalb der Werkzeugkette nachgemessen:.claude/skills/und.agents/skills/tragen 0 relative Links,instructions/114 relative Links mit 0 toten, die fünf instanz-eigenen Dateien innathan25 Links mit 0 toten, und ein frischerdist export0 Befunde — vor wie nach der Template-Übernahme.Was die erste Verifikation nicht abdeckte, und die Lehre daraus: sie prüfte den Arbeitsbaum und nicht den exportierten — bei einer Änderung, deren ganzer Gegenstand Kopien in anderer Verzeichnistiefe sind. Genau die Achse, um die es ging, war die ungeprüfte; der Defekt der Nachbesserung stand deshalb kurzzeitig ausgeliefert im Repo.
pytest/docs verify/instructions verifyliefen dabei durchgehend grün, wasinstructions/dev/stack-dev.mds Vorbehalt bestätigt: abgedeckt ist, was die Tests abdecken, nicht was sie abdecken sollten.Commits:
0fb8fd6(Reparatur, Checks, Tests, Doku),f140e26(Versionseskalation auf6.0.0-beta.1),c0dc212(Template-Ausnahme,6.0.0-beta.2).Verwandt
#83 (
instructions verifygleicht "wikitool commands used" gegen den Skill-Body ab) — dieselbe Prüfstelle und dieselbe Lücke: am publizierten Skill wird inhaltlich nichts geprüft. Kein Duplikat;check_skill_reference_pathsschließt nur die Link-Hälfte davon.Ausgearbeitet aus dem
status/incoming-Stub. Der Stub im Wortlaut, weil die Rumpfumschreibung unten die einzige Aufzeichnung der ursprünglichen Anfrage überschreibt:Changelog: Verdacht bestätigt und vermessen —
status/unconfirmedfällt weg. "Nicht zuverlässig" war zu schwach: 52 von 58 relativen Links brechen deterministisch, Titel entsprechend geändert. Zwei unabhängige Ursachen getrennt (fehlendes Ziel vs. Tiefenversatz), Gegenprobe in einer ausgelieferten Instanz (nathan5.0.0: 76/386 tot, alle in publizierten Skills). Als Wurzel ergänzt, dass der Stack überhaupt keine Linkziel-Prüfung hat, plus zwei weitere Fälle derselben Symptomklasse mit anderer Ursache. Drei Entscheidungen benannt, nicht beantwortet →kind/decision. Vier Pflichtlabel gesetzt,status/incomingentfernt.Relative Pfade werden aus Skills nicht zuverlässig gefundento `instructions sync` kopiert Skills in eine andere Verzeichnistiefe: 52 von 58 relativen Links brechenChangelog: Entscheidung 1 getroffen — repo-root-relative Klartextpfade in den 7
SKILL.mdstatt relativer Markdown-Links; der Abschnitt "Zu entscheiden" ist durch "Entschieden" mit Begründung und den drei verworfenen Alternativen ersetzt. Daraus ergänzt: die Prüfung braucht zwei Hälften, weil ein Markdown-Linkchecker Klartextpfade nicht sieht, und die Quellen zu prüfen genügt, solange die Kopie byteidentisch bleibt. Neue Akzeptanzkriterien für Byteidentität unddrift(). Präzisiert, dass nur die 7SKILL.mdbetroffen sind — die flachen Instructions werden nicht kopiert und behalten klickbare relative Links. Restfragen (Prüfort,CHANGES.md-Umfang) unter "Noch offen", beide von der Umsetzungssitzung tragbar →kind/decisionwirdkind/build.Changelog: Rumpf auf den Endzustand umgeschrieben und geschlossen. Der Defekt steht jetzt durchgehend im Präteritum; aus "Entschieden"/"Noch offen" ist ein "Umgesetzt"-Abschnitt geworden, der beide Restfragen als beantwortet führt — Prüfort: beide Kommandos, aufgeteilt nach Besitzverhältnis (
check_skill_reference_pathsininstructions verify,check_reference_targetsindocs verify);CHANGES.md: außerhalb des Umfangs, wie vorgeschlagen. Neuer Abschnitt zum Versionsteil: zuerst--patch, in der Schlussphase als Grenzübertritt erkannt (der Check erreicht fünf instanz-eigene Dateien, die ein Drop-in-Copy nicht ersetzt) und nach Freigabe auf6.0.0-beta.1eskaliert. Alle acht Akzeptanzkriterien abgehakt, jeweils mit dem, was sie belegt. Verifikation benannt statt nur Commit-Hashes:docs verify,instructions verify, 1242 Tests, plus Nachmessung in beiden publizierten Bäumen und in der Instanznathan.Changelog: Abschnitt "Verifiziert" korrigiert - er war unvollständig, und ein Defekt daraus ist inzwischen behoben (
c0dc212,6.0.0-beta.2).Direkt nach dem Schließen gegen einen frischen
dist exportnachgeprüft, was hier vorher nicht geschehen war:check_reference_targetsmeldete dort 13 tote Links (9×kb/CONTRACT.md, dazugerman-terminology.md,kb-profiles.md,link-taxonomy.md) - und zwar dafür, dass der Export tut, was er soll.kb/CONVENTIONS.mdund die vierCOLLECTION.mdwerden nur als.templateausgeliefert und erst im Personalisierungsschritt übernommen; die stack-eigenen Dateien verlinken sie unter ihrem künftigen Namen, korrekt.Behoben: ein Linkziel gilt auch dann als aufgelöst, wenn daneben
<ziel>.templateliegt. Eng gefasst - fehlt beides, bleibt es ein Befund. Zwei Tests fixieren beide Richtungen.CI war nie rot (der Replay übernimmt die Templates vor
docs verify, undsetup-instance.mdstellt die Personalisierung in Schritt 5/6 vor die Verifikation in Schritt 13); getroffen hätte es jeden, der nach dem Export einmal zur Kontrolledocs verifyaufruft.Die Lehre gehört zum Paket: die Verifikation hatte den Arbeitsbaum geprüft und nicht den exportierten - bei einer Änderung, deren ganzer Gegenstand Kopien in anderer Verzeichnistiefe sind. Genau die Achse, um die es ging, war die ungeprüfte.
Korrektur zum Rumpf: Der Abschnitt "Verifiziert" nennt den Vorbehalt "abgedeckt ist, was die Tests abdecken" als aus
instructions/dev/stack-dev.mdstammend. Diese Datei gibt es nicht — der Vorbehalt steht ininstructions/dev/stack-dev/SKILL.md, Schritt 3. Eine falsche Pfadangabe in einem Issue über falsche Pfadangaben; hier als Korrektur statt als weitere Rumpfumschreibung, weil sonst nichts am Zustand falsch ist.