Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 1.13.0 · 2026-07-25 07:56 UTC

buckwem / prodockit-extensions

Python-Markdown extension & pdf generation for professional and academic documentation

PythonMIT★ 0 Sterne⑂ 0 Forksseit Juli 2026Auf GitHub ansehen ↗

buckwem/prodockit-extensions erreicht einen Gesundheitsindex von 52 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei Vitality (73/100) ab, am schwächsten bei Community & Adoption (24/100). Zuletzt heute aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

52
gesamt / 100
Mittel

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

52
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende 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.

Eigentümerschaft

Mark BuckwellPersönliches Konto
1 Follower3 öffentliche Reposseit Juli 2019

Dieses Repository gehört einem persönlichen Konto. Ein Projekt mit nur einem Eigentümer trägt ein höheres Kontinuitätsrisiko als ein organisationsgetragenes.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlichtTags
PyPIprodockit0.10.2-25vor 0 Tagenextensionmarkdownpandocpdfpython-markdownzensical

Metriken nach Kategorie

Vitalität

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

73Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 0 Tagen
1.4/36Commit-Rhythmus — 2/52 Wochen mit Commits
18/18Commit-Volumen — 154 Commits im letzten Jahr
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Verwendete Eingangsdaten
commits_last_year154
human_commit_share1
days_since_last_push0
active_weeks_last_year2

Release-Disziplin

100Exzellent
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 36 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 0 Tagen
27/27Release-Rhythmus — ein Release etwa alle 0,4 Tage
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count36
latest_release_tagprodockit-v0.10.2
releases_from_tagsnein
days_since_latest_release0
mean_days_between_releases0,4
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?

24Kritisch · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 0 Stars
0/25Forks — 0 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (MIT)
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templatenein

Nachhaltigkeit & Governance

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

50Mittel · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 100 % der Commits
1.4/13.5Breite der Beitragenden — 1 Beitragende
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Verwendete Eingangsdaten
bus_factor1
contributors_sampled1
top_contributor_share1
Wie die Bewertung erfolgt
33.8/46.8Issue-Lösungsquote — 72 % der Issues geschlossen
38.2/38.3PR-Annahme — 65/65 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/20 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs65
open_issues8
closed_issues21
issue_closed_ratio0,724
closed_unmerged_prs0
Wie die Bewertung erfolgt
10/30Organisatorische Trägerschaft — persönliches (Nutzer-)Konto
0/20Verifizierte Domain — für Nutzerkonten nicht anwendbar
2.2/25Reichweite des Inhabers — 1 Follower von buckwem
16.4/25Kontohistorie — 3 öffentliche Repos, Kontoalter ca. 7 Jahre
Verwendete Eingangsdaten
followers1
owner_typeUser
is_verified
owner_loginbuckwem
public_repos3
account_age_days2.559
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Paketpflege

100Exzellent
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf pypi
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 0 Tagen
20/20Versionshistorie — 25 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesprodockit
ecosystemspypi
any_deprecatednein
min_days_since_publish0

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

67Mittel · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 3 Workflow(s)
24/24Tests vorhanden
0/16Linter-Konfiguration
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfignein
has_linter_confignein
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?

40Gefährdet · 16 % des Gesamtindex

Sicherheitslage

40Gefährdet
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
3.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 8 out of 8 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
0/7.5Code-Review — Found 0/20 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Lizenz — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
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 — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): signed_releases. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

49Gefährdet · 0 % 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
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — src/prodockit/py.typed
0/10Reproduzierbare Umgebung
10/10Belegte Agentenpraxis — 57 der letzten 100 Commits von Agenten verfasst oder ihnen zugeschrieben
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfiles
has_dockerfilenein
typed_languagenein
bootstrap_files
has_devcontainernein
has_linter_confignein
typecheck_configssrc/prodockit/py.typed
agent_commit_share0,57
toolchain_manifests
dependency_bot_commit_share0
Wie die Bewertung erfolgt
27/45Typprüfbarer Code — Python mit Typprüfungs-Konfiguration (src/prodockit/py.typed)
55/55Handhabbare Dateigrößen — 0/51 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languagePython
largest_source_bytes44.300
source_files_sampled51
oversized_source_files0

Eckdaten

0GitHub-Sterne
1Mitwirkende
154Commits, letzte 12 Monate
0Tage seit letztem Push
36Releases
1Bus-Faktor
8offene Issues
PyPIPaket-Ökosysteme

Warnungen zur Datenerhebung

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index pypi:prodockit@0.10.2; advisories assessed against the repository dependency graph instead

Weitere Details

OpenSSF Scorecard 4.0 / 10
4.0Gesamtwert

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-25 07:56 UTC

10Binary-Artifactsno binaries found in the repo
5Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/20 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
k. A.Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Direkte Abhängigkeiten 5
RegistryPaketVersionsvorgabeManifest
PyPIMarkdown>=3.4pyproject.toml
PyPIzensicalpyproject.toml
PyPIbeautifulsoup4>=4.12pyproject.toml
PyPIclick>=8.0pyproject.toml
PyPIpypdf>=4.0pyproject.toml
Alle Abhängigkeiten nicht erhoben

Der aufgelöste Abhängigkeitssatz konnte für diesen Bericht nicht erhoben werden: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

