Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 2.5.0 · 2026-07-30 22:50 UTC

TYPO3 / Fluid

Fluid template rendering engine - Standalone version

PHPLGPL-3.0★ 169 Sterne⑂ 107 Forksseit Aug. 2015Auf GitHub ansehen ↗

TYPO3/Fluid erreicht einen Gesundheitsindex von 80 von 100 und liegt damit im Bereich Exzellent. Am stärksten schneidet es bei Engineering Quality (80/100) ab, am schwächsten bei AI Readiness (41/100). Zuletzt vor 46 Tagen aktualisiert. 3 Mitwirkende tragen den Großteil der jüngsten Arbeit.

80
gesamt / 100
Exzellent

Software-Gesundheitsindex

Metriken werden auf einer standardisierten Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr gewichtetes Mittel, kalibriert auf die Verteilung des öffentlichen Registers, sodass die Stufen Perzentilbedeutung tragen; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze Gefährdet von 34.

80
Außergewöhnlich93-100Die Spitzengruppe des Registers (≈ obere 5 %); erfüllt im Wesentlichen alle geprüften Kriterien
Exzellent80-92Durchgehend stark; geringfügige Lücken
Gut65-79Gesund; Lücken sind begrenzt und beherrschbar
Mittel50-64Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Schwach35-49Wesentliche Schwächen in mehreren Bereichen
Gefährdet20-34Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-19Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Der gewichtete Gesamtwert 68 wird auf der veröffentlichten Indexskala auf 80 kalibriert (Register-Kalibrierung 2026-08-02).

Eigentümerschaft

117 Follower23 öffentliche Reposseit Mai 2009

Dieses Repository wird von einer Organisation getragen — geteilte, rechenschaftspflichtige Trägerschaft, die jeden einzelnen Maintainer überdauern kann.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
Packagisttypo3fluid/fluid5.3.1401.469117vor 105 Tagen

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

69Gut · 21 % des Gesamtindex
Wie die Bewertung erfolgt
18/36Push-Aktualität — letzter Push vor 46 Tagen
18/36Commit-Rhythmus — 26/52 Wochen mit Commits
18/18Commit-Volumen — 126 Commits im letzten Jahr
1/10OpenSSF Scorecard: Maintained — 2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
Verwendete Eingangsdaten
commits_last_year126
human_commit_share1
days_since_last_push46
active_weeks_last_year26
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 38 Releases veröffentlicht
27/36Release-Aktualität — letztes Release vor 105 Tagen
27/27Release-Rhythmus — ein Release etwa alle 15,9 Tage
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count38
latest_release_tag4.6.1
releases_from_tagsnein
days_since_latest_release105
mean_days_between_releases15,9
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Signed-Releases. Die verbleibenden Gewichte wurden renormalisiert.

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

70Gut · 17 % des Gesamtindex
Wie die Bewertung erfolgt
36.1/60Stars — 169 Stars
16.9/25Forks — 107 Forks
7.4/15Watcher — 22 Watcher
Verwendete Eingangsdaten
forks107
stars169
watchers22
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (LGPL-3.0)
18/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
readme_badges
has_contributingja
has_issue_templatenein
has_code_of_conductnein
readme_badge_services
has_pull_request_templatenein
Wie die Bewertung erfolgt
74.7/80Downloads pro Monat — 401.469 Downloads/Monat über packagist
13.1/20Abhängige in der Registry — 90 Pakete hängen davon ab
Verwendete Eingangsdaten
packagestypo3fluid/fluid
dependents90
ecosystemspackagist
total_downloads16.388.135
monthly_downloads401.469

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

79Gut · 23 % des Gesamtindex
Wie die Bewertung erfolgt
36/54Bus-Faktor — 3 Beitragende decken die Hälfte aller Commits ab
17.8/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 21 % der Commits
13.5/13.5Breite der Beitragenden — 100 Beitragende
10/10OpenSSF Scorecard: Contributors — project has 37 contributing companies or organizations
Verwendete Eingangsdaten
bus_factor3
contributors_sampled100
top_contributor_share0,211
Wie die Bewertung erfolgt
34.4/42Issue-Lösungsquote — 82 % der Issues geschlossen
26.5/30PR-Annahme — 924/1.046 entschiedene PRs gemergt
0/13Newcomer PR acceptance — kein PR eines Erstbeitragenden in 30 Tagen entschieden
6/15OpenSSF Scorecard: Code-Review — Found 14/30 approved changesets -- score normalized to 4
Verwendete Eingangsdaten
merged_prs924
open_issues59
closed_issues265
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio0,818
closed_unmerged_prs122
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): newcomer_pr_acceptance. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
14.9/25Reichweite des Inhabers — 117 Follower von TYPO3
22.1/25Kontohistorie — 23 öffentliche Repos, Kontoalter ca. 17 Jahre
Verwendete Eingangsdaten
followers117
owner_typeOrganization
is_verified
owner_loginTYPO3
public_repos23
account_age_days6.274

Paketpflege

100Außergewöhnlich
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf packagist
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 105 Tagen
20/20Versionshistorie — 117 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagestypo3fluid/fluid
ecosystemspackagist
any_deprecatednein
min_days_since_publish105

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

80Exzellent · 19 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 2 Workflow(s)
24/24Tests vorhanden
16/16Linter-Konfiguration — .php-cs-fixer.dist.php
0/9.6Pre-Commit-Hooks
6.4/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfigja
has_linter_configja
has_precommit_confignein
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
0/10Wiki
Verwendete Eingangsdaten
topics
has_wikinein
homepage
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

42Schwach · 16 % des Gesamtindex
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — keine Daten
2.5/2.5CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
3/7.5Code-Review — Found 14/30 approved changesets -- score normalized to 4
2.5/2.5Contributors — project has 37 contributing companies or organizations
0/10Dangerous-Workflow — keine Daten
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Lizenz — license file detected
0.8/7.5Maintained — 2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
0/5Packaging — keine Daten
0/5Pinned-Dependencies — keine Daten
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — keine Daten
0/7.5Token-Permissions — keine Daten
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated12
scorecard_versionv5.5.0
checks_inconclusive6
scorecard_aggregate4,2
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): branch_protection, dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Trägt ein bewusst kleines Gewicht (4 %): Agenten-Tooling ist ein echtes Pflegesignal, doch ein Repository ohne jedes Signal kann weiterhin 100/100 erreichen.

41Schwach · 4 % des Gesamtindex
Wie die Bewertung erfolgt
0/45Agentenanweisungen — keine CLAUDE.md / AGENTS.md / Editor-Regeln
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 98 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,98
agent_instruction_files
agent_instruction_max_bytes
Wie die Bewertung erfolgt
0/18Bootstrap mit einem Befehl
22/22Automatisierte Tests
11/11Lint-/Format-Konfiguration — .php-cs-fixer.dist.php
0/11Statische Typprüfung
0/10Reproduzierbare Umgebung
0/10Belegte Agentenpraxis — keine von Agenten verfassten Commits unter den letzten 100
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — keine Daten
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfiles
has_dockerfilenein
typed_languagenein
bootstrap_files
has_devcontainernein
has_linter_configja
typecheck_configs
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Pinned-Dependencies. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
0/45Typprüfbarer Code — PHP ohne Typprüfungs-Konfiguration
55/55Handhabbare Dateigrößen — 0/381 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languagePHP
largest_source_bytes42.311
source_files_sampled381
oversized_source_files0
Wie die Bewertung erfolgt
0/40API-Schema (OpenAPI/GraphQL/proto)
0/20MCP-Server
40/40Lauffähige Beispiele — examples
Verwendete Eingangsdaten
example_dirsexamples
has_mcp_signalnein
api_schema_files

Eckdaten

169GitHub-Sterne
100Mitwirkende
126Commits, letzte 12 Monate
46Tage seit letztem Push
38Releases
3Bus-Faktor
59offene Issues
PackagistPaket-Ökosysteme

Warnungen zur Datenerhebung

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • No resolved dependencies carried a version and a supported ecosystem

Weitere Details

Stern- und Fork-Verlauf 0 ★ / 107 ⇿
0Sterne
107Forks
38Releases

Wann jeder Stern und Fork hinzugefügt wurde, von GitHub erfasst und nach Tagen gruppiert. Das kumulierte Wachstum steht direkt über den täglichen Zugängen, aus denen es besteht, sodass beide gegeneinander lesbar sind: stetiger organischer Zuwachs sieht ganz anders aus als ein abrupter, kurzlebiger Ausschlag. Wo dieser Unterschied messbar ist, wird er als Wachstumsauthentizität ausgewiesen.

02040608010012010752015-092021-012026-04
Major 2Minor 16Patch 20

Jeder Punkt umfasst 10 Tage.

OpenSSF Scorecard 4.2 / 10
4.2Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).Scorecard v5.5.0 · 2026-07-30 22:49 UTC

10Binary-Artifactsno binaries found in the repo
k. A.Branch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
4Code-ReviewFound 14/30 approved changesets -- score normalized to 4
10Contributorsproject has 37 contributing companies or organizations
k. A.Dangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
1Maintained2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
k. A.Packagingpackaging workflow not detected
k. A.Pinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
k. A.Signed-Releasesno releases found
k. A.Token-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
Alle Abhängigkeiten 11

Vollständig aufgelöster Abhängigkeitssatz aus dem GitHub-Abhängigkeitsgraphen: 0 direkte und 11 indirekte (transitive) Pakete. Die transitive Hülle ist vollständig, wenn das Repository eine Lockfile eincheckt.

RegistryPaketVersionBeziehung
Packagistext-jsonindirekt
Packagistext-mbstringindirekt
Packagistext-simplexmlindirekt
Packagistfriendsofphp/php-cs-fixerindirekt
Packagistinfection/infectionindirekt
Packagistphpindirekt
Packagistphpstan/phpstanindirekt
Packagistphpstan/phpstan-phpunitindirekt
Packagistphpunit/phpunitindirekt
Packagistpsr/containerindirekt
Packagistt3docs/fluid-documentation-generatorindirekt
Abhängigkeits-Advisories nicht bewertet

Der Advisory-Abgleich konnte für diesen Bericht nicht ausgeführt werden: No resolved dependencies carried a version and a supported ecosystem

JSON-Rohbericht maschinenlesbar
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 6563,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "PHP": 1428096,
        "HTML": 7971
      },
      "pushed_at": "2026-06-14T12:03:59Z",
      "created_at": "2015-08-13T15:04:55Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-05T12:05:10Z",
      "description": "Fluid template rendering engine - Standalone version",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "LGPL-3.0",
      "default_branch": "main",
      "license_spdx_raw": "LGPL-3.0",
      "primary_language": "PHP",
      "significant_languages": [
        "PHP"
      ]
    },
    "owner": {
      "blog": "https://typo3.org",
      "name": "TYPO3 GitHub Department",
      "type": "Organization",
      "login": "TYPO3",
      "company": null,
      "location": null,
      "followers": 117,
      "avatar_url": "https://avatars.githubusercontent.com/u/88698?v=4",
      "created_at": "2009-05-26T11:58:25Z",
      "is_verified": null,
      "public_repos": 23,
      "account_age_days": 6274
    },
    "license": {
      "state": "standard",
      "spdx_id": "LGPL-3.0",
      "raw_spdx": "LGPL-3.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "4.6.1",
          "kind": "patch",
          "published_at": "2026-04-16T17:27:38Z"
        },
        {
          "tag": "5.3.1",
          "kind": "patch",
          "published_at": "2026-04-16T17:29:34Z"
        },
        {
          "tag": "5.3.0",
          "kind": "minor",
          "published_at": "2026-04-07T18:05:17Z"
        },
        {
          "tag": "4.6.0",
          "kind": "minor",
          "published_at": "2026-03-13T10:32:00Z"
        },
        {
          "tag": "5.2.0",
          "kind": "minor",
          "published_at": "2026-03-11T11:57:45Z"
        },
        {
          "tag": "5.1.1",
          "kind": "patch",
          "published_at": "2026-02-20T13:39:41Z"
        },
        {
          "tag": "5.1.0",
          "kind": "minor",
          "published_at": "2026-02-02T18:27:25Z"
        },
        {
          "tag": "4.5.1",
          "kind": "patch",
          "published_at": "2026-02-04T19:15:03Z"
        },
        {
          "tag": "5.0.3",
          "kind": "patch",
          "published_at": "2025-12-17T14:29:11Z"
        },
        {
          "tag": "5.0.2",
          "kind": "patch",
          "published_at": "2025-11-24T09:29:12Z"
        },
        {
          "tag": "5.0.1",
          "kind": "patch",
          "published_at": "2025-11-18T13:42:50Z"
        },
        {
          "tag": "5.0.0",
          "kind": "major",
          "published_at": "2025-11-16T15:57:27Z"
        },
        {
          "tag": "4.5.0",
          "kind": "minor",
          "published_at": "2025-11-15T14:38:21Z"
        },
        {
          "tag": "4.4.3",
          "kind": "patch",
          "published_at": "2025-08-28T12:05:37Z"
        },
        {
          "tag": "4.4.2",
          "kind": "patch",
          "published_at": "2025-08-06T10:18:04Z"
        },
        {
          "tag": "4.4.1",
          "kind": "patch",
          "published_at": "2025-08-06T10:12:06Z"
        },
        {
          "tag": "4.4.0",
          "kind": "minor",
          "published_at": "2025-07-28T15:14:24Z"
        },
        {
          "tag": "4.3.0",
          "kind": "minor",
          "published_at": "2025-06-24T13:09:34Z"
        },
        {
          "tag": "4.2.0",
          "kind": "minor",
          "published_at": "2025-05-19T11:26:58Z"
        },
        {
          "tag": "4.1.2",
          "kind": "patch",
          "published_at": "2025-04-22T08:33:53Z"
        },
        {
          "tag": "4.1.1",
          "kind": "patch",
          "published_at": "2025-04-17T15:52:16Z"
        },
        {
          "tag": "4.1.0",
          "kind": "minor",
          "published_at": "2025-04-09T16:35:12Z"
        },
        {
          "tag": "4.0.3",
          "kind": "patch",
          "published_at": "2025-01-21T10:02:22Z"
        },
        {
          "tag": "4.0.2",
          "kind": "patch",
          "published_at": "2024-11-18T21:58:55Z"
        },
        {
          "tag": "4.0.1",
          "kind": "patch",
          "published_at": "2024-10-03T09:54:14Z"
        },
        {
          "tag": "4.0.0",
          "kind": "major",
          "published_at": "2024-09-11T08:50:15Z"
        },
        {
          "tag": "2.15.0",
          "kind": "minor",
          "published_at": "2024-09-01T12:06:14Z"
        },
        {
          "tag": "2.14.1",
          "kind": "patch",
          "published_at": "2024-07-31T09:10:37Z"
        },
        {
          "tag": "2.14.0",
          "kind": "minor",
          "published_at": "2024-07-23T16:56:55Z"
        },
        {
          "tag": "2.13.0",
          "kind": "minor",
          "published_at": "2024-07-12T12:53:56Z"
        },
        {
          "tag": "2.12.0",
          "kind": "minor",
          "published_at": "2024-06-26T15:26:12Z"
        },
        {
          "tag": "2.11.0",
          "kind": "minor",
          "published_at": "2024-04-08T07:38:01Z"
        },
        {
          "tag": "2.10.1",
          "kind": "patch",
          "published_at": "2023-12-11T13:16:47Z"
        },
        {
          "tag": "2.10.0",
          "kind": "minor",
          "published_at": "2023-11-27T18:18:08Z"
        },
        {
          "tag": "2.9.3",
          "kind": "patch",
          "published_at": "2023-11-14T16:21:25Z"
        },
        {
          "tag": "2.9.2",
          "kind": "patch",
          "published_at": "2023-06-19T16:54:15Z"
        },
        {
          "tag": "2.9.1",
          "kind": "patch",
          "published_at": "2023-06-08T10:15:50Z"
        },
        {
          "tag": "2.9.0",
          "kind": "minor",
          "published_at": "2023-06-07T14:04:08Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "ef902a525a983f6dde46c37c9f0c1a912da3a7cc",
          "body": "See #1378",
          "is_bot": false,
          "headline": "[TASK] Add test case for stringable component argument (#1379)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-06-14T12:00:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8dca97cbf34875343c73f45eaf319ca13b0f4376",
          "body": null,
          "is_bot": false,
          "headline": "[DOCS] Fix typo in ViewHelper code example (#1376)",
          "author_name": "Jonas Werner",
          "author_login": "svwerder",
          "committed_at": "2026-06-14T11:46:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "28c42c75b171aef196ddbe151b0d1146c290249d",
          "body": "symfony/polyfill-php84 1.33.0->1.34.0 adds RoundingMode stub [1].\n\nround() in PHP < 8.4 allows int as third argument only, and\nhas been extended with php 8.4 to allow int|RoundingMode.\n\nThe 'class_exists()' check in RoundViewHelper now suddenly\nreturns true when latest symfony/polyfill-php84 is load\n[…]\n 8.4 callback chain avoiding RoundingMode enum\naltogether, to avoid the symfony/polyfill-php84 influence.\n\n[1] https://github.com/symfony/polyfill-php84/commit/e4e3f1cc81b8b84a7c596f8817c6d186678e2884",
          "is_bot": false,
          "headline": "[BUGFIX] Fix RoundViewHelper with symfony/polyfill-php84 (#1373)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2026-04-16T17:09:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "66da09ba59c857b58851ba667c0c22d10304dc92",
          "body": "Currently, the Fluid parser is not ready to require the location\neverywhere, so the `@todo` is clarified.",
          "is_bot": false,
          "headline": "[TASK] Clarify todo in parser exception (#1369)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-08T09:09:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1a7aa9759f4cd98f0d598cce73b5ecaec06da26",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] add more test for TemplateParser (#1367)",
          "author_name": "Matthias Vogel",
          "author_login": "Kanti",
          "committed_at": "2026-04-07T17:50:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "96c65692706fefb70108f7bf349f2c748f52c436",
          "body": "When removing the `<html xmlns` declarations from the template, line\nbreaks within the `<html>` tags were also removed. This lead to invalid\nline numbers reported by the template parser.\n\nWith this change, the affected `<html>` tag is replaced with the\nmatching number of newlines.",
          "is_bot": false,
          "headline": "[BUGFIX] Prevent shifting of line numbers (#1358)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-07T17:25:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae092f1e6e3725e47fb9fc0133a32b540de35b25",
          "body": "This patch adds a dedicated CLI command to analyze Fluid templates for\nerrors or deprecations. Templates can be provided either as paths or\nvia STDIN, which enables deeper integration of the fluid CLI tool into\ncode editors and IDEs. Output can be either human-readable or\nmachine-readable as JSON.\n\n\n[…]\ntly, a shortcoming of both the warmup and the analyze command is\nthat no additional global Fluid namespaces can be provided. This needs\nfurther investigation and thus is not addressed with this patch.",
          "is_bot": false,
          "headline": "[FEATURE] CLI command to analyze Fluid templates (#1359)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-07T15:25:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f40ae370eae8c67839bc7f54f70c10674b69189d",
          "body": "Until now, Fluid's exceptions are unaware of the exact location in\nthe original template file that triggered the exception. This patch\nintroduces the necessary data structures and interfaces to accomplish\nthis.\n\nIn a first step, the already available context in the `TemplateParser`\nis now attached t\n[…]\n character numbers currently provided might not\nalways be accurate due to the mechanisms the parser currently uses\ninternally. This change creates the basis to tackle this in a more\nstructured manner.",
          "is_bot": false,
          "headline": "[TASK] Template location aware exceptions (#1366)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-07T15:20:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "100e885396b0e915c501e72fa5e41fcf8b7982f7",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Add infection for mutation coverage (#1323)",
          "author_name": "Matthias Vogel",
          "author_login": "Kanti",
          "committed_at": "2026-04-06T10:19:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "951d00e823b476494fb479b08deab0313e3e9567",
          "body": "Some new ViewHelpers didn't yet cross-reference to the TYPO3\ndocumentation.",
          "is_bot": false,
          "headline": "[DOCS] Add missing cross-references to TYPO3 reference (#1363)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-04T10:48:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c130f9eacdbbdf045087ea156fe6aaa7bd5c6d95",
          "body": "All ViewHelper classes now have a `@see` annotation that points to the\nViewHelper reference documentation. Also, the `@api` annotation has been\nadded where it was missing.",
          "is_bot": false,
          "headline": "[DOCS] Add links to ViewHelper reference (#1362)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-04T10:41:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0b26b4cf180c0f774bb826a056187226dc6dced",
          "body": "`ViewHelperMetaFactory`, which is used both for CLI commands (such as\ncache warmup and schema generation) and for automatic documentation,\npreviously only collected the last instance of a PhpDoc annotation\non a ViewHelper class:\n\n```\n/**\n * @see link1\n * @see link2\n */\n```\n\nIn that example, the meta\n[…]\nh introduces a new flag that allows collecting all instances of\nannotations. When set, `ViewHelperMetadata` always stores arrays instead\nof strings, even if only one instance of the annotation exists.",
          "is_bot": false,
          "headline": "[TASK] Option to collect multiple PhpDoc annotations (#1361)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-03T19:24:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "79e043dec26f6db37ad31c494c9f514380a5138e",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Cover multiple @see annotations with test case (#1360)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-04-03T18:54:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "816016e9176d042a7a6e6da4411dbfc1dddfd27a",
          "body": "…357)",
          "is_bot": false,
          "headline": "[TASK] Add test case for undefined variable in ternary expression (#1…",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-31T14:48:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "954b6cd74b8cddfdef0dede140bb744f0b2b1490",
          "body": "Resolves: #1247",
          "is_bot": false,
          "headline": "[DOCS] Clarify scope of changelog (#1351)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-17T14:22:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dce7467c2bfd4c8fea3edbb7983664bdc6f51882",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Add exception codes to ViewHelper exceptions (#1347)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-11T11:10:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81509636664f1165d4bbacd1750652c911470f84",
          "body": "If the path to the current template file is available, exceptions\nfrom ViewHelpers now also contain this information to make debugging\neasier. To achieve that, all ViewHelper exceptions are wrapped in\nan outer exception which extends the original exception message. This\nnew behavior can be disabled by registering a custom error handler\nin the rendering context.",
          "is_bot": false,
          "headline": "[TASK] Add file path to ViewHelper exception messages (#1346)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-09T17:38:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6d3d9c26b02b3cd8c9715bf477d368c6ddb0897b",
          "body": "Previously, PHP code within the context of a template (most importantly\nViewHelpers, but also internal Fluid code) wasn't aware of the current\ntemplate context. This meant that exceptions couldn't refer to the\ntemplate file where the exception was actually triggered.\n\nThis change introduces the opti\n[…]\n files.\n\nIn follow-up patches, this path can be used to improve exception\nmessages within Fluid. It also allows users to access these values to\nimprove exception messages in their own implementations.",
          "is_bot": false,
          "headline": "[TASK] Provide current template path in renderingContext (#1337)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-09T13:24:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ec2c8702849d5f8fc3764fd13363dedcd61395a4",
          "body": "Several custom exceptions are introduced to indicate invalid ViewHelper\narguments. Their base class `InvalidArgumentException` extends from\n`ViewHelper\\Exception`, which makes it possible to catch them via\nFluid's error handlers. Previously, a lot of ViewHelpers used the\nglobal `\\InvalidArgumentExce\n[…]\n itself and by\nindividual ViewHelpers if a supplied argument value cannot be processed\nby the ViewHelper. We recommend that custom ViewHelpers also use this\nexception if they receive an invalid value.",
          "is_bot": false,
          "headline": "[TASK] Introduce dedicated exceptions for argument validation (#1344)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-09T13:13:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cb15a9d7458d5b25073e77b22343d08770874414",
          "body": "Use consistent syntax for `\\InvalidArgumentException`.",
          "is_bot": false,
          "headline": "[TASK] Unify exception usage in TagBuilder (#1345)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-07T16:35:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ffb251a159b7cc58f80eee6ee2740ecd1ee63b39",
          "body": "Version 4.4.2 is now officially compatible with Fluid 5.x.\n\n> composer req t3docs/fluid-documentation-generator:\"^4.4.2\" --dev",
          "is_bot": false,
          "headline": "[TASK] Update fluid-documentation-generator (#1343)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-07T11:02:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c2fd11f2cb85ace3957220c511c1f25944433305",
          "body": "In an effort to ease debugging, exceptions thrown by the Fluid parser\nnow contain the full path to the original template file. Previously,\nit could be quite hard to discover the affected template because of\nthe cryptic and internal templateIdentifier. Now, the full template\npath is given as an addit\n[…]\n high-level `TemplateView` class are encouraged to make use of the\nnew argument in `TemplateParser->parse()` and\n`TemplateParse->getOrParseAndStoreTemplate()` to provide the full\npath to the template.",
          "is_bot": false,
          "headline": "[TASK] Include template path in parser exceptions (#1336)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-07T10:32:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aadb6ce7869f2b71464cb8aa2054908c440fb41d",
          "body": "* Enable a skipped test that seems to work fine now.\n* $this->creatMock() vs. self::createStub(): Mocks that declare\n  no expectations are stubs. phpunit is now more picky with\n  this, which is good to clarify things. The change switches\n  many cases to stubs. Places that mock system-under-test to t\n[…]\n fixture classes extending the abstract and new().\n* expects(self::any()) is deprecated. We switch to once() and\n  friends or remove some cases entirely since some of course\n  turn out to be obsolete.",
          "is_bot": false,
          "headline": "[TASK] Have notice and deprecation free phpunit v13 (#1342)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2026-03-06T22:42:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "80ebac94351c9c7c12ac5eb4e1f5ea0ecaeb1c0f",
          "body": "Do not randomize test order in phpunit.xml since that is\nannoying when actively working with the test code base. Have\na dedicated workflow job instead to add a randomized run.\n\nRaise phpunit.xsd to oldest common denominator and remove\nresolveDependencies attribute which is identical to the\ndefault value.",
          "is_bot": false,
          "headline": "[TASK] Order tests by default by default (#1341)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2026-03-06T21:23:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b305e7eda33edc631e1c99dbb8c855364e958b51",
          "body": "Allows phpunit v13 when PHP version fits.\n\n> composer req --dev friendsofphp/php-cs-fixer:^3.94.2\n> composer req --dev phpstan/phpstan:^2.1.40\n> composer req --dev phpstan/phpstan-phpunit:^2.0.16\n> composer req --dev phpunit/phpunit:\"^11.5.55 || ^12.5.14 || ^13.0.5\"\n> composer req --dev psr/container:^2.0.2\n> composer req --dev t3docs/fluid-documentation-generator:^4.4.1",
          "is_bot": false,
          "headline": "[TASK] Bump dev dependencies (#1338)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2026-03-06T19:53:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb31cfe066f9807f818d054f67c74e10304cc31e",
          "body": "Resolves: #1244",
          "is_bot": false,
          "headline": "[DOCS] Add chapter about variable escaping (#1332)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-04T19:00:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "526092c411173c7183aebc1d17a229b8f84a9c78",
          "body": "This change aims to simplify debugging by providing improved exception\nmessages in cases where a template file cannot be resolved.\n\nPreviously, these exceptions lacked important context (e. g. which\ntype of template [template, partial, layout] is missing). Also,\nthe messages still suggested to the u\n[…]\nent exception classes and messages are now\nused for templates, partials and layouts, which helps during debugging.\nAlso, the exception messages have been streamlined, which also extends\nto components.",
          "is_bot": false,
          "headline": "[FEATURE] Clarify exceptions for missing templates (#1335)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-04T11:34:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "66183879e33830822f372801e4e2d83db1a0ae7d",
          "body": "Within `TemplatePaths`, a `InvalidTemplateResourceException` is thrown\nif no suitable template can be found based on the provided paths,\ncontroller and action. Previously, this has been part of\n`getTemplateSource()`, right before the template file is read.\n\nThis patch moves the validation one level \n[…]\nluid 6. Otherwise this change would have been breaking.\n\nIn a follow-up patch, this will be improved even further by providing\nthe user with a list of all possible template paths that have been\ntried.",
          "is_bot": false,
          "headline": "[TASK] Move around template file validation code (#1334)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-03T18:31:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "70f6eecafe7372ba762260eb7b4d7db799d880f9",
          "body": "A new interface `ComponentListProviderInterface` is added to Fluid,\nwhich allows component collections to not only resolve one specific\ncomponent, but also the reverse: When implemented,\n`getAvailableComponents()` returns a list of all components that are\npart of the collection. This can be useful f\n[…]\nat matches their custom folder structure. This will change in Fluid 6,\nwhere it will be assumed that users define both `resolveTemplateName()`\nand `getAvailableComponents()` consistently if necessary.",
          "is_bot": false,
          "headline": "[FEATURE] API to generate component listings (#1318)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-03-03T14:30:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b3f8a31faabd386a2911101fe19da0a389689796",
          "body": "The patch extends Fluid's own XSD schema generator classes to\nbe able to work with component definitions. This allows frameworks\nthat use Fluid components and are aware of all component collections\n(e. g. via DI) to generate XSD schema files for components.",
          "is_bot": false,
          "headline": "[TASK] Make ViewHelperMetadata compatible with components (#1331)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-26T16:06:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4e84db6f2f7824e81aa7c2ea7c5be9a33556c7b0",
          "body": "An option is added to `TemplateFinder` and `TemplatePaths` to get all\navailable templates without their file extension. This enables easier\nprocessing later, e. g. in the context of component collections.",
          "is_bot": false,
          "headline": "[TASK] Option to get available templates without extension (#1330)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-26T15:55:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c61416b4573f6b8d1acca0d01f5ebfe3c07e4087",
          "body": "This patch introduces new data structures that represent annotations\nfor ViewHelpers/Components or their individual arguments. The purpose\nis to be able to attach arbitrary information to definitions of\nViewHelpers/Components or arguments, either to pass them along as-is\nor to react to them within F\n[…]\nwritten to Fluid's template\ncache files, each annotation needs to implement the `compile()`\nmethod, which returns the PHP code that re-creates the annotation object\nwhen a template is read from cache.",
          "is_bot": false,
          "headline": "[FEATURE] Annotations API (#1314)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-24T11:21:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d563f3b169593548b01f45447f74e7cf454a268",
          "body": "Due to an oversight, each component call from a template created its\nown instance of the responsible ViewHelperResolverDelegate. This is\nnot necessary, since resolver delegates are meant to be sharable.\n\nThis patch introduces the new `getResolverDelegate()` method, which\ncentralizes the already exis\n[…]\nrDelegateInstanceFromClassName()` are migrated to the\nnew method.\n\nNote that the performance impact wasn't relevant in TYPO3, since the\nunderlying DI implementation already shared the service objects.",
          "is_bot": false,
          "headline": "[TASK] Share resolver delegates in cached templates (#1319)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-20T13:34:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d7b9920cc8695aed5c09e5e186beabb8cb8b033",
          "body": "… (#1305)\n\nWith #1288, the `UnsafeHTML` interface has been introduced, which prevents\nFluid's default output escaping if implemented by an object. In other Fluid\ninternals, objects that implement that interface are already stringified in\ncases where it increases compatibility with normal strings.\n\nT\n[…]\ntext (variables are not auto-converted if they should be compared\nstrictly).\n\nThis is a general enhancement and should not have consequences to loose\ncomparisons, which are commonly used in templates.",
          "is_bot": false,
          "headline": "[BUGFIX] Enhance boolean evaluation to check for UnsafeHTML instances…",
          "author_name": "Matthias Vogel",
          "author_login": "Kanti",
          "committed_at": "2026-02-20T13:32:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3f7634a5835a38a677477926549bc5b0f7292b1d",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Run phpunit tests in random order (#1322)",
          "author_name": "Matthias Vogel",
          "author_login": "Kanti",
          "committed_at": "2026-02-20T10:51:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e4d7a7ade20427dcc6eb3dee026209906b4d9bb",
          "body": "Fluid's `BooleanParser` attempts to cover a specific edge case: If\ntwo objects should be compared, according to the code it should always\nbe a strict comparison. However, the condition that should have\naccomplished this depends on the variable content during the first\nrun. If a template is compiled \n[…]\nither uncached or cached\ntemplates would be correct, but never both. The new version delivers\nthe same results as cached templates before this change, so it should\nbe in line with real-world projects.",
          "is_bot": false,
          "headline": "[BUGFIX] Address inconsistencies in object comparisons (#1320)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-20T10:41:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "65e961e89d6ddefb945118b35b424629014760c8",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Improve naming of metadata factory tests (#1315)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-18T17:40:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de298aea884f1a88d029fbdbcff6d1dc33d049a6",
          "body": "To simplify the code for further changes, constructor property\npromotion is now used in `ArgumentDefinition`. Also, compilation\nfor Fluid cache file is now handled within `ArgumentDefinition`.\nSelf-explaining comments are removed.",
          "is_bot": false,
          "headline": "[TASK] Consolidate ArgumentDefinition implementation (#1313)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-17T17:41:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc132cfff67f98e9311a438efcdd064d34fdac13",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Improve return type annotation for VH creation (#1310)",
          "author_name": "Elias Häußler",
          "author_login": "eliashaeussler",
          "committed_at": "2026-02-17T15:01:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c16e48bf8043b40f7517f486830376b8067d3a7b",
          "body": null,
          "is_bot": false,
          "headline": "[DOCS] Document reserved variables in Fluid 5 (#1309)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-14T11:22:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83779845a3398e3c9d0edd6a44c358b8bc8acf80",
          "body": null,
          "is_bot": false,
          "headline": "[DOCS] Document version for boolean attributes (#1306)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-14T11:17:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf489f651e121d963051199c96055f1d822b3cdd",
          "body": "… without being escaped (#1288)\n\nFluid escapes variable output by default to prevent XSS. In some cases,\nhowever, values originate from a trusted/sanitized source (e.g. HTML\ngenerated from a sanitizer, CMS RTE output, a Markdown renderer with\na strict allow-list, …) and should be rendered as HTML wi\n[…]\nion unwraps `UnsafeHTML` to a string first,\n  so empty HTML values behave like empty strings in conditions\n  (e.g. `{content}` is false when it’s `''`).\n\nTests/examples have been adjusted accordingly.",
          "is_bot": false,
          "headline": "[FEATURE] UnsafeHTML interface to allow passing variables to template…",
          "author_name": "Matthias Vogel",
          "author_login": "Kanti",
          "committed_at": "2026-02-02T18:23:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5badb37e9b00f8ffd45b36a40d5aaa67591b9f08",
          "body": "`null` can safely be converted to an empty string, so it's fine to\nallow it as a base string for string replacement.\n\nResolves: #1279",
          "is_bot": false,
          "headline": "[BUGFIX] Allow null value as input for f:replace (#1282)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-02T18:12:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee0790808bc83017ff2d745858a138748365d7ec",
          "body": "Since Fluid 5, ViewHelpers can assume that the types of their arguments\nare properly enforced by Fluid: Either by automatic casting for simple\ntypes or by throwing an exception. However, this is currently not the\ncase for `string`: Here, `StrictArgumentProcessor` still accepts\nstringable objects as \n[…]\nter:\n\n```\n$this->registerArgument('value', 'string|int|float|Stringable', '');\n```\n\nSince one specified goal of Fluid 5 is type safety within ViewHelpers,\nthis is considered a bugfix.\n\nResolves: #1099",
          "is_bot": false,
          "headline": "[BUGFIX] Cast stringable objects early for ViewHelper arguments (#1290)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-02T18:11:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5f1366e5c1fa8356c81e775b3f68eda3024d7566",
          "body": "Previously, duplicate template/partial/layout root paths were removed\nfrom the array to avoid potential duplicate lookups. However, this\nprevented reordering of those paths by adding one path multiple times\nto the same array, which would ideally increase its priority over\nother paths.\n\nThis patch re\n[…]\nbackported to Fluid 4. However,\nthis is highly unlikely, which is why this is not considered a\nbreaking change in Fluid 5.\n\nThis patch also clarifies comments to be able to simplify code with\nFluid 6.",
          "is_bot": false,
          "headline": "[BUGFIX] Don't remove path duplicates to allow reordering (#1298)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-02-02T18:10:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0456eb4b5aa7f1a5ae5a8425cac508ea8c2cd374",
          "body": "…296)\n\nResolves: #1284",
          "is_bot": false,
          "headline": "[TASK] Improve exception message for invalid ViewHelper arguments (#1…",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-01-26T15:40:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "33c5a37b788b0b4cc308f9857dfdb058fb110ca0",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Apply new cgl rules (#1294)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-01-26T15:36:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ed03cf9ad7ecc5603f43e1f2bdbe7dadbf5171d7",
          "body": "Documentation is added for the new `*.fluid.*` file extension and the\nassociated fallback chain. File references throughout the documentation\nare adjusted to always use the new extension. Also, links to moved files\nare fixed.\n\nResolves: #1289",
          "is_bot": false,
          "headline": "[DOCS] Fluid file extension (#1292)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-01-21T17:05:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c1454339cf707a9b4d6920bc602e4423145a339",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Add stringable tests for StrictArgumentProcessor (#1291)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-01-21T14:28:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2aa9f1d4063d8c9bff7a90927413c148739e39e0",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Add test case for template name fallbacks (#1287)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2026-01-14T17:40:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "993b77a2a7d9392e024b9980c8462e40c125c9cf",
          "body": "Fluid 5 disallows variable names that start with an underscore. While\nthis is already enforced in `StandardVariableProvider` for setting\nsuch variables, this change now also triggers an exception if a\nvariable with an invalid name is accessed.\n\nThis is probably a temporary change to be removed with Fluid 6. For now,\nit allows the `TemplateValidator`, which is used during template\nwarmup, to discover this issue during parse time, and to let users\nknow about affected templates.\n\nResolves: #1263",
          "is_bot": false,
          "headline": "[TASK] Allow TemplateValidator to discover underscore variables (#1283)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-12-16T17:26:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae55cbdb8814e031908c9b34bc4a1a2f4dc8eaac",
          "body": "Since a Fluid namespace does not necesarily refer to an existing class\n(e. g. \"TYPO3Fluid\\Fluid\\ViewHelpers\" is not a valid PHP class), the\nPHPDoc annotation is removed from `getNamespace()`.\n\nThis enables comparing namespace strings with the result of\n`getNamespace()` without phpstan issues (e. g. \"[...] will always\nevaluate to false\").",
          "is_bot": false,
          "headline": "[TASK] Loosen PHPDoc type for Fluid namespaces (#1280)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-12-15T19:47:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc82facd9838d6c645de4545dd220ef169240359",
          "body": "Due to the way the structure of components is extracted from template\nfiles, it was previously not possible to use a PHP constant or enum\ncase as default value for a component argument.\n\nThis patch adds the `<f:constant>` ViewHelper to the list of allowed\nViewHelpers for that pre-parsing step, which makes it now possible\nto use `<f:constant>` from within `<f:argument>`.",
          "is_bot": false,
          "headline": "[BUGFIX] Allow constants and enum cases as argument default (#1272)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-12-10T14:49:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1aa517a61646029b4e1029e2ff76aa0109b75c9d",
          "body": "…(#1274)",
          "is_bot": false,
          "headline": "[DOCS] Document `<f:argument>` does not work when rendering sections …",
          "author_name": "Daniel Corn",
          "author_login": "cundd",
          "committed_at": "2025-12-10T11:42:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aca11557d820b35536455253520ba596b35f1a38",
          "body": "The existing `BackedEnumExample` is renamed to `StringBackedEnumExample`\nto also cover int-backed enums with `IntBackedEnumExample`. The\nexisting tests for `<f:constant>` are extended to cover all enum\nvariants.",
          "is_bot": false,
          "headline": "[TASK] Extend enum test coverage (#1269)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-12-07T16:35:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03ef568664db2802bbc60e5f1ca81f20340d56f7",
          "body": "Due to refactorings in the cache layer of Fluid, which were necessary\nto make cache warmup feasible, the cache identifiers have changed\nwith Fluid 5. This currently leads to parse errors when a template\nname starts with a number because the associated cache file and most\nimportantly the generated PH\n[…]\n \"template_\" to cache\nidentifiers. Other special characters are already dealt with in\n`TemplateCompiler`, so we only need to ensure that the identifier\nstarts with an alpha-character.\n\nResolves: #1266",
          "is_bot": false,
          "headline": "[BUGFIX] Ensure valid name for cache classes (#1268)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-24T09:27:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "18048d9e26375c114cc1a59d47f0ceef186194b2",
          "body": "Change AbstractViewHelper declaration\n\n`abstract public function render(): mixed;`\n\nback to\n\n`abstract public function render();`\n\nToo much fallout with too little benefit.\n\nRelated: #1219",
          "is_bot": false,
          "headline": "[TASK] Avoid mixed return in AbstractViewHelper->render() (#1264)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2025-11-18T13:35:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee5b89dea88415860da6f7acf2d5f0ca50fcf53f",
          "body": "Previous Fluid versions already had a CLI command which could be used\nto warmup the cache for template files, e. g. during deployment.\nHowever, the previous implementation required a lot of additional\ncontext and mixed parsing/compilation and rendering state. The\nprevious warmup implementation has a\n[…]\nhe underlying API,\nnamely `TemplateFinder` for finding template files and\n`TemplateValidator`, which produces a validation report for each\ntemplate, are marked as `@internal` for now.\n\nResolves: #1103",
          "is_bot": false,
          "headline": "[FEATURE] Overhauled cache warmup command (#1224)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-13T11:05:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "31a451f44298bfbcba4ee42eba8a26095cbb2184",
          "body": "As a follow-up to #1258, all example templates are now using the new\nFluid file extension. In all places where the file extension isn't\nspecified explicitly, the fallback mechanism allows us to just rename\nthe templates without any other changes. However, for\n`setTemplatePathAndFilename()`, an explicit path is given, which\nneeds to be adjusted. Also, if the file extension is specified\nexplicitly when rendering a partial, this also needs to be adjusted\nmanually.",
          "is_bot": false,
          "headline": "[TASK] Use Fluid file extension in examples (#1261)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-11T17:16:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "42a07b76a351266d73852bd5475366aa6adfad38",
          "body": "Historically, Fluid has always used generic file extensions for\ntemplate files, such as `.html`, `.txt` or `.xml`. While this\nprovides IDE integration out-of-the-box, it makes it hard to\ndistinguish files that are interpreted by Fluid and others that\nare just text or html files.\n\nThis patch introduc\n[…]\nd templates, it also allows us to create better IDE\nintegrations in the future. Also, it enables us to scan a whole project\nfor Fluid templates, which makes cache warmup and linting tasks\nconfig-free.",
          "is_bot": false,
          "headline": "[FEATURE] Introduce optional .fluid.* file extension (#1258)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-11T16:52:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a83414309826673766bde38daf1f79f1bbef09cd",
          "body": "This patch adds a new `<f:contains>` ViewHelper to Fluid, which allows\nto check if a provided string or array contains a specified value.\nDepending on the input, this mimicks PHP's `in_array()` or `str_contains()`.\n\nThe initial version of this patch is intended to be backported to Fluid 4.\nIn a follow-up, the code and argument types can be improved for Fluid 5.\n\nResolves: #1125",
          "is_bot": false,
          "headline": "[FEATURE] <f:contains> ViewHelper (#1193)",
          "author_name": "Michael Staatz",
          "author_login": "staatzstreich",
          "committed_at": "2025-11-10T13:50:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "91f835138d52d3fc6de51c2f5d6611393feb50d8",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Cleanup example code (#1260)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-08T15:32:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f926ce229c58f0f13fb0000e43bd456c33641afd",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Test real-world setup in TemplatePathsTest (#1259)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-08T13:13:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a675bcb65e8a5244cdf1b3c2e3543e0590954db",
          "body": "All path handling and resolving in Fluid is performed by the\n`TemplatePaths` class, which is attached to the current rendering\ncontext. While this class has already been simplified in the past,\nthe actual path resolving has largely stayed the same because it\nincludes edge cases that were moved over \n[…]\not be found.\n\nIn a follow-up patch, this will also allow us to introduce a custom\nfile extension for Fluid templates, which will then also be part of that\nfallback chain.\n\nResolves: #371\nRelated: #938",
          "is_bot": false,
          "headline": "[FEATURE] Overhaul template path resolving (#1243)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-04T16:07:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f5377f0fa84adf61bad4fbf222f08cd06b3e8743",
          "body": "Fluid has so far removed any CDATA sections from templates. This has\nbeen introduced with 978071f, without any clear indication why this\nwas done. This means that Fluid templates either expect CDATA sections\nto be removed or avoid them altogether since they don't do anything.\nThis gives us the oppor\n[…]\n,\ninstead three curly braces `{{{ }}}` can be used to access Fluid\nvariables, call ViewHelpers and use expressions. The CDATA keyword\nitself is removed from the output.\n\nResolves: #1012\nResolves: #808",
          "is_bot": false,
          "headline": "[!!!][FEATURE] Alternative Fluid syntax in CDATA (#1246)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-04T16:04:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a8cb13977042aee22f2ccdc04417b0532b2a3d44",
          "body": "Quite early in the development of Fluid, the decision has been made\nto remove `<![CDATA[...]]>` sections from templates. The exact reason\nremains unclear, as 978071f8f5484e01882d7c4c6d740064f22d51ef only\nmentions that this has been added, but not why:\n\n> - replace cdata sections with empty lines (in\n[…]\n is now\ndeprecated: From Fluid 5 onwards, CDATA sections will just remain in\nFluid templates untouched. Until then, a deprecation will be emitted\nto let users know that this will change in the future.",
          "is_bot": false,
          "headline": "[TASK] Deprecate CDATA removal from templates (#1231)",
          "author_name": "Michael Staatz",
          "author_login": "staatzstreich",
          "committed_at": "2025-11-03T18:29:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b09cf355b072aa56e96a3f5dc042445d048db02b",
          "body": "In preparation for the possible introduction of more internal\nconstants in Fluid, custom variable names that start with an\nunderscore are no longer allowed.\n\nFor Fluid 4, a deprecation will be introduced in a follow-up patch\nto prepare template authors for the upcoming change.\n\nRelated: #1166\nRelated: #1041",
          "is_bot": false,
          "headline": "[!!!][TASK] Disallow variables that start with a \"_\" (#1225)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-03T18:25:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "640c57cff9f046b59fa530e185ced5200057777e",
          "body": "In preparation for the possible introduction of more internal\nconstants in Fluid, custom variable names that start with an\nunderscore will no longer be allowed.\n\nFor Fluid v4, a deprecation is emitted. In a follow-up for Fluid v5,\nthe deprecation will be replaced with an exception.\n\nRelated: #1166\nRelated: #1041",
          "is_bot": false,
          "headline": "[TASK] Deprecate variables that start with a \"_\" (#1253)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-11-03T18:19:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8101bb04a438493ff5787cbb5a9f76b9cf817f93",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Remove a duplicate header comment (#1255)",
          "author_name": "Elias Häußler",
          "author_login": "eliashaeussler",
          "committed_at": "2025-11-01T11:11:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd53a073ef487af0d000c94997826270f58a2bea",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Correct return value comment in `f:max` VH (#1254)",
          "author_name": "Elias Häußler",
          "author_login": "eliashaeussler",
          "committed_at": "2025-11-01T11:09:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecdcabb67d31b9de164b240192146a289316d666",
          "body": "MinViewHelper and MaxViewHelper\n\nExamples\n```\n<f:min value=\"{0: '1', 1: '2', 2: '3'}\" />\n<!-- 1 -->\n\n<f:max value=\"{0: '1', 1: '2', 2: '3'}\" />\n<!-- 3 -->\n```",
          "is_bot": false,
          "headline": "[FEATURE] Add f:min and f:max ViewHelpers (#1245)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-10-31T16:09:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "58bd87b3dea0ee1c88550f1d350dce4f3c2acaaf",
          "body": null,
          "is_bot": false,
          "headline": "[DOCS] Warn about using f:form.<something> in Components (#1250)",
          "author_name": "Lina Wolf",
          "author_login": "linawolf",
          "committed_at": "2025-10-15T12:56:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ffc4a8eb80653acf85ce2186a685772d92d6bab4",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Increase test coverage for template path resolving (#1241)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-21T16:38:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4dc0cc54007d0867ad0bc57578b5c0859ff0966b",
          "body": "With the `LenientArgumentProcessor`, which was previously used for\nViewHelper arguments, it was already possible to specify multiple\ntypes for an argument. However, that definition was silently ignored\nduring validation (see `ImageViewHelper` in TYPO3 Core).\n\nWith the introduction of the `StrictArgu\n[…]\nine the desired type automatically. Thus,\nif union types are used, all possible types need to be specified\nexplicitly and need to be dealt manually in the ViewHelper's\nimplementation.\n\nResolves: #1130",
          "is_bot": false,
          "headline": "[FEATURE] Support union types for ViewHelper and component API (#1226)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-16T14:46:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4d31333ee61944c97bd4faef0fb018b450d2470",
          "body": "Type declarations are added to all ViewHelper methods as well as\nall properties that are considered internal and are most likely not\nredefined directly by a ViewHelper implementation. Three properties\nare left out intentionally, since they are currently part of the\nViewHelper API:\n\n* `AbstractViewHe\n[…]\nHelper::$escapeChildren`\n* `AbstractTagBasedViewHelper::$tagName`\n\nAdding type declarations to those properties would make it impossible\nto create ViewHelpers that are compatible with Fluid v4 and v5.",
          "is_bot": false,
          "headline": "[!!!][TASK] Add type declarations to ViewHelper classes (#1219)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-16T13:39:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ccff4a587599899ee8a43ce7cc9ab5117c9387db",
          "body": "RoundViewHelper, CeilViewHelper and FloorViewHelper provide three different ways of rounding to Fluid template.\n\nExamples\n\n```\n<f:round value=\"123.456\" /> <!-- Outputs 123.46 -->\n<f:ceil value=\"123.456\" /> <!-- Outputs 124 -->\n<f:floor value=\"123.456\" /> <!-- Outputs 123 -->\n```\n\nThis continues the work of Pullrequest:\n[[FEATURE] Add f:round, f:ceil and f:floor ViewHelpers #868](https://github.com/TYPO3/Fluid/pull/868)",
          "is_bot": false,
          "headline": "[FEATURE] Add f:round, f:ceil and f:floor ViewHelpers (#1220)",
          "author_name": "Michael Staatz",
          "author_login": "staatzstreich",
          "committed_at": "2025-09-16T13:17:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "856b0811ed113e5b9bf30d4f28d30099155fed92",
          "body": "Because of deprecations and other prerequisites in v4, we are now\nable to accumulate all ViewHelper-related validation code in\n`ViewHelperInvoker`.",
          "is_bot": false,
          "headline": "[!!!][TASK] Accumulate validation code in ViewHelperInvoker (#1216)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-16T12:51:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3205b57fa86c3f045bc0ab7031b106fc3876910c",
          "body": "For compatibility reasons, Fluid interpreted tag attributes that were set\nto `null` as empty strings in `TagBuilder`, which resulted in an empty\ntag attribute (`data-attribute=\"\"`). With this patch, that behavior is\nchanged: `null` values now lead to the attribute being omitted from the\ntag, just like `false` does.\n\nBefore:\n\n```xml\n<my:tagBased data-attribute=\"{null}\" />\nResult: <div data-attribute=\"\"></div>\n```\n\nAfter:\n\n```xml\n<my:tagBased data-attribute=\"{null}\" />\nResult: <div></div>\n```",
          "is_bot": false,
          "headline": "[!!!][TASK] Remove tag attributes if set to null (#1233)",
          "author_name": "Bill.大狗",
          "author_login": "billdagou",
          "committed_at": "2025-09-16T12:14:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3c0131560abf04280f9146f43c23eb6789219e6d",
          "body": "This is a follow-up from #1236. The internal changes are now reflected\nin the public method signatures as well.",
          "is_bot": false,
          "headline": "[!!!][TASK] Don't allow null as template identifier in parser (#1239)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-13T13:24:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90f2f03397bfa1107c09f516388ff16c54c3eb09",
          "body": "This patch addresses various deprecations that were introduced in\nrecent dev versions of PHP 8.5. All changes should be non-breaking\nand thus can be backported to Fluid v4.\n\n* `TemplateParser` now uses empty strings instead of `null` as array\n  key for runtime cache. Public API will be adjusted in v\n[…]\n\n* GroupedForViewHelper ensures to use an empty string instead of\n  `null` for array key to avoid the deprecation and considered\n  non-breaking because php converted null-index to `\"\"` index\n  anyway.",
          "is_bot": false,
          "headline": "[TASK] Address deprecations introduced by PHP 8.5 (#1236)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-09-13T12:14:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "83a314972330ee876c2028c0cb104333908a8172",
          "body": "The method is never called or referenced. Also, there don't\nseem to be any usages of 3rd-party packages.",
          "is_bot": false,
          "headline": "[TASK] Remove unused resetState() method (#1217)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-22T10:03:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "060b4787f1dbcac42a642e7196a6b8333199ca41",
          "body": "If a component or ViewHelper argument is not required and is not\nsupplied in the ViewHelper call, Fluid takes care of filling in the\ndefault value. But this also happens if the argument is supplied and\nis set to `NULL`. This usually happens if an undefined variable is\nprovided to the ViewHelper. For\n[…]\ntrictArgumentProcessor` prevents the\nfallback from happening if the argument is supplied, but with `NULL`\nas value. This patch adjusts the `StrictArgumentProcessor` to also\npass `NULL` values through.",
          "is_bot": false,
          "headline": "[BUGFIX] Allow NULL for optional arguments with default (#1221)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-22T09:16:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e154ee806eea1579878ee278947502adc87ec5ca",
          "body": "This is a clean-up after #1173.",
          "is_bot": false,
          "headline": "[TASK] Remove obsolete $tagAttributes property (#1218)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-20T18:12:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21ac61973dd0091efc45ab3067951a412aae2dca",
          "body": "This patch introduces new API methods on the RenderingContext to\nobtain and replace Fluid's argument processor implementation. By\ndefault, the StrictArgumentProcessor is used, but the\nArgumentProcessorInterface exists to provide an alternative\nimplementation. However, it might be a good idea wrap cu\n[…]\ne StrictArgumentProcessor by using\nthe decorator design pattern to ensure valid input types\nto ViewHelpers and components.\n\nThis is a breaking feature because of the interface change.\n\nResolves: #1105",
          "is_bot": false,
          "headline": "[!!!][FEATURE] Ability to replace argument processor (#1204)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-20T17:11:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7fd755e367f525f309bff2833b3e51dae6e306e5",
          "body": "Since Fluid v5 will ship with a new, improved implementation of\ncache warmup, the old code related to warmup has been deprecated\nin Fluid v4 and is now removed. The new cache warmup feature is\nadded in a follow-up patch.",
          "is_bot": false,
          "headline": "[!!!][TASK] Remove old cache warmup implementation (#1209)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-20T16:47:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4218a45f83c8dafdaabc0e1db2e30388bb6b746",
          "body": "…#1189)\" (#1214)\n\nThis reverts commit 54cddfd80801ae100af0b33c6671d801b9d3847a.\n\nreact/promise 3.3.0 release fixed the issue.",
          "is_bot": false,
          "headline": "Revert \"[TASK] Apply react/promise patch to fix PHP 8.5 deprecation (…",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2025-08-20T12:45:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e36d4c2651eab8af6a6dfb265626555c4ed276d7",
          "body": "Fluid v4.2.0 introduced a new API to process component and ViewHelper\narguments (see #1062). To avoid breaking changes in Fluid v4 with\nhow ViewHelpers handle their arguments, a `LenientArgumentProcessor`\nhas been introduced which has been used exclusively for ViewHelpers.\nComponents have used the n\n[…]\n required, integer given\").\n\nThere might be consequences for custom ViewHelpers, however in\nmost cases this change will make a lot of custom validation code\nthat was necessary until Fluid v5 obsolete.",
          "is_bot": false,
          "headline": "[!!!][TASK] Strict argument processing for ViewHelpers (#1194)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-18T14:16:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8271df914934968442f96cd47e4353b33e0d1dd1",
          "body": "The current implementation of `AbstractViewHelper` includes\nFluid's validation logic for ViewHelper arguments in the public\nmethod `validateArguments()`. This method is called internally\nby each ViewHelper in `initializeArgumentsAndRender()`, just\nbefore initialization and rendering of the ViewHelpe\n[…]\nstom validation steps after the internal\nvalidation has been completed successfully. This should allow\nusers that previously overrode `validateArguments()` to\nmove their custom logic to the new event.",
          "is_bot": false,
          "headline": "[FEATURE] Introduce ViewHelperArgumentsValidated event (#1200) (#1213)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-18T14:11:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "65688c56d6a5f23d83eb4d7b77e5d7288b945ee3",
          "body": "In order to implement a reasonable cache warmup, the template\ncache needs to be independent of the context where the template\nwill be used later in the project. For cache files, this means that\nthey cannot limit how a template will be used later on\n(partial, layout or template).\n\nThis patch removes the context-dependent prefixes for cache\nfile names to achieve this.",
          "is_bot": false,
          "headline": "[TASK] Avoid context-dependent prefixes for cache files (#1205)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-18T14:03:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc9d2c77010e43d74210bba59d9778229d73f0ee",
          "body": "Use alias offsetSet() instead: \"The SplObjectStorage::contains(),\nSplObjectStorage::attach(), and SplObjectStorage::detach() methods\nhave been deprecated in favour of SplObjectStorage::offsetExists(),\nSplObjectStorage::offsetSet(), and SplObjectStorage::offsetUnset()\nrespectively.\"\n\nReleases: main, 4.5",
          "is_bot": false,
          "headline": "[TASK] Avoid PHP 8.5 deprecation \\SplObjectStorage->attach() (#1212)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2025-08-18T14:00:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "31580e8d469a5d7b734bb84a65c66b0c84266101",
          "body": "Fluid v5 will have a straightforward way to warmup the cache of\nFluid templates. As preparation for that, all code related to the\nold cache warmup is now deprecated.\n\nThis includes the `<f:cache.warmup>` ViewHelper, which allowed\nto provide special context to templates during cache warmup.\nSince all\n[…]\n dependencies of Fluid templates have been\ndeprecated and will no longer be an issue with Fluid v5, this\nworkaround will no longer be necessary.\n\nCo-authored-by: Simon Praetorius <simon@praetorius.me>",
          "is_bot": false,
          "headline": "[TASK] Deprecate old cache warmup feature (#1211)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2025-08-18T13:34:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "65ef1d82edcccbcb7953bb5db31eb3a447728773",
          "body": "Two new ViewHelpers `<f:startsWith>` and `<f:endsWith>` are added to Fluid. `<f:startsWith>` checks if the subject string starts with a specified string. `<f:endsWith>` checks if the subject string ends with a specified string. These ViewHelpers extend the AbstractConditionViewHelper.\n\nArguments:\n\ns\n[…]\nHello World\">\n\n</f:startsWith>\n<f:endsWith search=\"World\" subject=\"Hello World\">\n\n</f:endsWith>\n\n<f:variable name=\"result\" value=\"{myVariable -> f:startsWith(search: 'Hello')}\" />\n```\n\nResolves: #1126",
          "is_bot": false,
          "headline": "[FEATURE] <f:startsWith> and <f:endsWith> ViewHelpers (#1170)",
          "author_name": "Michael Staatz",
          "author_login": "staatzstreich",
          "committed_at": "2025-08-17T16:31:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c90fffb2fa806f24d4d6f64c89a5d4c6dfef01f3",
          "body": "A new <f:merge> ViewHelper is introduced to Fluid, which merges two arrays, optionally recursively.\n\nArguments:\n\narray $array\narray $with\nbool $recursive\nSee also [the php array_merge()](https://www.php.net/manual/en/function.array-merge.php) and [the php array_merge_recursive()](https://www.php.net\n[…]\n.php) functions.\n\nExamples:\n\n```\n<f:variable name=\"merged\" value=\"{f:merge(array: input, with: toMerge)}\" />\n<f:variable name=\"merged\" value=\"{input -> f:merge(with: toMerge)}\" />\n```\n\nResolves: #1123",
          "is_bot": false,
          "headline": "[FEATURE] <f:merge> ViewHelper (#1206)",
          "author_name": "Michael Staatz",
          "author_login": "staatzstreich",
          "committed_at": "2025-08-17T16:08:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a264bd2b976f4c759543039adb1757673813b05f",
          "body": "In #1151, it was already clarified that the `HtmlspecialcharsViewHelper`\nis in fact not used internally by Fluid. This means that we can also\nget rid of the custom compilation logic, which makes maintainance\nunnecessarily hard.",
          "is_bot": false,
          "headline": "[TASK] Remove micro-optimization from HtmlspecialcharsViewHelper (#1197)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-15T15:54:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0a756cb838d0f073851e4a2570b73107b5df0ee3",
          "body": "Currently, the ViewHelper validation API calls the internal ViewHelper\nAPI to obtain its argument definitions for validation. However, the\nproper way is to use the `ViewHelperResolver`, since it is possible\nto redefine certain argument definitions there.\n\nThis is demonstrated and tested by the `CustomViewHelperResolver`\nin the examples. However, this example only worked until now because\nof the lenient validation implementation of ViewHelpers.",
          "is_bot": false,
          "headline": "[BUGFIX] Call proper API to obtain ViewHelper API (#1199)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-15T15:54:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fc105cacaff2825366aedb318d50a35b10e6caa",
          "body": "The ViewHelper is called with a `string`, but the argument is declared\nas `integer`.",
          "is_bot": false,
          "headline": "[BUGFIX] Address bug in test ViewHelper",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-15T14:50:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d39fc164472acc12b9246e275a9c4817616c5841",
          "body": null,
          "is_bot": false,
          "headline": "[TASK] Apply new cgl rules",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-15T13:54:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f8a8cdbdd51ab72850dce0168bfe07a8824b5ee",
          "body": "With TYPO3 v14, there will be a deeper integration of the new\ncomponents feature into TYPO3. At that point, TYPO3-specific\ndocumentation of components can be added to the official TYPO3\ndocumentation.\n\nFor now, we try to cover TYPO3-specific parts in the Fluid\ndocumentation by adding tips in the relevant places.",
          "is_bot": false,
          "headline": "[DOCS] Improve TYPO3-related sections of components docs (#1188)",
          "author_name": "Simon Praetorius",
          "author_login": "s2b",
          "committed_at": "2025-08-13T12:44:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54cddfd80801ae100af0b33c6671d801b9d3847a",
          "body": "Dev dependency.\nThis has been fixed upstream but not released, yet.\n\nPHP:\nhttps://github.com/php/php-src/commit/5f8d648af6ef4e29a3c7f2b2029d08466c12bc6f\n\nReact/promise:\nhttps://github.com/reactphp/promise/commit/d3998c8a5d3cff0b39b2f332da550e996f35b947",
          "is_bot": false,
          "headline": "[TASK] Apply react/promise patch to fix PHP 8.5 deprecation (#1189)",
          "author_name": "Christian Kuhn",
          "author_login": "lolli42",
          "committed_at": "2025-08-13T12:15:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "866c192774e7367a4f58ef6d54e1c547f4dd94e2",
          "body": "Removed the `get` method entirely and enhanced `getByPath` to handle both local variables and chain traversal. Updated tests to cover the new behavior, improving test robustness by adding cases for nested and array-based paths.\n\nResolves: #1164",
          "is_bot": false,
          "headline": "[BUGFIX] Fix  path access in `ChainedVariableProvider::get` (#1165)",
          "author_name": "Sascha Egerer",
          "author_login": "sascha-egerer",
          "committed_at": "2025-08-12T13:05:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 38,
      "commits_last_year": 126,
      "latest_release_at": "2026-04-16T17:27:38Z",
      "latest_release_tag": "4.6.1",
      "releases_from_tags": false,
      "days_since_last_push": 46,
      "active_weeks_last_year": 26,
      "days_since_latest_release": 105,
      "mean_days_between_releases": 15.9
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "typo3fluid/fluid",
          "exists": true,
          "license": "LGPL-3.0-or-later",
          "keywords": [],
          "ecosystem": "packagist",
          "matches_repo": true,
          "registry_url": "https://packagist.org/packages/typo3fluid/fluid",
          "is_deprecated": false,
          "latest_version": "5.3.1",
          "repository_url": "https://github.com/TYPO3/Fluid",
          "versions_count": 117,
          "total_downloads": 16388135,
          "dependents_count": 90,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 401469,
          "first_published_at": null,
          "latest_published_at": "2026-04-16T17:09:54Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 105
        }
      ]
    },
    "popularity": {
      "forks": 107,
      "stars": 169,
      "watchers": 22,
      "fork_history": {
        "days": [
          {
            "date": "2015-09-16",
            "count": 1
          },
          {
            "date": "2015-09-18",
            "count": 1
          },
          {
            "date": "2015-09-24",
            "count": 1
          },
          {
            "date": "2016-01-29",
            "count": 1
          },
          {
            "date": "2016-02-03",
            "count": 1
          },
          {
            "date": "2016-03-01",
            "count": 1
          },
          {
            "date": "2016-03-05",
            "count": 1
          },
          {
            "date": "2016-04-04",
            "count": 1
          },
          {
            "date": "2016-04-07",
            "count": 1
          },
          {
            "date": "2016-09-16",
            "count": 1
          },
          {
            "date": "2016-09-21",
            "count": 1
          },
          {
            "date": "2017-01-30",
            "count": 1
          },
          {
            "date": "2017-02-10",
            "count": 1
          },
          {
            "date": "2017-03-19",
            "count": 1
          },
          {
            "date": "2017-04-08",
            "count": 1
          },
          {
            "date": "2017-05-14",
            "count": 1
          },
          {
            "date": "2017-07-05",
            "count": 1
          },
          {
            "date": "2017-07-11",
            "count": 1
          },
          {
            "date": "2017-07-28",
            "count": 1
          },
          {
            "date": "2017-07-30",
            "count": 1
          },
          {
            "date": "2017-09-27",
            "count": 1
          },
          {
            "date": "2017-10-19",
            "count": 1
          },
          {
            "date": "2017-10-28",
            "count": 1
          },
          {
            "date": "2017-12-06",
            "count": 1
          },
          {
            "date": "2017-12-07",
            "count": 1
          },
          {
            "date": "2017-12-29",
            "count": 1
          },
          {
            "date": "2018-01-08",
            "count": 1
          },
          {
            "date": "2018-01-15",
            "count": 1
          },
          {
            "date": "2018-01-18",
            "count": 1
          },
          {
            "date": "2018-02-08",
            "count": 1
          },
          {
            "date": "2018-02-28",
            "count": 1
          },
          {
            "date": "2018-05-08",
            "count": 1
          },
          {
            "date": "2018-05-29",
            "count": 1
          },
          {
            "date": "2018-05-30",
            "count": 1
          },
          {
            "date": "2018-07-18",
            "count": 1
          },
          {
            "date": "2018-12-05",
            "count": 1
          },
          {
            "date": "2019-03-13",
            "count": 1
          },
          {
            "date": "2019-03-28",
            "count": 1
          },
          {
            "date": "2019-04-08",
            "count": 1
          },
          {
            "date": "2019-05-15",
            "count": 1
          },
          {
            "date": "2019-06-19",
            "count": 1
          },
          {
            "date": "2019-06-20",
            "count": 3
          },
          {
            "date": "2019-06-22",
            "count": 1
          },
          {
            "date": "2019-07-31",
            "count": 1
          },
          {
            "date": "2019-08-03",
            "count": 1
          },
          {
            "date": "2019-09-25",
            "count": 1
          },
          {
            "date": "2020-01-08",
            "count": 1
          },
          {
            "date": "2020-01-29",
            "count": 1
          },
          {
            "date": "2020-03-29",
            "count": 1
          },
          {
            "date": "2020-04-30",
            "count": 1
          },
          {
            "date": "2020-05-27",
            "count": 1
          },
          {
            "date": "2020-10-27",
            "count": 1
          },
          {
            "date": "2020-12-16",
            "count": 1
          },
          {
            "date": "2021-04-28",
            "count": 1
          },
          {
            "date": "2021-05-04",
            "count": 1
          },
          {
            "date": "2021-05-12",
            "count": 1
          },
          {
            "date": "2021-06-02",
            "count": 1
          },
          {
            "date": "2021-06-08",
            "count": 1
          },
          {
            "date": "2021-08-30",
            "count": 1
          },
          {
            "date": "2021-10-21",
            "count": 1
          },
          {
            "date": "2021-10-26",
            "count": 1
          },
          {
            "date": "2021-11-15",
            "count": 1
          },
          {
            "date": "2021-11-19",
            "count": 1
          },
          {
            "date": "2022-02-07",
            "count": 1
          },
          {
            "date": "2022-05-26",
            "count": 1
          },
          {
            "date": "2022-07-14",
            "count": 1
          },
          {
            "date": "2022-07-29",
            "count": 1
          },
          {
            "date": "2022-07-30",
            "count": 1
          },
          {
            "date": "2022-08-05",
            "count": 1
          },
          {
            "date": "2022-09-08",
            "count": 1
          },
          {
            "date": "2022-09-20",
            "count": 1
          },
          {
            "date": "2022-11-10",
            "count": 1
          },
          {
            "date": "2022-12-09",
            "count": 1
          },
          {
            "date": "2023-01-30",
            "count": 1
          },
          {
            "date": "2023-03-22",
            "count": 1
          },
          {
            "date": "2023-04-18",
            "count": 1
          },
          {
            "date": "2023-04-26",
            "count": 1
          },
          {
            "date": "2023-05-11",
            "count": 1
          },
          {
            "date": "2023-11-24",
            "count": 1
          },
          {
            "date": "2023-12-01",
            "count": 1
          },
          {
            "date": "2023-12-27",
            "count": 1
          },
          {
            "date": "2024-01-12",
            "count": 1
          },
          {
            "date": "2024-03-14",
            "count": 1
          },
          {
            "date": "2024-05-21",
            "count": 1
          },
          {
            "date": "2024-09-27",
            "count": 1
          },
          {
            "date": "2024-10-18",
            "count": 1
          },
          {
            "date": "2025-02-11",
            "count": 1
          },
          {
            "date": "2025-03-27",
            "count": 1
          },
          {
            "date": "2025-04-20",
            "count": 1
          },
          {
            "date": "2025-04-27",
            "count": 1
          },
          {
            "date": "2025-05-05",
            "count": 1
          },
          {
            "date": "2025-05-19",
            "count": 1
          },
          {
            "date": "2025-05-22",
            "count": 1
          },
          {
            "date": "2025-07-29",
            "count": 1
          },
          {
            "date": "2025-08-02",
            "count": 1
          },
          {
            "date": "2025-08-04",
            "count": 1
          },
          {
            "date": "2025-08-07",
            "count": 2
          },
          {
            "date": "2025-08-09",
            "count": 1
          },
          {
            "date": "2025-08-29",
            "count": 1
          },
          {
            "date": "2025-09-04",
            "count": 1
          },
          {
            "date": "2025-09-05",
            "count": 1
          },
          {
            "date": "2025-09-09",
            "count": 1
          },
          {
            "date": "2026-02-19",
            "count": 1
          },
          {
            "date": "2026-04-25",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 107,
        "total_forks": 107
      },
      "star_history": null,
      "open_issues_and_prs": 72
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 42311,
      "source_files_sampled": 381,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "composer.json"
      ],
      "advisories": {
        "error": "No resolved dependencies carried a version and a supported ecosystem",
        "scope": "repository_graph",
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 11,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "packagist"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "ext-json",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "ext-mbstring",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "ext-simplexml",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "friendsofphp/php-cs-fixer",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "infection/infection",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "php",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "phpstan/phpstan",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "phpstan/phpstan-phpunit",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "phpunit/phpunit",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "psr/container",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "t3docs/fluid-documentation-generator",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 11,
        "direct_count": 0,
        "indirect_count": 11
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 13,
        "merged_prs": 924,
        "open_issues": 59,
        "closed_ratio": 0.818,
        "closed_issues": 265,
        "closed_unmerged_prs": 122
      },
      "bus_factor": 3,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "NamelessCoder",
          "commits": 343,
          "avatar_url": "https://avatars.githubusercontent.com/u/2228052?v=4"
        },
        {
          "type": "User",
          "login": "s2b",
          "commits": 258,
          "avatar_url": "https://avatars.githubusercontent.com/u/458524?v=4"
        },
        {
          "type": "User",
          "login": "lolli42",
          "commits": 229,
          "avatar_url": "https://avatars.githubusercontent.com/u/2178068?v=4"
        },
        {
          "type": "User",
          "login": "skurfuerst",
          "commits": 222,
          "avatar_url": "https://avatars.githubusercontent.com/u/190777?v=4"
        },
        {
          "type": "User",
          "login": "kdambekalns",
          "commits": 181,
          "avatar_url": "https://avatars.githubusercontent.com/u/95873?v=4"
        },
        {
          "type": "User",
          "login": "robertlemke",
          "commits": 104,
          "avatar_url": "https://avatars.githubusercontent.com/u/95582?v=4"
        },
        {
          "type": "User",
          "login": "afoeder",
          "commits": 23,
          "avatar_url": "https://avatars.githubusercontent.com/u/1125168?v=4"
        },
        {
          "type": "User",
          "login": "sbuerk",
          "commits": 20,
          "avatar_url": "https://avatars.githubusercontent.com/u/1453466?v=4"
        },
        {
          "type": "User",
          "login": "hlubek",
          "commits": 18,
          "avatar_url": "https://avatars.githubusercontent.com/u/33351?v=4"
        },
        {
          "type": "User",
          "login": "maddy2101",
          "commits": 16,
          "avatar_url": "https://avatars.githubusercontent.com/u/1925287?v=4"
        }
      ],
      "contributors_sampled": 100,
      "top_contributor_share": 0.211
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build.yml",
        "test-documentation.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".php-cs-fixer.dist.php"
      ],
      "has_editorconfig": true,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 4,
            "reason": "Found 14/30 approved changesets -- score normalized to 4",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 37 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 1,
            "reason": "2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "ef902a525a983f6dde46c37c9f0c1a912da3a7cc",
        "ran_at": "2026-07-30T22:49:36Z",
        "aggregate_score": 4.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-30T07:59:28Z",
      "oldest_open_prs": [
        {
          "number": 396,
          "created_at": "2018-07-16T09:21:56Z",
          "last_comment_at": "2018-07-16T10:45:28Z",
          "last_comment_author": "NamelessCoder"
        },
        {
          "number": 398,
          "created_at": "2018-07-26T13:48:29Z",
          "last_comment_at": "2019-03-25T12:22:12Z",
          "last_comment_author": "coveralls"
        },
        {
          "number": 469,
          "created_at": "2019-07-31T12:56:57Z",
          "last_comment_at": "2019-07-31T13:46:46Z",
          "last_comment_author": "mbrodala"
        },
        {
          "number": 572,
          "created_at": "2021-10-26T14:48:46Z",
          "last_comment_at": "2025-06-02T11:45:05Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 671,
          "created_at": "2022-12-09T11:31:37Z",
          "last_comment_at": "2023-08-16T16:12:17Z",
          "last_comment_author": "spthiel"
        },
        {
          "number": 1052,
          "created_at": "2025-04-16T22:18:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1229,
          "created_at": "2025-09-04T21:09:55Z",
          "last_comment_at": "2026-02-15T20:52:17Z",
          "last_comment_author": "schliesser"
        },
        {
          "number": 1234,
          "created_at": "2025-09-11T03:12:05Z",
          "last_comment_at": "2025-09-16T01:10:28Z",
          "last_comment_author": "billdagou"
        },
        {
          "number": 1271,
          "created_at": "2025-12-07T17:22:13Z",
          "last_comment_at": "2026-03-13T06:50:54Z",
          "last_comment_author": "mbrodala"
        },
        {
          "number": 1321,
          "created_at": "2026-02-19T17:32:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1372,
          "created_at": "2026-04-15T17:13:17Z",
          "last_comment_at": "2026-04-16T17:30:49Z",
          "last_comment_author": "lolli42"
        },
        {
          "number": 1375,
          "created_at": "2026-04-24T05:37:03Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1384,
          "created_at": "2026-07-01T08:30:27Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-06-14T12:03:57Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 177,
          "created_at": "2016-09-29T14:30:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 212,
          "created_at": "2016-10-27T06:06:11Z",
          "last_comment_at": "2016-10-27T11:07:13Z",
          "last_comment_author": "AndreasA"
        },
        {
          "number": 274,
          "created_at": "2017-03-02T13:38:13Z",
          "last_comment_at": "2023-11-24T16:34:29Z",
          "last_comment_author": "lolli42"
        },
        {
          "number": 280,
          "created_at": "2017-04-18T15:46:10Z",
          "last_comment_at": "2023-11-24T17:40:31Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 336,
          "created_at": "2017-08-10T14:47:54Z",
          "last_comment_at": "2023-05-15T12:31:53Z",
          "last_comment_author": "masi"
        },
        {
          "number": 373,
          "created_at": "2018-02-27T08:17:27Z",
          "last_comment_at": "2018-12-07T15:16:55Z",
          "last_comment_author": "NamelessCoder"
        },
        {
          "number": 382,
          "created_at": "2018-03-21T14:59:30Z",
          "last_comment_at": "2023-11-24T17:07:41Z",
          "last_comment_author": "lolli42"
        },
        {
          "number": 391,
          "created_at": "2018-07-04T08:16:31Z",
          "last_comment_at": "2021-06-03T11:41:15Z",
          "last_comment_author": "aimeos"
        },
        {
          "number": 407,
          "created_at": "2018-09-28T09:19:39Z",
          "last_comment_at": "2021-01-22T12:53:14Z",
          "last_comment_author": "NamelessCoder"
        },
        {
          "number": 412,
          "created_at": "2018-10-22T09:51:41Z",
          "last_comment_at": "2023-11-24T17:19:23Z",
          "last_comment_author": "lolli42"
        },
        {
          "number": 417,
          "created_at": "2018-11-07T11:12:31Z",
          "last_comment_at": "2021-05-18T20:23:08Z",
          "last_comment_author": "bmack"
        },
        {
          "number": 428,
          "created_at": "2019-02-14T14:37:42Z",
          "last_comment_at": "2021-05-21T08:58:04Z",
          "last_comment_author": "hilburger"
        },
        {
          "number": 514,
          "created_at": "2020-03-06T21:06:23Z",
          "last_comment_at": "2021-05-20T19:18:32Z",
          "last_comment_author": "hilburger"
        },
        {
          "number": 522,
          "created_at": "2020-09-02T13:37:53Z",
          "last_comment_at": "2023-11-24T17:39:23Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 533,
          "created_at": "2021-03-17T18:11:28Z",
          "last_comment_at": "2024-08-11T09:17:14Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 556,
          "created_at": "2021-07-08T16:30:57Z",
          "last_comment_at": "2025-03-25T07:47:12Z",
          "last_comment_author": "mbrodala"
        },
        {
          "number": 590,
          "created_at": "2022-05-07T22:23:38Z",
          "last_comment_at": "2024-08-11T08:59:25Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 938,
          "created_at": "2024-07-25T10:35:50Z",
          "last_comment_at": "2024-08-11T08:04:40Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 953,
          "created_at": "2024-08-11T07:57:02Z",
          "last_comment_at": "2025-02-11T18:39:10Z",
          "last_comment_author": "s2b"
        },
        {
          "number": 975,
          "created_at": "2024-08-18T10:25:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/TYPO3/Fluid",
    "host": "github.com",
    "name": "Fluid",
    "owner": "TYPO3"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "excellent",
      "name": "Overall health",
      "note": "The weighted overall 68 is calibrated to 80 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 68,
            "calibrated": 80,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 80,
      "inputs": {
        "security": 42,
        "vitality": 69,
        "community": 70,
        "governance": 79,
        "calibration": "2026-08-02",
        "engineering": 80,
        "ai_readiness": 41,
        "weighted_overall_raw": 68
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 69,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "commits_last_year": 126,
              "human_commit_share": 1,
              "days_since_last_push": 46,
              "active_weeks_last_year": 26
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 46 days ago",
                "points": 18,
                "status": "partial",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 46
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "26/52 weeks with commits",
                "points": 18,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 26
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "126 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 126
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 90,
            "inputs": {
              "releases_count": 38,
              "latest_release_tag": "4.6.1",
              "releases_from_tags": false,
              "days_since_latest_release": 105,
              "mean_days_between_releases": 15.9
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "38 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 38
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 105 days ago",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 105
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~15.9 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 15.9
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 51,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 51 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 51
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "good",
        "name": "Community & Adoption",
        "value": 70,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "moderate",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "forks": 107,
              "stars": 169,
              "watchers": 22,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "169 stars",
                "points": 36.1,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 169
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "107 forks",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 107
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "22 watchers",
                "points": 7.4,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (LGPL-3.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "LGPL-3.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "excellent",
            "name": "Ecosystem adoption (downloads)",
            "note": null,
            "notes": [],
            "value": 88,
            "inputs": {
              "packages": [
                "typo3fluid/fluid"
              ],
              "dependents": 90,
              "ecosystems": "packagist",
              "total_downloads": 16388135,
              "monthly_downloads": 401469
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "401,469 downloads/month across packagist",
                "points": 74.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 401469,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "90 packages depend on it",
                "points": 13.1,
                "status": "partial",
                "details": [
                  {
                    "code": "registry_dependents",
                    "params": {
                      "count": 90
                    }
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "good",
        "name": "Sustainability & Governance",
        "value": 79,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "good",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "bus_factor": 3,
              "contributors_sampled": 100,
              "top_contributor_share": 0.211
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "3 contributor(s) cover half of all commits",
                "points": 36,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 21% of commits",
                "points": 17.8,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 21
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "100 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 37 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 77,
            "inputs": {
              "merged_prs": 924,
              "open_issues": 59,
              "closed_issues": 265,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 0.818,
              "closed_unmerged_prs": 122,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "82% of issues closed",
                "points": 34.4,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 82
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "924/1046 decided PRs merged",
                "points": 26.5,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 924,
                      "decided": 1046
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 14/30 approved changesets -- score normalized to 4",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "followers": 117,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "TYPO3",
              "public_repos": 23,
              "account_age_days": 6274
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "117 followers of TYPO3",
                "points": 14.9,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 117,
                      "login": "TYPO3"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "23 public repos, account ~17 yr old",
                "points": 22.1,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 23
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 17
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "typo3fluid/fluid"
              ],
              "ecosystems": "packagist",
              "any_deprecated": false,
              "min_days_since_publish": 105
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on packagist",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 105 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 105
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "117 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 117
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "excellent",
        "name": "Engineering Quality",
        "value": 80,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": ".php-cs-fixer.dist.php",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".php-cs-fixer.dist.php"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "weak",
        "name": "Security",
        "value": 42,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "weak",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 42,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 12,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 6,
              "scorecard_aggregate": 4.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 14/30 approved changesets -- score normalized to 4",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 37 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 22
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "weak",
        "name": "AI Readiness",
        "value": 41,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "weak",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.98,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "98 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "weak",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 37,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".php-cs-fixer.dist.php",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".php-cs-fixer.dist.php"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "primary_language": "PHP",
              "largest_source_bytes": 42311,
              "source_files_sampled": 381,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "PHP without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "PHP"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/381 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 381,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "weak",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "top": [
        "library"
      ],
      "labels": [
        "library"
      ],
      "scores": {
        "library": 6
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:packagist",
          "weight": 6
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.5.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-30T22:50:04.584181Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/t/TYPO3/Fluid.svg",
  "full_name": "TYPO3/Fluid",
  "license_state": "standard",
  "license_spdx": "LGPL-3.0"
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v2.5.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenPackagist.