incoming/: die Rohablage wird abgeleitet statt von Hand einsortiert
#58
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?
Umgesetzt und ausgeliefert in
4.8.0-beta.3, Commit36d2128. Aufgeworfen und entschieden in den Sitzungen vom 2026-09-04, gebaut am 2026-09-05.Das Problem, das es gab
raw/CONTRACT.mds Routing-Tabelle war eine Regel für Menschen: wer eine Datei ablegte, wähltearticles//documents//notes//assets/selbst. Zwei Folgen:kb/,raw/war ausgenommen, ohne dass das je jemand entschieden hätte.raw_files:der Source-Seite.Nicht das Problem war die Tiefe selbst:
config.iter_raw_filesmachtrglob("*"),provenance.pyundsources coveragearbeiten auf repo-relativen Pfaden —raw/documents/handbuch/original.pdffunktionierte schon vorher ohne Codeänderung. Flach waren nur die Contract-Tabelle unddist_cmd.RAW_SUBDIRS. Es fehlte kein Mechanismus, es fehlte eine Zuständigkeit.Ebenfalls nicht das Problem war der Bestand: die 29 Rohdateien liegen flach innerhalb ihrer Unterverzeichnisse (
articles/3,documents/1,notes/25;assets/leer und mangels Datei nicht getrackt). Unter Entscheidung 3 sind das eindateiige Quellen in vorschriftsmäßiger Form. Es wurde nichts umsortiert.Der Weg, wie er jetzt läuft
Mehrdateiige Quelle:
Eindateiige Quelle:
Die Entscheidungen
1. Der Eingang ist ein Top-Level-
incoming/im Repo, gitignoriert. Nicht außerhalb, nicht unterraw/.Unter
raw/war es unmöglich:.gitignoreendet mit dem Backstop!raw/**, unddocs_verify.check_ignored_contentschlägt auf jede ignorierte Datei unterraw|kb|workfehl — einraw/incoming/wäre entweder committed oderdocs verifyrot. Gegen „außerhalb des Repos" entschied der Nachweis: „wird nie committed" ist überdocs_verify.REQUIRED_IGNORE_CANARIESmechanisch belegbar (git check-ignore --no-indexbeantwortet die Frage über den Regelsatz, ohne dass die Datei existieren muss); für einen Pfad außerhalb des Baums existiert dieses Beweismittel nicht, und er bräuchte zusätzlich eine Konfigurationsfläche, die es nirgends gibt.Gilt auch für #32. Dessen schärfere Anforderung („eine Quarantäne, die kein Kommando der normalen Pipeline liest") trägt nicht der Ort, sondern die Grenze zwischen Sitzung und Pipeline-Kommando — siehe § Verhältnis zu #32.
2. Der Typ wird über Unterverzeichnisse im Eingang deklariert, nicht über ein Flag.
incoming/spiegeltRAW_SUBDIRS. Kein--type-Argument.Keine Rückkehr zur Handsortierung, weil zwei Entscheidungen auseinanderfallen: was für ein Dokument das ist (eine Klassifikation, die kein Werkzeug ableiten kann — eine
.mdkannnotes/oderarticles/sein) und wo die Datei am Ende liegt (Unterverzeichnis, Bundle ja/nein, Bundle-Name, die Bewegung). Der Mensch liefert nur die erste, aus einem Vierer-Vokabular. Drei Vorteile gegenüber dem Flag: die Erklärung wird abgegeben, wenn der Mensch das Dokument in der Hand hat, und überlebt Sitzungswechsel; ein Argument weniger ist ein Fehlweg weniger; eine Datei direkt inincoming/kann abgelehnt werden, während ein Flag immer gesetzt ist, richtig oder falsch.3. Ein Bundle-Verzeichnis entsteht nur bei Bedarf — ab der zweiten Datei. Eine Datei → Datei, mehrere → Verzeichnis.
Das war die Kehre gegenüber der ursprünglichen Skizze („einheitlich"). Entscheidend war die Folge für den Bestand: unter „einheitlich" wären die 29 flachen Dateien eine datierte Ausnahme im Contract gewesen oder eine Umsortierung mit 29 Bewegungen plus referenzierenden Seiten — über der Mass-Update-Schwelle, also ein eigener Publish mit Freigabe. Unter „nur bei Bedarf" stellt sich der Fall nicht.
4. Der Bundle-Name kommt aus dem Stem der Primärdatei (erstes Argument, bzw. die bereits liegende Datei im Wachstumsfall), nicht aus dem Titel der Source-Seite — letzteres würde
raw/ankb/koppeln.5. Ein Bundle trägt den Typ der Quelle, nicht der einzelnen Datei. Ein Diagramm zu einer
documents/-Quelle wird ausincoming/documents/befördert, nicht ausincoming/assets/;assets/ist für Quellen, die selbst ein Asset sind. Steht als Satz inraw/CONTRACT.md.6.
--pageist optional, außer im Wachstumsfall. Ohne--pagebewegtacceptnur und druckt die Zielpfade fürnew source --set raw_files=…. Mit--pageerweitert esraw_files:einer bestehenden Seite; entsteht dadurch die zweite Datei, zieht es die Bundle-Beförderung der bereits liegenden Datei im selben Aufruf nach.Die Rückwärtssuche musste nicht gebaut werden:
provenance.source_pages_by_raw_file()invertiertraw_files:über alle Source-Seiten und trägt schonduplicate_raw_file_owners. Sie wird benutzt statt eines „ich weiß ja, welche Seite gemeint ist"-Kurzschlusses — eine zu bewegende Rohdatei mit mehr als einem Owner wird abgelehnt, statt die andere Seite unbemerkt zu brechen.7.
RAW_SUBDIRSist die einzige Quelle der Liste. Sie speist vier Stellen: Eingangsverzeichnisse,raw/-Verzeichnisse, Contract-Tabelle,.gitkeep-Schleife indist export.docs verify(check_raw_subdirs) hält die Tabelle beidseitig dagegen (Invariante 8).8. Die Version ist MINOR. Die ursprüngliche Vermutung „eine erzwungene Umsortierung wäre die Major-Zeile" hielt dem Drop-in-Test nicht stand: eine Umsortierung dieser Instanz wäre eine Korpus-Operation und erreicht keine fremde Instanz. Boundary-crossing wäre es erst, wenn etwas die Bundle-Form validiert; nichts tut das, und unter Entscheidung 3 wird ohnehin nichts umsortiert.
Umsetzungsnotizen
Path.rename()stattgit mv. Das in #16 als geteiltes Kleinstprimitiv erwartete „git mvversuchen, bei not under version control aufmvzurückfallen" wird hier nicht gebraucht: die Quelle inincoming/ist per Definition nie getrackt, undpage_ops.rename_command/move_commandbewegenkb/-Dateien längst mit schlichtemPath.rename(), weilpublishsgit add -Aeine inhaltsgleiche Bewegung ohnehin als Rename erkennt. Bewusst dem bestehenden Muster gefolgt statt einen neuen git-Subprozess-Helfer einzuführen.doctorwurde nicht erweitert. Kein Akzeptanzkriterium verlangte es, und der Fall, um den es ginge (frischer Klon ohneincoming/), ist überinstructions/bootstrap.mdSchritt 2 abgedeckt.doctormeldet weiterhin nur und legt nie an — der Satz in Schritt 2 sagt das ausdrücklich.README.mdbeschrieb den Ingest-Einstieg noch als „drop a file intoraw/" (Verzeichnisbaum, Quickstart, „Curate sources", erste Ingestion,wiki-ingest-Zeile) — nachgezogen, weil AGENTS.md § Changelog eine Stack-Änderung erst mit der Menschendoku als fertig zählt.docs/pipeline-rationale.mdbekam einen Satz:incoming/liegt auf der Diesseits-Seite der Vertrauensgrenze, die Grenze ist die Beförderung nachraw/, nicht der Moment der Ablage.INSTALL.md,INSTALL-MCP.md,EVALS.mdundtools/README.mdwurden geprüft und brauchten nichts.Verhältnis zu #32
#32 skizziert dieselbe Mechanik, kommt aber von der anderen Seite: dort fremd eingereichtes Material, das nicht ungeprüft in ein öffentliches Repo darf, hier eigenes, das der Nutzer nicht selbst einsortieren soll. Ein Mechanismus, zwei Auslöser.
incoming/will, dass die Ingest-Sitzung hineinsieht. Aufgelöst über die Grenze Sitzung vs. Pipeline-Kommando — und das war gratis:lintundsources coveragegehen ausschließlich überconfig.iter_raw_files(config.RAW_DIR), alles außerhalbraw/ist per Konstruktion unsichtbar, ohne Ausschlussliste.status/blockedauf #19; der lokale Ablagepfad hing an nichts davon.raw acceptsteht jetzt; #32 konsumiert es und ergänzt, was nur der Fremdeinreichung eigen ist: Auth, Kontingente, Manifest mit Einreicherzurechnung, Ablehnungspfad.Verhältnis zu #16
Keine Abhängigkeit, in keiner Richtung — auch nicht die, die #16s Kommentar vom 2026-09-04 20:56 behauptete. Dort ist die Richtigstellung als Kommentar hinterlegt:
raw acceptbefördert eine Datei, die noch keine Seite referenziert, und der eine referenzierende Fall benutzt die vorhandene Inversion ausprovenance.py. Der Bestandspunkt stellte sich unter Entscheidung 3 gar nicht.Was #16 aus dieser Umsetzung erbt: die
raw-Kommandogruppe existiert jetzt (tools/chemenu/commands/raw_cmd.py, registriert incli.py),raw renamehängt sich nur noch ein.Abgrenzung (unverändert eingehalten)
wikitool.raw/;raw/bleibt immutabel, hier entstand nur ein Weg hinein.Akzeptanzkriterien
raw acceptsind die beförderten Dateien byte-identisch mit dem, was im Eingang lag, und der Eingang enthält sie nicht mehr — Test vergleicht Inhalte (test_single_file_needs_no_bundle,test_two_files_bundle_under_the_first_files_stem).raw/<sub>/<name>ohne Zwischenverzeichnis; mehrere in einem Aufruf alsraw/<sub>/<stem>/<name>.incoming/wird mit Exit 1 abgelehnt und nennt die zulässigen Verzeichnisse; nichts wird bewegt (test_file_directly_in_incoming_is_rejected, dazutest_unknown_type_subdir_is_rejected,test_nested_too_deep_is_rejected).incoming/erzeugt keinuncovered_raw_files-Finding (test_promoted_file_in_incoming_is_never_reported_uncovered).git check-ignore --no-indexmeldet einen Pfad unterincoming/als ignoriert, geprüft überdocs_verify.REQUIRED_IGNORE_CANARIES(test_incoming_inbox_is_ignored, plus das bestehendetest_no_content_is_gitignored, das die Kanarie mitprüft).raw_files:-Referenz ins Leere; im Wachstumsfall nenntraw_files:danach alle Dateien unter neuen Pfaden,lintmeldet wederbroken_raw_refsnochuncovered_raw_files(test_growth_case_no_broken_or_uncovered_refs_afterwards).test_growth_case_rejects_a_multi_owner_raw_file).dist_cmd.RAW_SUBDIRSund die Routing-Tabelle beschreiben dieselbe Liste;docs verifyschlägt in beiden Richtungen fehl (check_raw_subdirs,test_raw_subdirs_mismatch_is_reported).dist exportlegt jeRAW_SUBDIRS-Elementraw/<sub>/.gitkeepundincoming/<sub>/.gitkeepan (test_plan_creates_matching_incoming_subdirs,test_export_into_a_fresh_directory_works).instructions/bootstrap.mdlegt die Eingangsverzeichnisse an (neuer Schritt 2, mit dem Grund: gitignoriert,doctormeldet nur).raw/CONTRACT.mdbeschreibt Eingang, Bundle-Regel und den Typ-des-Bundles-Satz; die Routing-Tabelle liest sich als abgeleitetes Verhalten.tools/CONTRACT.mdträgt Zeilen fürraw acceptund seinen Fehlerkontrakt;docs verifyerzwingt beide Richtungen.wiki-ingest-Skill kennt den Weg über den Eingang (neuer Schritt 1, Schritte neu nummeriert, Kommandoliste ergänzt).4.8.0-beta.3(Kandidat, kein Release).Verifiziert
tools/wikitool docs verify— OK, 52 Kommandos dokumentiert, 11 Ignore-Kanarien klar.tools/wikitool instructions verify— OK, 20 Instructions und 7 Skills gültig, 14 publizierte Kopien identisch.pytest -qlokal: 1032 passed, davon 19 neu intools/chemenu/tests/test_raw_cmd.pyplus 4 intest_docs_verify.py/test_dist_cmd.py.--dry-run, dann echte Beförderungincoming/notes/… → raw/notes/…,sources coveragemeldete die Datei danach korrekt als ungedeckt (keine Source-Seite); Testdatei wieder entfernt.36d2128: Lauf 182 (verify) grün — Tests, Coverage, Verify-Tree, Version-Gate,dist exportund der Frisch-Instanz-Replay des Exports. Lauf 183 (release) grün und hat korrekt kein Release geschnitten:VERSIONträgt-beta.3, jüngstes Release bleibtv4.7.4.Schließt #58.
Changelog: Alle sechs offenen Fragen entschieden, Body auf den Entwurfsstand umgeschrieben,
kind/decision→kind/build.Zwei Entscheidungen fielen anders aus als der ursprüngliche Body vorschlug:
incoming/statt über ein--type-Flag. Die Klassifikation wird abgegeben, wenn der Mensch das Dokument in der Hand hat, und überlebt den Sitzungswechsel; das Flag entfällt ersatzlos.Weiter entschieden: Eingang als Top-Level-
incoming/im Repo (gilt auch für #32), Bundle-Name aus dem Stem der Primärdatei, Bundle trägt den Typ der Quelle,--pageoptional außer im Wachstumsfall,RAW_SUBDIRSbleibt einzige Quelle der Liste.Drei Korrekturen gegen den alten Body: die Version ist MINOR, nicht MAJOR — eine Umsortierung dieser Instanz ist eine Korpus-Operation und erreicht keine fremde Instanz. Die 29 Dateien liegen nicht „flach in
raw/", sondern flach innerhalb ihrer Unterverzeichnisse (3/1/25,assets/leer). Und die Rückwärtssuche für den Wachstumsfall muss nicht gebaut werden —provenance.source_pages_by_raw_file()gibt es seit langem undlintbenutzt sie bereits.Neu ergänzt: § Verhältnis zu #16 hält fest, dass keine Abhängigkeit in beide Richtungen besteht, und notiert den Korrekturbedarf am dortigen Kommentar vom 2026-09-04 20:56, der nach diesen Entscheidungen in beiden Hälften nicht mehr gilt.
Changelog: Body auf den Endstand umgeschrieben und geschlossen. Alle 14 Akzeptanzkriterien abgehakt, jeweils mit dem Test benannt, der sie hält. Das Problem steht jetzt im Präteritum, die acht Entscheidungen als getroffen.
Neu gegenüber dem Entwurfsstand ist der Abschnitt Umsetzungsnotizen mit drei Punkten, die beim Bauen entschieden wurden und aus keinem Kriterium folgten:
Path.rename()statt des aus #16 erwartetengit mv-Primitivs (Quelle inincoming/ist nie getrackt, undpage_opsbewegtkb/-Dateien längst genauso);doctorbewusst nicht erweitert (der Fall liegt beibootstrap.mdSchritt 2); und die Menschendoku über die Kriterienliste hinaus —README.mdbeschrieb den Einstieg noch als „drop a file intoraw/",docs/pipeline-rationale.mdbekam einen Satz zur Vertrauensgrenze,INSTALL*.md/EVALS.md/tools/README.mdgeprüft und unverändert.Der Korrekturbedarf an #16 ist erledigt statt nur vermerkt: Kommentar dort stellt beide Hälften richtig und hält fest, was #16 aus dieser Umsetzung erbt (die
raw-Kommandogruppe existiert jetzt).Verifikation im Body benannt:
docs verify,instructions verify, 1032 lokale Tests, ein manueller CLI-Durchlauf, CI-Läufe 182 (verify, grün) und 183 (release, grün und korrekt ohne Release für den-beta.3-Kandidaten).torben referenced this issue2026-09-11 09:34:27 +00:00