JSON-Rohbericht maschinenlesbar
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 1216,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "HTML": 4145,
        "Python": 525826
      },
      "pushed_at": "2026-07-25T07:53:38Z",
      "created_at": "2026-07-14T11:13:06Z",
      "owner_type": "User",
      "updated_at": "2026-07-25T07:52:04Z",
      "description": "Python-Markdown extension & pdf generation for professional and academic documentation",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Python",
      "significant_languages": [
        "Python"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Mark Buckwell",
      "type": "User",
      "login": "buckwem",
      "company": null,
      "location": "United Kingdom",
      "followers": 1,
      "avatar_url": "https://avatars.githubusercontent.com/u/53193258?v=4",
      "created_at": "2019-07-22T18:56:17Z",
      "is_verified": null,
      "public_repos": 3,
      "account_age_days": 2559
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "prodockit-v0.10.2",
          "kind": "other",
          "published_at": "2026-07-25T07:53:50Z"
        },
        {
          "tag": "prodockit-v0.10.1",
          "kind": "other",
          "published_at": "2026-07-24T22:40:26Z"
        },
        {
          "tag": "prodockit-v0.10.0",
          "kind": "other",
          "published_at": "2026-07-24T22:00:47Z"
        },
        {
          "tag": "prodockit-v0.9.0",
          "kind": "other",
          "published_at": "2026-07-24T18:42:19Z"
        },
        {
          "tag": "prodockit-v0.8.1",
          "kind": "other",
          "published_at": "2026-07-24T08:22:53Z"
        },
        {
          "tag": "prodockit-v0.8.0",
          "kind": "other",
          "published_at": "2026-07-24T08:00:14Z"
        },
        {
          "tag": "prodockit-v0.7.1",
          "kind": "other",
          "published_at": "2026-07-24T07:49:52Z"
        },
        {
          "tag": "prodockit-v0.7.0",
          "kind": "other",
          "published_at": "2026-07-23T23:10:14Z"
        },
        {
          "tag": "prodockit-v0.6.8",
          "kind": "other",
          "published_at": "2026-07-21T19:24:37Z"
        },
        {
          "tag": "prodockit-v0.6.6",
          "kind": "other",
          "published_at": "2026-07-21T17:33:17Z"
        },
        {
          "tag": "prodockit-v0.6.5",
          "kind": "other",
          "published_at": "2026-07-21T09:25:48Z"
        },
        {
          "tag": "prodockit-v0.6.4",
          "kind": "other",
          "published_at": "2026-07-21T08:47:37Z"
        },
        {
          "tag": "prodockit-v0.6.3",
          "kind": "other",
          "published_at": "2026-07-20T22:58:07Z"
        },
        {
          "tag": "prodockit-v0.6.2",
          "kind": "other",
          "published_at": "2026-07-20T20:19:21Z"
        },
        {
          "tag": "prodockit-v0.6.1",
          "kind": "other",
          "published_at": "2026-07-20T19:34:07Z"
        },
        {
          "tag": "prodockit-v0.6.0",
          "kind": "other",
          "published_at": "2026-07-20T19:24:38Z"
        },
        {
          "tag": "prodockit-v0.5.0",
          "kind": "other",
          "published_at": "2026-07-19T10:33:08Z"
        },
        {
          "tag": "prodockit-v0.4.2",
          "kind": "other",
          "published_at": "2026-07-18T23:29:23Z"
        },
        {
          "tag": "prodockit-v0.4.1",
          "kind": "other",
          "published_at": "2026-07-18T23:01:47Z"
        },
        {
          "tag": "prodockit-v0.4.0",
          "kind": "other",
          "published_at": "2026-07-18T21:58:10Z"
        },
        {
          "tag": "prodockit-v0.3.1",
          "kind": "other",
          "published_at": "2026-07-18T18:19:35Z"
        },
        {
          "tag": "prodockit-v0.3.0",
          "kind": "other",
          "published_at": "2026-07-18T17:08:47Z"
        },
        {
          "tag": "prodockit-v0.2.0",
          "kind": "other",
          "published_at": "2026-07-17T23:06:57Z"
        },
        {
          "tag": "prodockit-v0.1.1",
          "kind": "other",
          "published_at": "2026-07-17T14:52:28Z"
        },
        {
          "tag": "prodockit-v0.1.0",
          "kind": "other",
          "published_at": "2026-07-17T09:38:29Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-07-15T20:29:38Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-07-15T19:35:21Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-07-15T19:07:57Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-15T18:49:20Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-14T21:56:29Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-07-14T21:40:10Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-07-14T14:29:13Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-07-14T13:44:16Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-07-14T13:00:28Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-07-14T12:38:47Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-07-14T12:03:00Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "01704d39b624eb13575933cabd2416307555476d",
          "body": "Docs-only release: points to Zensical's own site search instead of a\ngeneric browser/Ctrl-F reference - see the changelog for details. No\ncode changes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.10.2",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-25T07:51:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2d6be1a17bb2661b4ded98d1e015101fbed6db04",
          "body": "Point to Zensical's own site search instead of browser/Ctrl-F search",
          "is_bot": false,
          "headline": "Merge pull request #94 from buckwem/update-index-search-reference",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-25T07:49:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d2a57be8cb3810fce2fe8e0921e13be5141ba04",
          "body": "Zensical ships built-in site search (https://zensical.org/docs/setup/search/),\na more accurate and discoverable way to describe how a reader finds a\nterm on the live website than a generic browser Ctrl-F reference.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Point to Zensical's own site search instead of browser/Ctrl-F search",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-25T07:36:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e747ccb95357ffaf1b226004b621e3d971f0501e",
          "body": "Docs-only release: combines index-term marking and index generation\ninto one docs page, renamed to \"Index (pdf-only)\" - see the changelog\nfor details. No code changes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.10.1",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:38:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "82550cf107d25d02a800d1df467108a6969fc25c",
          "body": "Combine index-term marking and generation into one docs page, rename to 'Index (pdf-only)'",
          "is_bot": false,
          "headline": "Merge pull request #93 from buckwem/combine-index-terms-docs",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:35:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "398fb995c1d47eeb2b5ec44598a9fc5c53e4507e",
          "body": "Now that this page covers the whole feature (marking and generation),\nnot just marking - and to make the PDF-only scope explicit in nav/the\nbrowser tab title. The file path (extensions/index-terms.md) and anchor\nids are unchanged.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Rename 'Index terms' to 'Index (pdf-only)'",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:31:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "db55270d2477352e240a304280780cc6631c7748",
          "body": "prodockit.bibliography's own docs already combine marking (\\citebib{id})\nand generation (\\bibliography) into one page - prodockit.index/\nprodockit.pdf's back-of-book index was split across two pages instead\n(extensions/index-terms.md for marking, pdf.md for generation), even\nthough the marker is use\n[…]\nleft a short pointer in pdf.md's own Configuration/Python API sections -\nmatching how prodockit.bibliography is treated there. No code changes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Combine index-term marking and index generation into one docs page",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:30:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9aaa0c4b7f409cbcf428fa742e1a54789d3002f1",
          "body": "… page\"\n\nThis reverts commit ae4358f699639b377fb59f8085bbb9007fe312bf.",
          "is_bot": false,
          "headline": "Revert \"Combine index-term marking and index generation into one docs…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:26:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae4358f699639b377fb59f8085bbb9007fe312bf",
          "body": "prodockit.bibliography's own docs already combine marking (\\citebib{id})\nand generation (\\bibliography) into one page - prodockit.index/\nprodockit.pdf's back-of-book index was split across two pages instead\n(extensions/index-terms.md for marking, pdf.md for generation), even\nthough the marker is use\n[…]\nleft a short pointer in pdf.md's own Configuration/Python API sections -\nmatching how prodockit.bibliography is treated there. No code changes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Combine index-term marking and index generation into one docs page",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T22:23:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "acde20cfee8c91434be30a0f9ecfcedc155348b2",
          "body": "New, backward-compatible feature: prodockit.bibliography's \\bibliography\nmarker now supports generating both a strict References section and a\nbroader Bibliography section - see the changelog for details.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.10.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T21:54:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "07565557cc0a61db257aa951d620a319dc255d01",
          "body": "Add References/Bibliography sections to prodockit.bibliography's \\bibliography marker",
          "is_bot": false,
          "headline": "Merge pull request #92 from buckwem/generate-references-and-bibliography",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T21:51:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c3e52c87c5f3f33521e86a839521b12f8613619",
          "body": "The \"Comparing the two approaches\" table didn't mention this PR's new\ncapability at all, even though it's a real differentiator - prodockit.citations\nhas no equivalent built-in References/Bibliography split.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add References/Bibliography split to the comparison table",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T21:49:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9e07f560dfa21c35a354abba0e25b7fccf922cbf",
          "body": "…liography marker\n\n\\bibliography now takes two optional, positional parameters -\n\\bibliography{<file>}{<true|false>} - so a project can generate a strict\nReferences section (cited_only=true) and a broader Bibliography section\n(every entry, including uncited background reading) in the same build,\nfro\n[…]\nr, not a CSL reimplementation), rather than assuming a\nsingle global bibliography page - the common single-file case is\nunaffected.\n\nFixes #89.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add References/Bibliography sections to prodockit.bibliography's \\bib…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T21:16:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0adfbf0da2e899160baace44cfc3b137eb064437",
          "body": "Breaking change: copyright/pdf_copyright now render as a real HTML\nfragment in the PDF footer (real links survive) instead of a CSS\ncontent string - see the changelog for details.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.9.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T18:40:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cdd3897efd867409670d1f6ef6c5cbddf768750e",
          "body": "Give the PDF's copyright footer real Zensical/prodockit links, unlink cover page",
          "is_bot": false,
          "headline": "Merge pull request #90 from buckwem/adjust-zensical-links",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T18:37:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40be41e0b6771e0b0769275d45b7de55c1d48707",
          "body": "… cover page\n\nFixes #88.\n\n- docs/index.md: the cover page's hero subtitle no longer hyperlinks\n  \"Zensical\" - the word stays, the link doesn't.\n- prodockit.pdf.build/css: copyright_text (project.copyright/\n  pdf_copyright) is now a real HTML fragment rendered as a real DOM\n  element via CSS Paged Me\n[…]\ncted). No formal, versioned public API\nsurface yet for prodockit.pdf (see prodockit-extension#7), so this is\nan acceptable break at this stage.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Give the PDF's copyright footer real Zensical/prodockit links, unlink…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T18:25:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "445b01523899d7d393b4e703473efa2b8606e500",
          "body": "Docs-only release: this project's own site and PDF now carry the\n\"Made with Zensical and prodockit\" credit line - see the changelog\nfor details. No library code changed.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.8.1",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T08:20:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "319e2f2321fa0ae64d3825814fdbff0124d82075",
          "body": "…wn site and PDF\n\nThis project's own docs site and PDF were missing the credit line that\noverrides/partials/copyright.html and pdf_copyright already give a\ndownstream project (e.g. prodockit-template) - added both here too, so\nthis site credits itself the same way a project built with it does.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add the 'Made with Zensical and prodockit' credit to this project's o…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T08:16:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d91d96dc41e1d8550a082e699ddd52500c8d547f",
          "body": "changelog.md lives in docs/about/, so the link needed ../pdf.md, not\npdf.md - caught by the strict docs build failing in CI after the 0.8.0\nbump.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix broken changelog link to pdf.md's Copyright text section",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T08:03:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9716c3fca0c96f743f5fec8ec15eec9d17903442",
          "body": "New opt-in pdf_copyright setting overrides project.copyright for the\nPDF's footer only, plus a white-space: pre-line fix so a \\A forced\nline break in either setting actually renders as a line break - see\nthe changelog for details.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.8.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T07:59:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac55a7afc43ed630b8cb47b2e72d9c97e809ea14",
          "body": "Add an opt-in pdf_copyright override, PDF-only",
          "is_bot": false,
          "headline": "Merge pull request #85 from buckwem/add-pdf-copyright-override",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T07:58:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca9754fa026aa1b009d4981f694bee17050405ef",
          "body": "Docs-only release: this project's own docs site now enables every\nprodockit extension, which surfaced and fixed a non-deterministic\nheading-id collision bug in the docs content itself - see the\nchangelog for details. No library code changed.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.7.1",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T07:49:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aca5aa78210be7d9d7325ab986f1bac9cbf59ec5",
          "body": "Enable every prodockit extension on this project's own docs site",
          "is_bot": false,
          "headline": "Merge pull request #87 from buckwem/enable-all-prodockit-extensions",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-24T07:48:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec8d3bf06e4557b530a86fee1b222e953b944fa4",
          "body": "Breaking change: prodockit.bibliography now uses \\citebib{id} instead\nof \\cite{id}, resolving the syntax conflict with prodockit.citations so\nboth can be enabled together - see the changelog for details. Also\nfixes a stale \\cite{id} mention in README.md's bibliography row missed\nby the PR #86 rename.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.7.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T23:09:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "39033d3292a7a7c052b49c4b0d55431f72d78fd4",
          "body": "BREAKING: rename prodockit.bibliography's \\cite{id} to \\citebib{id}",
          "is_bot": false,
          "headline": "Merge pull request #86 from buckwem/rename-bibliography-cite-marker",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T23:07:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3722f82060800c53e8f32e7f8f93da2ff97588af",
          "body": "zensical.toml now enables prodockit.headings (numbering=\"continuous\"),\nprodockit.refs, prodockit.citations, prodockit.glossary, and\nprodockit.bibliography, alongside the already-enabled prodockit.tables/\nprodockit.index - every extension this project documents is now also\navailable on its own docs s\n[…]\ncross several repeated\nbuilds, confirming the non-determinism is gone) and a real `prodockit\npdf` build (86 pages, no stash-placeholder leaks).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Enable every prodockit extension on this project's own docs site",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T22:19:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5765e2b44b08825747f3160484b6cf3120126af",
          "body": "BREAKING CHANGE: prodockit.bibliography and prodockit.citations both\nused to claim \\cite{id}, so only one could ever be enabled in a build -\nenabling both made their inline patterns (same regex, same priority)\nrace for the same match, with whichever ran first silently winning.\n\nprodockit.bibliograph\n[…]\n\\cite{id} no longer resolves, and a new test confirming\nprodockit.citations and prodockit.bibliography now coexist correctly\nin the same build.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Rename prodockit.bibliography's syntax from \\cite{id} to \\citebib{id}",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T21:59:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0b1512d308c829913ed8d0543e3d55179a6ee578",
          "body": "Adds a \"Copyright text\" section to the PDF generation docs: how\ncopyright feeds both website and PDF by default, how pdf_copyright\noverrides it for the PDF only, the \\A line-break escape (and why it\nneeds a TOML literal string, not a basic one), and a brief pointer to\nthe separate, non-prodockit mechanism for crediting the site on the\nwebsite's own footer (a Zensical custom_dir partials override).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Document how copyright/pdf_copyright work",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T21:38:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "46594e19df28957ea34432d849ff145b6234542e",
          "body": "project.copyright feeds both the live website's own copyright text and\nthe PDF's running footer - there was no way for a project to show\nsomething different in the PDF only. Added extra.pdf_copyright: unset\nby default (falls back to project.copyright, so every existing\nproject's PDF and website keep\n[…]\n under\nthe default white-space: normal. Added to both the single-sided\n@bottom-left copyright box and the double-sided verso @bottom-right one.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add an opt-in pdf_copyright override, PDF-only",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-23T21:31:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9f1af887f9735aa58afee8f9bd7f01e98e41ac67",
          "body": "Add cover page marker substitution to build_pdf_from_zensical_config()",
          "is_bot": false,
          "headline": "Merge pull request #84 from buckwem/upstream-cover-page-markers",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T19:20:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5915160674e3996f48d63b514f0dcf9b88fd3ed3",
          "body": "…onflicts)",
          "is_bot": false,
          "headline": "Merge origin/main into upstream-cover-page-markers (resolve version c…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T19:17:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d110f345dad24766577282b4fc1db503f13a47d",
          "body": "Drop the #only-dark half of a light/dark image pair from PDF output",
          "is_bot": false,
          "headline": "Merge pull request #83 from buckwem/drop-dark-mode-images-from-pdf",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T19:15:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27d0dc3f30532f520beed65557636b57e144caa4",
          "body": "build_css()'s own docs say copyright_text/site_name \"should already be\nCSS-content-string-safe\" before being passed in - it substitutes both\ndirectly into a content: \"...\" string with no escaping of its own.\nbuild_pdf_from_zensical_config() passed config.get(\"copyright\")/\nconfig.get(\"site_name\") str\n[…]\nker substitution (added earlier this\nbranch) is unaffected - it still uses the raw, unescaped value, since\nit's substituted into HTML, not CSS.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Escape copyright/site_name before passing to build_pdf()'s CSS",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T19:01:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "943c585f9c2da004ad3187a20d32fe5e6bae230f",
          "body": "build_pdf_from_zensical_config() only ever read project.extra_css (the\nwebsite's own stylesheet list) - a project wanting a stylesheet meant\n*only* for the PDF (e.g. a rule that would look wrong on the live\nwebsite, like a cover-page-only override) had no way to add one short\nof hardcoding a second \n[…]\nxtra_css rule) - found while migrating\nprodockit-template off its own build_pdf.py, which hardcoded loading a\nsecond \"print.css\" file this way.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add pdf_extra_css for PDF-only stylesheet overrides",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T18:40:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6fa18004bd796b7746e3ee58177aa27a7521f47b",
          "body": "Adds {WORDCOUNT}/{REPOURL}/{RELEASE}/{{ site_name }} marker support to\n`prodockit pdf` (build_pdf_from_zensical_config()), so a project no\nlonger needs its own custom Python just to fill in a cover page's word\ncount, repo URL, or release tag - found via prodockit-template, whose\nbuild_pdf.py had shr\n[…]\nonce\ncompiled into the PDF's own temporary work directory - now resolved and\nbase64-embedded, matching how a local <img> reference already was.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add cover page marker substitution to build_pdf_from_zensical_config()",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T18:33:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6575a73189bfc503ca8ecb428b99af13424507c4",
          "body": "fix_up_page_html() base64-embeds every local <img> into the PDF's HTML\nso it doesn't depend on relative paths resolving from wherever Pandoc\nhappens to run. For a #only-light/#only-dark pair (mkdocs-material/\nZensical's website light/dark toggle convention), to_base64_data_uri()\nalready strips anyth\n[…]\ne source rather than\nonly in the one pipeline that happened to expose it.\n\nAlso updates docs/pdf.md's \"PDF differences vs the website\" section.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Drop the #only-dark half of a light/dark image pair from PDF output",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T18:08:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8b4d4a7d6c044b52f0f1455277bb744baeb8c1ae",
          "body": "Bump to 0.6.6",
          "is_bot": false,
          "headline": "Merge pull request #82 from buckwem/release-0.6.6",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T17:32:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "df7a0907a64c013d047ee68bcada399f942645db",
          "body": "Docs-only visual consistency fix (hero graphic/button/index-letter\ncolour) plus the one prodockit.pdf.css constant change - see the\nchangelog for details.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.6.6",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T17:32:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6956cd99c89b22612a79dce6c94c7e916bdcd361",
          "body": "Make the hero graphic, PDF download button, and index letter all the same green",
          "is_bot": false,
          "headline": "Merge pull request #81 from buckwem/green-hero-and-index-color",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T17:28:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "afc9d38555cf9fb973b8dadf3004a554e46effce",
          "body": "…ter all the same green\n\n- docs/assets/cover-hero-light.svg previously used a blue palette while\n  cover-hero-dark.svg used green - recoloured light to match dark exactly\n  (identical path data/stroke-width/opacity, only the stroke colours\n  changed), so the hero graphic reads the same regardless of\n[…]\nto #22c55e to match the\n  now-green hero graphic a PDF always shows (light variant, regardless of\n  a project's own website light/dark toggle).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Make the light-theme hero graphic, PDF download button, and index let…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T10:11:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "273965fa2bc5ca28026718c8a6a3d45fa8e394ac",
          "body": "Fold running-header fix into the 0.6.5 changelog entry",
          "is_bot": false,
          "headline": "Merge pull request #79 from buckwem/changelog-0.6.5-include-header-fix",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:16:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d4b143e077208c555d664a6fa27fbe09deb6895",
          "body": "Fix ruff line-length violation in source_bundle.py",
          "is_bot": false,
          "headline": "Merge pull request #80 from buckwem/fix-ruff-line-length-source-bundle",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:16:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9502cd6124751dba1b2dd5d866d401ce31484fcd",
          "body": "Wrapped the combined dir/file exclusion check onto multiple lines - it\nwas 103 characters, 3 over ruff's configured 100-character limit, and\nbroke CI on main after PR #78 merged (E501). Verified locally this time:\nruff, mypy, and the full test suite (406/406) all pass.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix ruff line-length violation in source_bundle.py",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:15:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e4d3315ad7927b56645d5c340411861bbb52d64b",
          "body": "PR #77 (fix source_bundle.pdf's running header naming the wrong file)\nmerged to main alongside the styles/lockfile exclusion work, under the\nsame 0.6.5 version bump, but wasn't mentioned in the changelog entry -\nadd it so the release notes cover everything actually shipping in 0.6.5.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fold the running-header fix (#77) into the 0.6.5 changelog entry",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:13:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bd5177632b6fe3567e8dec08dfd6c5550ad51a32",
          "body": "…-from-source-bundle\n\nExclude Vale styles and dependency lockfiles from PDF source bundles",
          "is_bot": false,
          "headline": "Merge pull request #78 from buckwem/exclude-vale-styles-and-lockfiles…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:08:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9f135c055f654637523564decbd1f0baead8aa3a",
          "body": "…ndary\n\nFix source_bundle.pdf's running header naming the wrong file",
          "is_bot": false,
          "headline": "Merge pull request #77 from buckwem/fix-source-bundle-header-page-bou…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:07:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad085edb6a7c82f2e4538c7eb123f8929a7febd2",
          "body": "Extends the 0.6.4 always-excluded-directory mechanism in\nprodockit.pdf.source_bundle beyond .icons:\n\n- Any directory literally named `styles` - a Vale StylesPath\n  (conventionally named this way) holds downloaded rule packs\n  (Microsoft/proselint/Readability-style .yml files), typically tracked\n  fo\n[…]\ncontent.\n\nNeither exclusion is project-configurable, matching .icons: a project\ncan't reach for the same knob to narrow what a bundle archives.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Exclude Vale styles and dependency lockfiles from PDF source bundles",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:02:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "db52ce8137f00b0ec80ab73ff50bc26fe989d2db",
          "body": ".file-marker (which sets the string-set: current-file CSS string used\nby the @top-right running header) had no page-break of its own - only\nthe following <pre> did. That let a file's own marker render on the\n*previous* file's last page, right at the tail end just before the\nbreak, so that page's hea\n[…]\nfile long enough to\nspan several pages had its own last page mislabeled with the next\nfile's name; fixed, and covered by a new regression test.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix source_bundle.pdf's running header naming the wrong file",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T09:01:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "692eca62da3ea5ea0cc661e2899604e5c5b3e9d9",
          "body": "prodockit.pdf.source_bundle relied entirely on .gitignore to decide\nwhat belongs in source_bundle.pdf, but a project's own custom_icons\ndirectory (pymdownx.emoji's own convention) is typically *tracked* -\nneeded for the site/PDF to build at all - so .gitignore alone can't\nkeep a vendored icon pack o\n[…]\nthe discover_source_files() and\nbuild_source_bundle() level (nested and top-level .icons, and that\n.gitignore has no bearing on it either way).\n\nCo-authored-by: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Always exclude vendored .icons directories from the source bundle (#76)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T08:46:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ea757c23aaabdf026ef4cd0dd50ee56b4734bece",
          "body": "…cement\n\nVerify the back-of-book index starts on a recto page under double_sided",
          "is_bot": false,
          "headline": "Merge pull request #75 from buckwem/test-double-sided-index-recto-pla…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T08:46:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe128c6845b29f7b5652c5ff1336de00e3e6dc85",
          "body": "Checked directly with a real pandoc+weasyprint build (chapter1/chapter2\neach long enough to force page breaks, double_sided=True,\ninclude_index=True): every recto-forced heading, including the\n.unnumbered Index trigger heading, correctly lands on an odd page.\nThis was flagged as an untested interact\n[…]\npandoc+weasyprint\nactually being installed) plus a docstring note on the existing CSS-level\ntest explaining why the exact-string match matters.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Verify the back-of-book index starts on a recto page under double_sided",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-21T08:21:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "420380d8819c103d0b73e1dea02ab6fef6906be8",
          "body": "Bump to 0.6.3",
          "is_bot": false,
          "headline": "Merge pull request #74 from buckwem/release-0.6.3",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:57:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d2004ce2fd6d584bc31216680af2318947a1a4d",
          "body": "Bug fixes found by an in-depth test-coverage review of the extensions\nand PDF pipeline test suites - see the changelog for the full list.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.6.3",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:56:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c748ed20f0773ffb452ed5bba015ccd804eb85ae",
          "body": "Document and test config.py's CWD-relative path resolution",
          "is_bot": false,
          "headline": "Merge pull request #73 from buckwem/test-config-cwd-relative-paths",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:51:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b399dd7e1d72c8044fb4936ad75960c47a6551b4",
          "body": "Add misc PDF pipeline edge-case tests (icons/rotate/html/css)",
          "is_bot": false,
          "headline": "Merge pull request #72 from buckwem/add-pdf-pipeline-misc-tests",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:50:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1355033eb724642c4914cd4bb213fa6799a26417",
          "body": "Add heading_counter_reset() branch tests for zensical_macros.py",
          "is_bot": false,
          "headline": "Merge pull request #71 from buckwem/add-zensical-macros-branch-tests",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:50:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ffe2c4ad259b133a5288791964433931b61d4bcc",
          "body": "Add tables.py nested and multiple-table tests",
          "is_bot": false,
          "headline": "Merge pull request #70 from buckwem/add-tables-nested-multiple-tests",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:49:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74bac542e43ff4ec4a30a1d33f0225b6f94c47eb",
          "body": "Add malformed-input tests for citations.py/glossary.py",
          "is_bot": false,
          "headline": "Merge pull request #69 from buckwem/add-malformed-input-tests",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:49:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ac4e8f0683d2d021b742bd2c3167b2076027683",
          "body": "…-tests\n\nAdd direct util.py tests and missing nested cross-page href coverage",
          "is_bot": false,
          "headline": "Merge pull request #68 from buckwem/add-registry-and-nested-crosspage…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:48:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "56decad56e822479dea7ec162296e457b5eea640",
          "body": "Clamp index entry indent level at the deepest CSS rule",
          "is_bot": false,
          "headline": "Merge pull request #67 from buckwem/fix-pdf-index-depth-cap",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:48:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "940084ec8c7da7fd8ccd85c3dcd36d89f65cda3e",
          "body": "Add a timeout to the pandoc/WeasyPrint subprocess call",
          "is_bot": false,
          "headline": "Merge pull request #66 from buckwem/add-pandoc-subprocess-timeout",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:47:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21991ad48e78eac084979a778e50710bc64f4f30",
          "body": "Escape math_dir/tex2svg_script when embedding them in the Lua filter",
          "is_bot": false,
          "headline": "Merge pull request #65 from buckwem/fix-lua-path-escaping",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:46:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd81b3f1149577e449e1aaa6b561731abb694c1f",
          "body": "Skip files invalid past is_probably_text's 8 KiB sniff window",
          "is_bot": false,
          "headline": "Merge pull request #64 from buckwem/fix-source-bundle-unicode-decode",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:46:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d695573ba1fa24e0bd549414c44409abae8bc010",
          "body": "Catch OSError in render_mermaid_diagram, not just CalledProcessError",
          "is_bot": false,
          "headline": "Merge pull request #63 from buckwem/fix-mermaid-oserror",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:45:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "629a1d82bf686cfd9b4093f3390a9cbd9e31a10e",
          "body": "Backfill skipped heading levels instead of numbering them 0",
          "is_bot": false,
          "headline": "Merge pull request #62 from buckwem/fix-headings-numbering-edge-cases",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:44:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c2c0f8d01f0899e2ca96fdd4ef30d59d48c02e2d",
          "body": "_find_mmdc_bin/_find_tex2svg_script resolve a relative\npdf_mmdc_bin/pdf_tex2svg_script against the current working directory,\nnot wherever config_path itself lives - fine for the common case of\nrunning `prodockit pdf` from the project root, but an untested footgun\nfor `-f`/`--config-file` pointing a\n[…]\nnged - the\nfix (resolving against config_path's own directory instead) needs a\nfirmer read on backward-compatibility impact before changing it.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Document and test config.py's CWD-relative path resolution",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:33:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "158cce338d31a2d1f0e76a5c7661802dc6302672",
          "body": "Pure test-coverage additions, no behavior changes:\n\n- discover_icon_dirs() had zero coverage; build_icon_registry()'s\n  documented collision priority (earlier dir wins for derived short-form\n  keys, later dir wins for the primary slug key) was unverified.\n- rotate.py's documented \"anything pypdf can\n[…]\nns that copyright_text/site_name must\n  already be CSS-string-safe, but nothing demonstrated the actual\n  corruption an unescaped quote causes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add misc PDF pipeline edge-case tests (icons/rotate/html/css)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:30:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "19e6cbf48f92d407d56e7687c70f796d4efe2a03",
          "body": "Only the disabled-config and outside-a-real-build fallback branches\nhad tests - the appendix-letter CSS branch and the \"real build,\nnon-appendix page with n>0\" branch (continuing numbering from earlier\nnav pages) had zero coverage.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add heading_counter_reset() branch tests for zensical_macros.py",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:25:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "50c9121f8e72f47c5ca1438406109c68bc15d615",
          "body": "No test confirmed a table nested inside an admonition (a realistic\ncombination given how the docs use both together) is still found and\nsized, or that multiple tables in one document - some widthed, some\nnot, with different widths - are each handled independently with no\ncross-contamination.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add tables.py nested and multiple-table tests",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:23:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7555c251cebad5f761c46d419c458f0dbf34f1e5",
          "body": "citations.py's graceful comma-split handling (empty segments from a\nleading/trailing/double comma), an id-less data-cite-text/data-term\nelement being stripped but not registered, and an empty \\gls{} call\nwere all untested defensive/boundary paths.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add malformed-input tests for citations.py/glossary.py",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:21:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c3d1294b946be1fd1225e4d610e6e3aca9f2b991",
          "body": "prodockit.util's IdRegistry/CitationRegistry/GlossaryRegistry/\ncross_page_href had no direct test_util.py at all - only indirect\ncoverage via the extensions that use them. Also, refs.py and glossary.py\nboth lacked the nested-subdirectory cross-page href test that\ncitations.py/bibliography.py each already have.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add direct util.py tests and missing nested cross-page href coverage",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:19:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f7b7c4c94b016cbc36e1a5f8c73e608da4edc66f",
          "body": "prodockit.pdf.css only defines an indent step up to\ndiv.prodockit-index-level-3 - a 4th nesting level\n(\\index{Parent!Child!Grandchild!GreatGrandchild}) rendered with an\nunstyled prodockit-index-level-4 class, silently landing flush with the\ntop level instead of the deepest available indent. render_index_content()\nnow clamps at MAX_RENDERED_INDEX_LEVEL (3).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Clamp index entry indent level at the deepest CSS rule",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:16:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9b561d92710dade636a5eedcb2329105e718d2e0",
          "body": "run_pandoc() had no timeout= on subprocess.run at all, so a hung\npandoc/WeasyPrint invocation (e.g. a pathological CSS layout) blocked\nthe whole build indefinitely with no way to recover. Added a\npandoc_timeout parameter (default 1800s/30 minutes, generous for any\nreal document; pass None to disable) that raises a clear PdfBuildError\non expiry instead.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add a timeout to the pandoc/WeasyPrint subprocess call",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:13:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "714a097f7b15316c7fe504497915cca906d3a2e9",
          "body": "Both paths were interpolated straight into a double-quoted Lua string\nliteral with no escaping - a path containing a literal \" or an\nunescaped \\ (e.g. a Windows-style path) produced syntactically broken\nLua, only discoverable at real pandoc runtime.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Escape math_dir/tex2svg_script when embedding them in the Lua filter",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:10:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c28657c9a9d79dd914c83d31a7584c07f9c15ebd",
          "body": "is_probably_text() only sniffs the first 8 KiB of each candidate file,\nbut build_source_bundle() then read the whole file as UTF-8 with no\nerror handling - a file valid in its sniffed prefix but not further in\n(a stray invalid byte, or a multi-byte character split at the boundary)\nraised an uncaught\n[…]\njust skipping that one file the way an outright binary file\nalready is. Also added a test for the (previously untested) empty-\nrepository case.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Skip files invalid past is_probably_text's 8 KiB sniff window",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:08:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4c750b63a1d59aa75f9dc6d99c21783e3b966539",
          "body": "A non-executable mmdc_bin (permission bits, or a directory mistakenly\nconfigured as the binary path) makes subprocess.run raise\nPermissionError/OSError directly, not CalledProcessError - this was\npreviously uncaught, contradicting this module's own \"one bad diagram\ncan't fail an entire build\" promise.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Catch OSError in render_mermaid_diagram, not just CalledProcessError",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:05:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5b08123e3a38e798ad2409374910a0ef9f5a7688",
          "body": "HeadingsTreeprocessor left a shallower level's counter at 0 whenever no\nheading of that level had appeared yet - a document skipping straight\nfrom h1 to h3, starting below h1, or nesting a numbered heading under\nan .unnumbered one all produced a number with a literal \"0\" segment\n(e.g. \"1.0.1\" or \"0.\n[…]\ny such missing shallower level to 1\nbefore incrementing the current one, so the number always reads as a\nsensible implicit first level instead.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Backfill skipped heading levels instead of numbering them 0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T22:01:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c098eb7eeaf2b13442c229262012f15713b86c35",
          "body": "Catch SourceBundleError in the pdf CLI command",
          "is_bot": false,
          "headline": "Merge pull request #61 from buckwem/fix-cli-source-bundle-error",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T21:55:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf90f5d8b1d1b0ffe2a39740efb2f9d64612c313",
          "body": "build_pdf_from_zensical_config() calls build_source_bundle() directly\nwhen pdf_source_bundle is enabled, but SourceBundleError (a plain\nRuntimeError subclass) wasn't in the CLI's caught exception tuple - a\nfailed bundle build (e.g. git missing, or the project root not being a\ngit working tree) crashed with a raw traceback instead of exiting\ncleanly with an Error: message like every other build failure.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Catch SourceBundleError in the pdf CLI command",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T21:54:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "efeeaf878c4c1bc154c7af3e6e323cdf2b57b8e3",
          "body": "Fix stash-placeholder leak in docs (bump to 0.6.2)",
          "is_bot": false,
          "headline": "Merge pull request #60 from buckwem/fix-docs-index-syntax-leak",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T20:18:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c8f49d9cdf7c42ec3229ad3c25f110c3c3c48af8",
          "body": "… guard\n\nInvestigated further and found the real trigger: pymdownx.inlinehilite\n(this project's own zensical.toml, and almost certainly any real Zensical\nproject's) replaces Python-Markdown's plain 'backtick' inline pattern\nwith its own - same priority and registry name, but a different\nimplementati\n[…]\nut the placeholder's name\nas an example, indistinguishable from a real leak once rendered - reworded\nto describe it without the literal string.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add regression tests for the stash-placeholder leak, plus a repo-wide…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T20:17:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d731221c8ec474d3c6889a52ee2ed9fa4bd6b52e",
          "body": "Fixed a real bug found by checking the live site after 0.6.1: several\nspots in docs/extensions/index-terms.md, docs/pdf.md, and this project's\nown changelog tried to show the code-styled \\index{} syntax as literal\nexample text using inline backticks around a hierarchical, code-styled\npath (e.g. `\\in\n[…]\nk or reworded to avoid\nthe literal example entirely. Verified end-to-end: rebuilt the site\nlocally and confirmed no placeholder leaks anywhere.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.6.2",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T20:06:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a2b47468e591a87256aac95f2ac56a893641ea66",
          "body": "Add prodockit.index to README/PyPI metadata (bump to 0.6.1)",
          "is_bot": false,
          "headline": "Merge pull request #59 from buckwem/readme-add-index-extension",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:33:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b7eb00b4e82cd681a756e1b25476a6f2f7aa582",
          "body": "Add prodockit.index (new in 0.6.0) to README.md, pyproject.toml's own\ndescription (PyPI's summary line), and __init__.py's module docstring -\nall three had the same gap, matching the exact oversight this project\nalready fixed once before for prodockit.tables/prodockit.bibliography\n(see the 0.3.1 changelog entry).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.6.1",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:31:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b97bef823f884b4920898f9ae4149d5c38778ee2",
          "body": "Bump to 0.6.0",
          "is_bot": false,
          "headline": "Merge pull request #58 from buckwem/bump-0.6.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:23:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a902873b6d92f0ac930f428dfc363fbb058fbda",
          "body": "New back-of-book index (\\index{Term}, #55/#57): hierarchical sub-entries,\ncode-styled terms, and the pdf_include_index/pdf_index_title two-pass PDF\nbuild behind it - see the changelog for the full feature list.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump to 0.6.0",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:22:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e20632fd3a7e0cd95eba7306e5d43ccd20c173f7",
          "body": "Add a back-of-book style Index, PDF-only",
          "is_bot": false,
          "headline": "Merge pull request #57 from buckwem/back-of-book-index-55",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:18:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee0d8f51c40dffae774da565520652cc1452f562",
          "body": "While reviewing test coverage, found that \\index{`Git`!commit} (an\nunsupported combination - code-styling isn't meant to work on anything\nbut the last segment) didn't just fail to work, it actively corrupted\nthe output: INDEX_CODE_RE only matched a backtick pair immediately before\nthe closing }, so \n[…]\non-\nprefixed terms that share a sort key but stay separate entries, and a\npurely-punctuation term exercising _sort_key()'s own fallback branch.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix a real bug: code-styling a non-last segment corrupted the term",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:17:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6967386c09ecac4b02d12cad007b43db0490be9",
          "body": "- test_term_as_a_raw_html_link_preserves_target_blank: confirms the\n  documented raw <a target=\"_blank\"> workaround (for when attr_list\n  can't combine cleanly with a linked term) keeps the attribute intact.\n- test_term_works_inside_an_admonition /\n  test_mark_index_terms_finds_a_term_nested_inside_\n[…]\nwn span lookup already\n  work correctly regardless of the surrounding <div class=\"admonition\">\n  wrapper, checked directly rather than assumed.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add tests for target=\"_blank\" preservation and admonition-nested terms",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:08:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9d24c8a69dc2ea9c34853d18b53dd1255568a6c2",
          "body": "Letter headings (A, B, C...) now use #1e3a8a - the innermost, most\nsaturated ring of prodockit-template/prodockit-userguide's own shared\ncover page hero graphic (docs/assets/cover-hero-light.svg) - replacing\nthe arbitrary brick red picked earlier. Confirmed directly against a\nreal rendered PDF that \n[…]\nhe attribute's own braces confuse \\index{}'s regex if\nplaced inside) - a raw inline <a target=\"_blank\"> tag is the workaround,\nalso documented.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Index letter headers match the hero graphic; document linked terms",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T19:02:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "35e2e65233fdc07aede541499891670b9f7be078",
          "body": "Backticks around a term's last segment - \\index{`git commit`}, or\ncombined with hierarchy, \\index{Git!`git commit`} - mark it as a\ncommand/code term: it displays inline in a real <code> element, and the\ngenerated index entry renders the same way, picking up whatever code {}\nstyling a project already\n[…]\ns, chmod, grep) -\nconfirmed both the built PDF and the live website render each one\ncode-styled, in the prose and in the generated index alike.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Support code-styled index terms: \\index{`Term`}",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T18:50:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8adb698a5d6eaf82ed7a9591e7540975c54c7363",
          "body": "Full back-of-book index spec: \\index{Parent!Child!Grandchild} (matching\nLaTeX makeidx's own long-established convention) nests up to three levels\ndeep, each level indented a fixed 12pt step; consecutive pages collapse\ninto an en-dash range (\"67–70\") rather than listing every page; and a\nterm alphabe\n[…]\netic build exercising all of the above\n(hierarchy, ranges, punctuation sorting) plus a real rebuild of\nprodockit-userguide's own 18-term index.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add hierarchical sub-entries and page-range formatting to the index",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T17:26:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "da2114699ca567e93705b2e4c24e51b8e20ed3ac",
          "body": "Matches a traditional printed book's own index layout: a bold letter\nheading (A, B, C, ...) per group, entries below as \"Term, page, page\"\n(comma-separated, not colon), the whole thing in two columns (WeasyPrint's\nCSS Multi-column support, confirmed directly to paginate correctly).\n\nLetter headings \n[…]\nied end-to-end against prodockit-userguide's real 18-term index: the\nbuilt PDF's Index page renders exactly as intended, letter groups and all.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Lay out the back-of-book index in two columns with letter headings",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T16:34:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c35615b5b9390e89033921d77a8712915fb8925",
          "body": "New capability, off by default (pdf_include_index = true under\n[project.extra] to turn it on): a traditional back-of-book index - an\nalphabetised list of terms with the page number(s) they appear on -\nappended at the very end of the PDF.\n\nMarker syntax needed real thought (per the issue's own reques\n[…]\nntent,\nconfirmed the generated index page correctly showed the right terms,\ncorrectly merged case-insensitive duplicates, and correctly resolved to\nthe right (and correctly deduplicated) page numbers.",
          "is_bot": false,
          "headline": "Add a back-of-book style Index, PDF-only (#55)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-20T11:10:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a1c1c11d2ed1d802357a2e25bc9e573bd377af6c",
          "body": "New prodockit.pdf.source_bundle feature (#50), plus the PDF-icon action\nbutton (#49).",
          "is_bot": false,
          "headline": "Bump to 0.5.0 (#53)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-19T10:32:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a8b2d9aba244cdb6d513278c83721ae228c36639",
          "body": "…(#52)\n\nNew optional capability, off by default (pdf_source_bundle = true under\n[project.extra] to turn it on): bundles every text/source file\n.gitignore doesn't exclude into a single source_bundle.pdf at the\nproject's own top-level directory (not docs_dir) - 8pt Courier, wrapped\nlines, each file st\n[…]\nges) and checked the rendered output: correct per-file page\nbreaks, correct header/footer on the first and last page, and confirmed\nno .venv/site/.git content or the PDF itself leaked into the bundle.",
          "is_bot": false,
          "headline": "Add prodockit.pdf.source_bundle: bundle repo source into a PDF (#50) …",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-19T10:26:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4daf176de498afe3d2005510e170e06fbf198d1",
          "body": "…#51)\n\nAdds overrides/partials/actions.html - a customised copy of Zensical's\nown bundled partials/actions.html (requires custom_dir = \"overrides\",\nnewly added to zensical.toml) - with a fourth action icon next to\nedit/view: a direct link to this page's own per-page PDF (see\n.github/workflows/docs.y\n[…]\n(showing prodockit\nusers the generic convention, not this site's own specific\nimplementation) is left as-is - still accurate on its own terms,\nunrelated to this project's own template-override choice.",
          "is_bot": false,
          "headline": "Show a PDF download icon next to \"view\", not a page-body link (#49) (…",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-19T09:53:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce0a4ebb92a5696eadc693185f90b52b553743ae",
          "body": "Theme config parity fixes with prodockit-userguide (#47).",
          "is_bot": false,
          "headline": "Bump to 0.4.2 (#48)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-18T23:28:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6c3d8159ba7ed4d1d13498d78504946ea919a057",
          "body": "* Show the actual GitHub logo in the header, not the generic Git icon\n\nMissing theme.icon.repo left Zensical's default in place (FontAwesome's\n\"git\" icon - confirmed directly by decoding the rendered header's own\nSVG path, matching git.svg's path exactly, not github.svg's) - matches\nprodockit-usergu\n[…]\ns through\nthere too.\n\nLeft theme.custom_dir (\"overrides\") out - userguide's only use for it\nis a custom GitLab icon this project's own docs never reference, so\nthere's nothing for it to point at here.",
          "is_bot": false,
          "headline": "Show the actual GitHub logo in the header (#47)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-18T23:23:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5489c2c19ea4b42daba5f220709192b15096e1e0",
          "body": "Docs/site chrome rework and PDF footer copyright fix (#42/#45).",
          "is_bot": false,
          "headline": "Bump to 0.4.1 (#46)",
          "author_name": "Mark Buckwell",
          "author_login": "buckwem",
          "committed_at": "2026-07-18T23:00:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 36,
      "commits_last_year": 154,
      "latest_release_at": "2026-07-25T07:53:50Z",
      "latest_release_tag": "prodockit-v0.10.2",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 2,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 0.4
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "prodockit",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "extension",
            "markdown",
            "pandoc",
            "pdf",
            "python-markdown",
            "zensical",
            "Development Status :: 3 - Alpha",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: MIT License",
            "Programming Language :: Python :: 3",
            "Topic :: Text Processing :: Markup :: Markdown"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/prodockit/",
          "is_deprecated": false,
          "latest_version": "0.10.2",
          "repository_url": "https://github.com/buckwem/prodockit-extensions",
          "versions_count": 25,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-07-17T09:39:06.154273Z",
          "latest_published_at": "2026-07-25T07:54:31.917207Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 8
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "src/prodockit/py.typed"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 44300,
      "source_files_sampled": 51,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "pyproject.toml"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "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": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "pypi"
      ],
      "dependencies": [
        {
          "name": "Markdown",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=3.4"
        },
        {
          "name": "zensical",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "beautifulsoup4",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=4.12"
        },
        {
          "name": "click",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=8.0"
        },
        {
          "name": "pypdf",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=4.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 65,
        "open_issues": 8,
        "closed_ratio": 0.724,
        "closed_issues": 21,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "buckwem",
          "commits": 157,
          "avatar_url": "https://avatars.githubusercontent.com/u/53193258?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "docs.yml",
        "publish.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "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": 5,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "8 out of 8 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": 0,
            "reason": "Found 0/20 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "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": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "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": "01704d39b624eb13575933cabd2416307555476d",
        "ran_at": "2026-07-25T07:56:09Z",
        "aggregate_score": 4,
        "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-25T07:54:36Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-25T07:49:05Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 55,
          "created_at": "2026-07-11T18:42:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 7,
          "created_at": "2026-07-15T17:50:30Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 9,
          "created_at": "2026-07-15T18:21:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 49,
          "created_at": "2026-07-19T09:35:39Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 50,
          "created_at": "2026-07-19T09:40:01Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 54,
          "created_at": "2026-07-19T22:41:40Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 56,
          "created_at": "2026-07-20T10:03:27Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 91,
          "created_at": "2026-07-24T20:43:10Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/buckwem/prodockit-extensions",
    "host": "github.com",
    "name": "prodockit-extensions",
    "owner": "buckwem"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 52,
      "inputs": {
        "security": 40,
        "vitality": 73,
        "community": 24,
        "governance": 50,
        "engineering": 67
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 73,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "commits_last_year": 154,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 2
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "2/52 weeks with commits",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "154 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 154
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "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": 100,
            "inputs": {
              "releases_count": 36,
              "latest_release_tag": "prodockit-v0.10.2",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 0.4
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "36 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 36
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.4 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.4
                    }
                  }
                ],
                "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": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "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 (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 50,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "merged_prs": 65,
              "open_issues": 8,
              "closed_issues": 21,
              "issue_closed_ratio": 0.724,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "72% of issues closed",
                "points": 33.8,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 72
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "65/65 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 65,
                      "decided": 65
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/20 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 36,
            "inputs": {
              "followers": 1,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "buckwem",
              "public_repos": 3,
              "account_age_days": 2559
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "1 followers of buckwem",
                "points": 2.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 1,
                      "login": "buckwem"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "3 public repos, account ~7 yr old",
                "points": 16.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 3
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 7
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "prodockit"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "25 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 25
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 67,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "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": "at_risk",
        "name": "Security",
        "value": 40,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 40,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 4
            },
            "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": "branch protection is not maximal on development and all release branches",
                "points": 3.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 8 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 0/20 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "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": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "excellent",
            "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"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "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": "at_risk",
        "name": "AI Readiness",
        "value": 49,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "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": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "src/prodockit/py.typed"
              ],
              "agent_commit_share": 0.57,
              "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "src/prodockit/py.typed",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "src/prodockit/py.typed"
                    }
                  }
                ],
                "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": "57 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 57,
                      "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": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "good",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 44300,
              "source_files_sampled": 51,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python with type-check config (src/prodockit/py.typed)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "src/prodockit/py.typed",
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/51 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 51,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index pypi:prodockit@0.10.2; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-25T07:56:21.564621Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/b/buckwem/prodockit-extensions.svg",
  "full_name": "buckwem/prodockit-extensions",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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 v1.13.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenPyPI.