Am 2026-08-30 hat .gitea/workflows/ci.yml ein paths-ignore bekommen, damit reine Inhaltsänderungen kein CI mehr auslösen — publish fasst bei jedem Ingest kb/, raw/ und work/ an, und die volle Suite dafür zu fahren ist Lärm.
Belegt ist das nicht. Dass Gitea die Muster genauso auswertet wie GitHub, ist eine Annahme. Sie kostet nichts, wenn sie stimmt, und sie ist mit einer einzigen Beobachtung zu prüfen — deshalb dieses Issue statt einer Zeile Code.
Der Grund für die Vorsicht: in genau dieser Sache wurde in derselben Session schon einmal falsch geschlossen. Aus zwei Wiki-Szenarien wurde abgeleitet, actions/checkout liefe auf einem Nicht-Node-Image; das kostete sechs fehlgeschlagene Runs (46–51).
Drei Entscheidungen, die beim Anfassen erhalten bleiben sollten:
kb/CONTRACT.md fehlt bewusst. Es liegt unter einem Inhaltsverzeichnis, gehört aber zum Stack (das Version-Gate zählt [^/]+/CONTRACT\.md zu den Stack-Pfaden). Es muss sein CI behalten. Dasselbe gilt für raw/, work/, reports/ — deshalb überall */** statt **.
Kein !**/CONTRACT.md-Negat. Ob Gitea Negationen in Filtermustern unterstützt, ist nicht belegt.
Kein YAML-Anchor, obwohl die Liste doppelt steht (push und pull_request). GitHubs Parser lehnt Anchors ab, für Giteas ist nichts dokumentiert.
Die Muster sind so gewählt, dass ein Irrtum fail-open endet: alles Unvorhergesehene löst CI aus, statt still übersprungen zu werden.
Wie der Beleg aussieht
Nichts zu bauen. Nach dem nächsten reinen Inhalts-Publish (nur kb/, raw/, work/ im Commit — der Normalfall bei einem Ingest):
Für den betreffenden head_sha erscheint kein Run → Filter greift, Issue schließen.
Ein Run erscheint → Filter greift nicht.
Nützlich zum Gegenprüfen: Commit b94166b (nur TODO.md) hat berechtigt CI ausgelöst — TODO.md steht nicht in der Ignore-Liste. Ein Publish, der kb/log.md mitschreibt, ist der eigentliche Testfall.
Falls der Filter nicht greift
Zwei Wege, in dieser Reihenfolge:
Herausfinden, welche Musterform dieser Gitea-Stand versteht. Möglich ist, dass ** anders gebunden wird als bei GitHub; dann tut es eine einfachere Form wie kb/** plus separater Umgang mit den Contract-Dateien.
Wenn die Filterebene nichts taugt: die Entscheidung in den Job verlegen. Ein erster Schritt vergleicht die geänderten Pfade gegen dieselbe Regex, die das Version-Gate schon benutzt — ^(tools/|types/|instructions/|AGENTS\.md$|[^/]+/CONTRACT\.md$) — und beendet den Job früh, wenn nichts davon dabei ist. Kostet einen anlaufenden Container je Publish, ist dafür unabhängig von Giteas Glob-Semantik.
Akzeptanzkriterien
Eine Beobachtung an einem echten Inhalts-Publish, mit head_sha und Ergebnis hier notiert.
Falls der Filter greift: der Befund kommt als Satz in die Kommentarköpfe von ci.yml, damit die nächste Person ihn nicht erneut für eine Annahme hält.
Falls nicht: einer der beiden Wege oben, und der Kommentar in ci.yml wird entsprechend korrigiert.
## Eine Beobachtung, kein Bauauftrag
Am 2026-08-30 hat `.gitea/workflows/ci.yml` ein `paths-ignore` bekommen, damit reine Inhaltsänderungen kein CI mehr auslösen — `publish` fasst bei jedem Ingest `kb/`, `raw/` und `work/` an, und die volle Suite dafür zu fahren ist Lärm.
**Belegt ist das nicht.** Dass Gitea die Muster genauso auswertet wie GitHub, ist eine Annahme. Sie kostet nichts, wenn sie stimmt, und sie ist mit einer einzigen Beobachtung zu prüfen — deshalb dieses Issue statt einer Zeile Code.
Der Grund für die Vorsicht: in genau dieser Sache wurde in derselben Session schon einmal falsch geschlossen. Aus zwei Wiki-Szenarien wurde abgeleitet, `actions/checkout` liefe auf einem Nicht-Node-Image; das kostete sechs fehlgeschlagene Runs (46–51).
## Der aktuelle Stand in `ci.yml`
```yaml
paths-ignore:
- 'kb/*/**'
- 'kb/index.md'
- 'kb/log.md'
- 'kb/provenance.md'
- 'raw/*/**'
- 'work/*/**'
- 'reports/*/**'
```
Drei Entscheidungen, die beim Anfassen erhalten bleiben sollten:
- **`kb/CONTRACT.md` fehlt bewusst.** Es liegt unter einem Inhaltsverzeichnis, gehört aber zum Stack (das Version-Gate zählt `[^/]+/CONTRACT\.md` zu den Stack-Pfaden). Es muss sein CI behalten. Dasselbe gilt für `raw/`, `work/`, `reports/` — deshalb überall `*/**` statt `**`.
- **Kein `!**/CONTRACT.md`-Negat.** Ob Gitea Negationen in Filtermustern unterstützt, ist nicht belegt.
- **Kein YAML-Anchor**, obwohl die Liste doppelt steht (`push` und `pull_request`). GitHubs Parser lehnt Anchors ab, für Giteas ist nichts dokumentiert.
Die Muster sind so gewählt, dass ein Irrtum **fail-open** endet: alles Unvorhergesehene löst CI aus, statt still übersprungen zu werden.
## Wie der Beleg aussieht
Nichts zu bauen. Nach dem nächsten **reinen Inhalts-Publish** (nur `kb/`, `raw/`, `work/` im Commit — der Normalfall bei einem Ingest):
```
actions_run_read: method=list_runs, owner=torben, repo=llm-wiki-test1
```
- Für den betreffenden `head_sha` erscheint **kein** Run → Filter greift, Issue schließen.
- Ein Run erscheint → Filter greift nicht.
Nützlich zum Gegenprüfen: Commit `b94166b` (nur `TODO.md`) hat berechtigt CI ausgelöst — `TODO.md` steht nicht in der Ignore-Liste. Ein Publish, der `kb/log.md` mitschreibt, ist der eigentliche Testfall.
## Falls der Filter nicht greift
Zwei Wege, in dieser Reihenfolge:
1. Herausfinden, **welche** Musterform dieser Gitea-Stand versteht. Möglich ist, dass `**` anders gebunden wird als bei GitHub; dann tut es eine einfachere Form wie `kb/**` plus separater Umgang mit den Contract-Dateien.
2. Wenn die Filterebene nichts taugt: die Entscheidung in den Job verlegen. Ein erster Schritt vergleicht die geänderten Pfade gegen dieselbe Regex, die das Version-Gate schon benutzt — `^(tools/|types/|instructions/|AGENTS\.md$|[^/]+/CONTRACT\.md$)` — und beendet den Job früh, wenn nichts davon dabei ist. Kostet einen anlaufenden Container je Publish, ist dafür unabhängig von Giteas Glob-Semantik.
## Akzeptanzkriterien
- [ ] Eine Beobachtung an einem echten Inhalts-Publish, mit `head_sha` und Ergebnis hier notiert.
- [ ] Falls der Filter greift: der Befund kommt als Satz in die Kommentarköpfe von `ci.yml`, damit die nächste Person ihn nicht erneut für eine Annahme hält.
- [ ] Falls nicht: einer der beiden Wege oben, und der Kommentar in `ci.yml` wird entsprechend korrigiert.
Der Filter greift. Beobachtung liegt vor, nichts zu bauen.
Der Beleg
actions_run_read: list_runs über die letzten vier Commits auf main:
Commit
Inhalt
Runs
6f54c31
Stack (1.1.0)
59
adfa220
Stack (1.1.1)
60, 61
f916376
nur kb/ und raw/
keine
40adbb7
Stack (1.2.0)
62, 63
f916376 ist der gesuchte Testfall — ein reiner Inhalts-Publish aus einem Ingest. Er hat kb/index.md, kb/log.md, kb/provenance.md, acht Seiten unter kb/*/** und eine Datei unter raw/notes/ angefasst, also ausschließlich Pfade aus der Ignore-Liste. Für seinen head_sha erscheint kein Run.
Die Stack-Commits davor und danach zeigen zum Vergleich je zwei Runs (CI plus Release, weil VERSION sich bewegte). Der Unterschied liegt also am Filter und nicht daran, dass zufällig gerade kein Runner lief.
Gitea wertet diese Muster damit so aus wie GitHub. Die drei Entscheidungen aus dem Issue-Text bleiben unberührt: kb/CONTRACT.md fehlt weiterhin absichtlich in der Liste, kein !-Negat, kein YAML-Anchor.
Zweites Akzeptanzkriterium
Der Befund steht jetzt im Kommentarkopf von .gitea/workflows/ci.yml (5426a6e), damit ihn niemand erneut für eine Annahme hält:
# That the filter works is now observed, not assumed (Gitea issue #11): commit
# f916376 published only kb/ and raw/ paths and produced no run at all, while
# the stack commits on either side of it (adfa220, 40adbb7) each produced two.
# Gitea evaluates these patterns the way GitHub does. Do not re-derive this.
Die Wechselwirkung, die das Issue am Ende nennt, löst sich zugunsten von #9 auf: weil der Filter greift, läuft lint --fail-on-error bei einem Inhalts-Publish tatsächlich nicht mehr mit. Der nächtliche Drift-Check verliert damit keinen Teil seiner Begründung, sondern behält den wichtigsten.
**Der Filter greift.** Beobachtung liegt vor, nichts zu bauen.
## Der Beleg
`actions_run_read: list_runs` über die letzten vier Commits auf `main`:
| Commit | Inhalt | Runs |
|---|---|---|
| `6f54c31` | Stack (1.1.0) | 59 |
| `adfa220` | Stack (1.1.1) | 60, 61 |
| **`f916376`** | **nur `kb/` und `raw/`** | **keine** |
| `40adbb7` | Stack (1.2.0) | 62, 63 |
`f916376` ist der gesuchte Testfall — ein reiner Inhalts-Publish aus einem Ingest. Er hat `kb/index.md`, `kb/log.md`, `kb/provenance.md`, acht Seiten unter `kb/*/**` und eine Datei unter `raw/notes/` angefasst, also ausschließlich Pfade aus der Ignore-Liste. Für seinen `head_sha` erscheint kein Run.
Die Stack-Commits davor und danach zeigen zum Vergleich je zwei Runs (CI plus Release, weil `VERSION` sich bewegte). Der Unterschied liegt also am Filter und nicht daran, dass zufällig gerade kein Runner lief.
Gitea wertet diese Muster damit so aus wie GitHub. Die drei Entscheidungen aus dem Issue-Text bleiben unberührt: `kb/CONTRACT.md` fehlt weiterhin absichtlich in der Liste, kein `!`-Negat, kein YAML-Anchor.
## Zweites Akzeptanzkriterium
Der Befund steht jetzt im Kommentarkopf von `.gitea/workflows/ci.yml` (`5426a6e`), damit ihn niemand erneut für eine Annahme hält:
```
# That the filter works is now observed, not assumed (Gitea issue #11): commit
# f916376 published only kb/ and raw/ paths and produced no run at all, while
# the stack commits on either side of it (adfa220, 40adbb7) each produced two.
# Gitea evaluates these patterns the way GitHub does. Do not re-derive this.
```
## Wirkung auf #9
Die Wechselwirkung, die das Issue am Ende nennt, löst sich zugunsten von #9 auf: weil der Filter greift, läuft `lint --fail-on-error` bei einem Inhalts-Publish tatsächlich **nicht** mehr mit. Der nächtliche Drift-Check verliert damit keinen Teil seiner Begründung, sondern behält den wichtigsten.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Eine Beobachtung, kein Bauauftrag
Am 2026-08-30 hat
.gitea/workflows/ci.ymleinpaths-ignorebekommen, damit reine Inhaltsänderungen kein CI mehr auslösen —publishfasst bei jedem Ingestkb/,raw/undwork/an, und die volle Suite dafür zu fahren ist Lärm.Belegt ist das nicht. Dass Gitea die Muster genauso auswertet wie GitHub, ist eine Annahme. Sie kostet nichts, wenn sie stimmt, und sie ist mit einer einzigen Beobachtung zu prüfen — deshalb dieses Issue statt einer Zeile Code.
Der Grund für die Vorsicht: in genau dieser Sache wurde in derselben Session schon einmal falsch geschlossen. Aus zwei Wiki-Szenarien wurde abgeleitet,
actions/checkoutliefe auf einem Nicht-Node-Image; das kostete sechs fehlgeschlagene Runs (46–51).Der aktuelle Stand in
ci.ymlDrei Entscheidungen, die beim Anfassen erhalten bleiben sollten:
kb/CONTRACT.mdfehlt bewusst. Es liegt unter einem Inhaltsverzeichnis, gehört aber zum Stack (das Version-Gate zählt[^/]+/CONTRACT\.mdzu den Stack-Pfaden). Es muss sein CI behalten. Dasselbe gilt fürraw/,work/,reports/— deshalb überall*/**statt**.!**/CONTRACT.md-Negat. Ob Gitea Negationen in Filtermustern unterstützt, ist nicht belegt.pushundpull_request). GitHubs Parser lehnt Anchors ab, für Giteas ist nichts dokumentiert.Die Muster sind so gewählt, dass ein Irrtum fail-open endet: alles Unvorhergesehene löst CI aus, statt still übersprungen zu werden.
Wie der Beleg aussieht
Nichts zu bauen. Nach dem nächsten reinen Inhalts-Publish (nur
kb/,raw/,work/im Commit — der Normalfall bei einem Ingest):head_shaerscheint kein Run → Filter greift, Issue schließen.Nützlich zum Gegenprüfen: Commit
b94166b(nurTODO.md) hat berechtigt CI ausgelöst —TODO.mdsteht nicht in der Ignore-Liste. Ein Publish, derkb/log.mdmitschreibt, ist der eigentliche Testfall.Falls der Filter nicht greift
Zwei Wege, in dieser Reihenfolge:
**anders gebunden wird als bei GitHub; dann tut es eine einfachere Form wiekb/**plus separater Umgang mit den Contract-Dateien.^(tools/|types/|instructions/|AGENTS\.md$|[^/]+/CONTRACT\.md$)— und beendet den Job früh, wenn nichts davon dabei ist. Kostet einen anlaufenden Container je Publish, ist dafür unabhängig von Giteas Glob-Semantik.Akzeptanzkriterien
head_shaund Ergebnis hier notiert.ci.yml, damit die nächste Person ihn nicht erneut für eine Annahme hält.ci.ymlwird entsprechend korrigiert.Der Filter greift. Beobachtung liegt vor, nichts zu bauen.
Der Beleg
actions_run_read: list_runsüber die letzten vier Commits aufmain:6f54c31adfa220f916376kb/undraw/40adbb7f916376ist der gesuchte Testfall — ein reiner Inhalts-Publish aus einem Ingest. Er hatkb/index.md,kb/log.md,kb/provenance.md, acht Seiten unterkb/*/**und eine Datei unterraw/notes/angefasst, also ausschließlich Pfade aus der Ignore-Liste. Für seinenhead_shaerscheint kein Run.Die Stack-Commits davor und danach zeigen zum Vergleich je zwei Runs (CI plus Release, weil
VERSIONsich bewegte). Der Unterschied liegt also am Filter und nicht daran, dass zufällig gerade kein Runner lief.Gitea wertet diese Muster damit so aus wie GitHub. Die drei Entscheidungen aus dem Issue-Text bleiben unberührt:
kb/CONTRACT.mdfehlt weiterhin absichtlich in der Liste, kein!-Negat, kein YAML-Anchor.Zweites Akzeptanzkriterium
Der Befund steht jetzt im Kommentarkopf von
.gitea/workflows/ci.yml(5426a6e), damit ihn niemand erneut für eine Annahme hält:Wirkung auf #9
Die Wechselwirkung, die das Issue am Ende nennt, löst sich zugunsten von #9 auf: weil der Filter greift, läuft
lint --fail-on-errorbei einem Inhalts-Publish tatsächlich nicht mehr mit. Der nächtliche Drift-Check verliert damit keinen Teil seiner Begründung, sondern behält den wichtigsten.