Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 2.5.0 · 2026-08-02 11:04 UTC

dinho149 / yeaboi.ai

yeaboi — AI Scrum Master in your terminal: sprint planning, daily standups, team retros, 1:1s & delivery reports, synced with Jira, Azure DevOps, GitHub, Confluence and Notion

PythonMIT★ 2 Sterne⑂ 0 Forksseit März 2026Auf GitHub ansehen ↗
ArtBibliothekMCP-ServerWeboberflächewie das ermittelt wird

dinho149/yeaboi.ai erreicht einen Gesundheitsindex von 75 von 100 und liegt damit im Bereich Gut. Am stärksten schneidet es bei Engineering Quality (100/100) ab, am schwächsten bei Community & Adoption (33/100). Zuletzt heute aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

75
gesamt / 100
Gut

Software-Gesundheitsindex

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

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

Bewertungsprofil

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

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

Eigentümerschaft

DinhoPersönliches Konto
3 Follower38 öffentliche Reposseit Mai 2020

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
PyPIyeaboi2.47.15.32948vor 0 Tagenagileai-agentai-scrum-masterazure-devopsclijirallmmcpplanning-pokerproject-managementretrospectivescrumsprint-planningstanduptui

Metriken nach Kategorie

Vitalität

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

81Exzellent · 21 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 0 Tagen
4.8/36Commit-Rhythmus — 7/52 Wochen mit Commits
18/18Commit-Volumen — 442 Commits im letzten Jahr
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Verwendete Eingangsdaten
commits_last_year442
human_commit_share0,99
days_since_last_push0
active_weeks_last_year7

Release-Disziplin

100Außergewöhnlich
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 66 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 0 Tagen
27/27Release-Rhythmus — ein Release etwa alle 0,7 Tage
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count66
latest_release_tagv2.47.1
releases_from_tagsnein
days_since_latest_release0
mean_days_between_releases0,7
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?

33Gefährdet · 17 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 2 Stars
0/25Forks — 0 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks0
stars2
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
readme_badges
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
readme_badge_services
has_pull_request_templatenein
Wie die Bewertung erfolgt
49.7/80Downloads pro Monat — 5.329 Downloads/Monat über pypi
0/20Abhängige in der Registry — von diesem Ökosystem nicht ausgewiesen
Verwendete Eingangsdaten
packagesyeaboi
dependents
ecosystemspypi
total_downloads
monthly_downloads5.329
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Abhängige in der Registry. Die verbleibenden Gewichte wurden renormalisiert.

Nachhaltigkeit & Governance

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

46Schwach · 23 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
7.8/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 65 % der Commits
4.1/13.5Breite der Beitragenden — 3 Beitragende
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Verwendete Eingangsdaten
bus_factor1
contributors_sampled3
top_contributor_share0,653
Wie die Bewertung erfolgt
0/42Issue-Lösungsquote — 0 % der Issues geschlossen
26.7/30PR-Annahme — 114/128 entschiedene PRs gemergt
0/13Newcomer PR acceptance — kein PR eines Erstbeitragenden in 30 Tagen entschieden
0/15OpenSSF Scorecard: Code-Review — Found 0/14 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs114
open_issues1
closed_issues0
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio0
closed_unmerged_prs14
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): newcomer_pr_acceptance. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
10/30Organisatorische Trägerschaft — persönliches (Nutzer-)Konto
0/20Verifizierte Domain — für Nutzerkonten nicht anwendbar
4.3/25Reichweite des Inhabers — 3 Follower von dinho149
23.6/25Kontohistorie — 38 öffentliche Repos, Kontoalter ca. 6 Jahre
Verwendete Eingangsdaten
followers3
owner_typeUser
is_verified
owner_logindinho149
public_repos38
account_age_days2.282
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Paketpflege

100Außergewöhnlich
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 — 48 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesyeaboi
ecosystemspypi
any_deprecatednein
min_days_since_publish0

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

100Außergewöhnlich · 19 % des Gesamtindex

Engineering-Praktiken

100Außergewöhnlich
Wie die Bewertung erfolgt
24/24CI-Workflows — 13 Workflow(s)
24/24Tests vorhanden
16/16Linter-Konfiguration — .eslintrc, .eslintrc.json
9.6/9.6Pre-Commit-Hooks
6.4/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 15 out of 15 merged PRs checked by a CI test -- score normalized to 10
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfigja
has_linter_configja
has_precommit_configja

Dokumentation

100Außergewöhnlich
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
15/15Dokumentations-/Homepage-Site — https://yeaboi.ai/
10/10Repository-Beschreibung
10/10Topics — 20 Topics
10/10Wiki
Verwendete Eingangsdaten
topicsagile, ai-agent, ai-scrum-master, azure-devops, claude, cli, jira, langgraph, llm, mcp, mcp-server, planning-poker, python, retrospective, scrum, scrum-master, sprint-planning, standup, terminal, tui
has_wikija
homepagehttps://yeaboi.ai/
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

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

59Mittel · 16 % des Gesamtindex
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 15 out of 15 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/14 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
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Lizenz — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
4/5SAST — SAST tool detected but not run on all commits
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — keine Daten
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
3.8/7.5Vulnerabilities — 5 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate5,9
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? Trägt ein bewusst kleines Gewicht (4 %): Agenten-Tooling ist ein echtes Pflegesignal, doch ein Repository ohne jedes Signal kann weiterhin 100/100 erreichen.

82Exzellent · 4 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 99 von 99 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes18.378
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile, desktop-pet/node_modules/json-stringify-safe/Makefile, desktop-pet/node_modules/progress/Makefile
22/22Automatisierte Tests
11/11Lint-/Format-Konfiguration — .eslintrc, .eslintrc.json
11/11Statische Typprüfung — desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json
10/10Reproduzierbare Umgebung — lockfile
10/10Belegte Agentenpraxis — 90 der letzten 100 Commits von Agenten verfasst oder ihnen zugeschrieben
8/8Automatisierte Wartung — 1 der letzten 100 Commits sind automatisierte Abhängigkeits-Updates
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfilespackage-lock.json, uv.lock, yarn.lock
has_dockerfilenein
typed_languagenein
bootstrap_filesMakefile, desktop-pet/node_modules/json-stringify-safe/Makefile, desktop-pet/node_modules/progress/Makefile
has_devcontainernein
has_linter_configja
typecheck_configsdesktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json
agent_commit_share0,9
toolchain_manifests
dependency_bot_commit_share0,01
Wie die Bewertung erfolgt
27/45Typprüfbarer Code — Python mit Typprüfungs-Konfiguration (desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json)
53/55Handhabbare Dateigrößen — 25/688 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languagePython
largest_source_bytes584.773
source_files_sampled688
oversized_source_files25
Wie die Bewertung erfolgt
0/40API-Schema (OpenAPI/GraphQL/proto)
20/20MCP-Server
40/40Lauffähige Beispiele — example
Verwendete Eingangsdaten
example_dirsexample
has_mcp_signalja
api_schema_files

Eckdaten

2GitHub-Sterne
3Mitwirkende
442Commits, letzte 12 Monate
0Tage seit letztem Push
66Releases
1Bus-Faktor
1offene Issues
npm, PyPIPaket-Ökosysteme

Warnungen zur Datenerhebung

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index pypi:yeaboi@2.47.1; advisories assessed against the repository dependency graph instead

Weitere Details

OpenSSF Scorecard 5.9 / 10
5.9Gesamtwert

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-08-02 11:04 UTC

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests15 out of 15 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/14 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
8SASTSAST tool detected but not run on all commits
10Security-Policysecurity policy file detected
k. A.Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
5Vulnerabilities5 existing vulnerabilities detected
Direkte Abhängigkeiten 15
RegistryPaketVersionsvorgabeManifest
npmpreact^10.29.1frontend/package.json
PyPIlangchainpyproject.toml
PyPIlanggraphpyproject.toml
PyPIlangchain-anthropicpyproject.toml
PyPIrichpyproject.toml
PyPIprompt-toolkitpyproject.toml
PyPIpython-dotenvpyproject.toml
PyPIPyGithubpyproject.toml
PyPIazure-devopspyproject.toml
PyPIjirapyproject.toml
PyPIatlassian-python-apipyproject.toml
PyPInotion-clientpyproject.toml
PyPIlanggraph-checkpoint-sqlitepyproject.toml
PyPIholidayspyproject.toml
PyPIsegnopyproject.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": [
        "agile",
        "ai-agent",
        "ai-scrum-master",
        "azure-devops",
        "claude",
        "cli",
        "jira",
        "langgraph",
        "llm",
        "mcp",
        "mcp-server",
        "planning-poker",
        "python",
        "retrospective",
        "scrum",
        "scrum-master",
        "sprint-planning",
        "standup",
        "terminal",
        "tui"
      ],
      "is_fork": false,
      "size_kb": 38833,
      "has_wiki": true,
      "homepage": "https://yeaboi.ai/",
      "languages": {
        "CSS": 165125,
        "HTML": 209470,
        "Shell": 15318,
        "Python": 9173996,
        "Makefile": 9153,
        "JavaScript": 1699,
        "TypeScript": 848962
      },
      "pushed_at": "2026-08-02T11:01:10Z",
      "created_at": "2026-03-17T04:31:30Z",
      "owner_type": "User",
      "updated_at": "2026-08-02T10:58:39Z",
      "description": "yeaboi — AI Scrum Master in your terminal: sprint planning, daily standups, team retros, 1:1s & delivery reports, synced with Jira, Azure DevOps, GitHub, Confluence and Notion",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Python",
      "significant_languages": [
        "Python"
      ]
    },
    "owner": {
      "blog": "https://medium.com/@dinho149",
      "name": "Dinho",
      "type": "User",
      "login": "dinho149",
      "company": null,
      "location": "London",
      "followers": 3,
      "avatar_url": "https://avatars.githubusercontent.com/u/64692956?v=4",
      "created_at": "2020-05-02T13:26:36Z",
      "is_verified": null,
      "public_repos": 38,
      "account_age_days": 2282
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.47.1",
          "kind": "patch",
          "published_at": "2026-08-02T11:01:11Z"
        },
        {
          "tag": "v2.47.0",
          "kind": "minor",
          "published_at": "2026-08-01T10:04:54Z"
        },
        {
          "tag": "v2.46.0",
          "kind": "minor",
          "published_at": "2026-07-31T21:05:45Z"
        },
        {
          "tag": "v2.45.0",
          "kind": "minor",
          "published_at": "2026-07-31T18:57:46Z"
        },
        {
          "tag": "v2.44.0",
          "kind": "minor",
          "published_at": "2026-07-31T17:43:15Z"
        },
        {
          "tag": "v2.43.0",
          "kind": "minor",
          "published_at": "2026-07-31T13:36:50Z"
        },
        {
          "tag": "v2.42.0",
          "kind": "minor",
          "published_at": "2026-07-31T11:36:23Z"
        },
        {
          "tag": "v2.41.0",
          "kind": "minor",
          "published_at": "2026-07-28T11:07:51Z"
        },
        {
          "tag": "v2.40.0",
          "kind": "minor",
          "published_at": "2026-07-27T20:38:29Z"
        },
        {
          "tag": "v2.38.0",
          "kind": "minor",
          "published_at": "2026-07-27T06:57:04Z"
        },
        {
          "tag": "v2.37.0",
          "kind": "minor",
          "published_at": "2026-07-27T05:15:43Z"
        },
        {
          "tag": "v2.36.0",
          "kind": "minor",
          "published_at": "2026-07-25T05:21:38Z"
        },
        {
          "tag": "v2.35.0",
          "kind": "minor",
          "published_at": "2026-07-24T21:08:21Z"
        },
        {
          "tag": "v2.34.0",
          "kind": "minor",
          "published_at": "2026-07-24T12:29:21Z"
        },
        {
          "tag": "v2.33.0",
          "kind": "minor",
          "published_at": "2026-07-24T12:14:38Z"
        },
        {
          "tag": "v2.32.0",
          "kind": "minor",
          "published_at": "2026-07-24T12:02:03Z"
        },
        {
          "tag": "v2.31.1",
          "kind": "patch",
          "published_at": "2026-07-24T11:44:06Z"
        },
        {
          "tag": "v2.31.0",
          "kind": "minor",
          "published_at": "2026-07-23T06:37:55Z"
        },
        {
          "tag": "v2.30.0",
          "kind": "minor",
          "published_at": "2026-07-23T05:28:13Z"
        },
        {
          "tag": "v2.29.0",
          "kind": "minor",
          "published_at": "2026-07-22T19:05:26Z"
        },
        {
          "tag": "v2.28.0",
          "kind": "minor",
          "published_at": "2026-07-22T10:37:42Z"
        },
        {
          "tag": "v2.27.0",
          "kind": "minor",
          "published_at": "2026-07-22T07:49:27Z"
        },
        {
          "tag": "v2.26.0",
          "kind": "minor",
          "published_at": "2026-07-21T15:46:25Z"
        },
        {
          "tag": "v2.25.0",
          "kind": "minor",
          "published_at": "2026-07-21T14:52:11Z"
        },
        {
          "tag": "v2.24.0",
          "kind": "minor",
          "published_at": "2026-07-21T11:15:42Z"
        },
        {
          "tag": "v2.23.0",
          "kind": "minor",
          "published_at": "2026-07-20T21:12:12Z"
        },
        {
          "tag": "v2.22.0",
          "kind": "minor",
          "published_at": "2026-07-20T20:24:50Z"
        },
        {
          "tag": "v2.21.0",
          "kind": "minor",
          "published_at": "2026-07-20T13:36:28Z"
        },
        {
          "tag": "v2.20.0",
          "kind": "minor",
          "published_at": "2026-07-20T13:04:44Z"
        },
        {
          "tag": "v2.19.1",
          "kind": "patch",
          "published_at": "2026-07-20T11:14:19Z"
        },
        {
          "tag": "v2.19.0",
          "kind": "minor",
          "published_at": "2026-07-20T10:52:20Z"
        },
        {
          "tag": "v2.18.0",
          "kind": "minor",
          "published_at": "2026-07-19T15:59:49Z"
        },
        {
          "tag": "v2.17.0",
          "kind": "minor",
          "published_at": "2026-07-19T15:47:22Z"
        },
        {
          "tag": "v2.16.0",
          "kind": "minor",
          "published_at": "2026-07-19T15:19:52Z"
        },
        {
          "tag": "v2.15.0",
          "kind": "minor",
          "published_at": "2026-07-19T14:03:11Z"
        },
        {
          "tag": "v2.14.0",
          "kind": "minor",
          "published_at": "2026-07-18T10:51:55Z"
        },
        {
          "tag": "v2.13.0",
          "kind": "minor",
          "published_at": "2026-07-18T09:04:18Z"
        },
        {
          "tag": "v2.12.1",
          "kind": "patch",
          "published_at": "2026-07-18T08:28:18Z"
        },
        {
          "tag": "v2.12.0",
          "kind": "minor",
          "published_at": "2026-07-18T07:50:00Z"
        },
        {
          "tag": "v2.11.0",
          "kind": "minor",
          "published_at": "2026-07-18T06:41:28Z"
        },
        {
          "tag": "v2.10.1",
          "kind": "patch",
          "published_at": "2026-07-18T06:29:17Z"
        },
        {
          "tag": "v2.10.0",
          "kind": "minor",
          "published_at": "2026-07-18T03:57:07Z"
        },
        {
          "tag": "v2.9.1",
          "kind": "patch",
          "published_at": "2026-07-17T12:20:47Z"
        },
        {
          "tag": "v2.9.0",
          "kind": "minor",
          "published_at": "2026-07-17T11:47:02Z"
        },
        {
          "tag": "v2.8.3",
          "kind": "patch",
          "published_at": "2026-07-17T10:43:49Z"
        },
        {
          "tag": "v2.8.2",
          "kind": "patch",
          "published_at": "2026-07-17T09:24:14Z"
        },
        {
          "tag": "v2.8.1",
          "kind": "patch",
          "published_at": "2026-07-16T16:21:00Z"
        },
        {
          "tag": "v2.8.0",
          "kind": "minor",
          "published_at": "2026-07-16T13:02:34Z"
        },
        {
          "tag": "v2.7.0",
          "kind": "minor",
          "published_at": "2026-07-16T10:01:40Z"
        },
        {
          "tag": "v2.6.0",
          "kind": "minor",
          "published_at": "2026-07-16T06:11:14Z"
        },
        {
          "tag": "v2.5.0",
          "kind": "minor",
          "published_at": "2026-07-16T04:52:10Z"
        },
        {
          "tag": "v2.4.2",
          "kind": "patch",
          "published_at": "2026-07-16T03:52:58Z"
        },
        {
          "tag": "v2.4.1",
          "kind": "patch",
          "published_at": "2026-07-15T20:40:08Z"
        },
        {
          "tag": "v2.4.0",
          "kind": "minor",
          "published_at": "2026-07-15T11:59:21Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2026-07-15T04:37:22Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-07-14T05:40:45Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-07-13T04:40:10Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2026-07-11T18:26:46Z"
        },
        {
          "tag": "v1.7.0",
          "kind": "minor",
          "published_at": "2026-07-10T21:48:06Z"
        },
        {
          "tag": "v1.6.0",
          "kind": "minor",
          "published_at": "2026-07-10T19:16:03Z"
        },
        {
          "tag": "v1.5.0",
          "kind": "minor",
          "published_at": "2026-07-10T14:55:44Z"
        },
        {
          "tag": "v1.4.0",
          "kind": "minor",
          "published_at": "2026-07-10T10:24:41Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2026-04-01T06:01:10Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2026-03-25T06:03:41Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2026-03-22T07:49:37Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2026-03-20T07:59:23Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "8f4d56290f6118a5fc290628b8373ad44caf6bf5",
          "body": "Bumps the actions-all group with 2 updates: [actions/setup-node](https://github.com/actions/setup-node) and [github/codeql-action](https://github.com/github/codeql-action).\n\n\nUpdates `actions/setup-node` from 6 to 7\n- [Release notes](https://github.com/actions/setup-node/releases)\n- [Commits](https:\n[…]\nversion-update:semver-major\n  dependency-group: actions-all\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(ci): bump the actions-all group with 2 updates (#126)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-08-02T10:58:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b8716f945c0e2cab5488d247529e29915509587",
          "body": "* make the invite one link that carries its own code\n\nEvery Copy Invite path put two things on the clipboard as a two-line string —\nthe share URL, a newline, then \"Access code: XXXX-XXXX\". The URL always ends\nin \"/\", so any paste target that flattens a newline into a space produced\nhttps://host/%20A\n[…]\nhropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>",
          "is_bot": false,
          "headline": "make the invite one link that carries its own code (#132)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-08-02T10:55:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7dc71f4c115ec3dd24f6a2e2d16fbc6ed266f131",
          "body": "…s (#129)\n\nEvery claude-code-action run in this repo failed with HTTP 401 from\n2026-07-30, and the outage was misdiagnosed twice — first as a stale\nHaiku alias, then as a token needing rotation — because the action\nhides SDK output, so the only symptom was a bare `is_error: true`.\n\nNothing about ver\n[…]\ner the wrong cause\n- record the incident and its signatures in the ci-and-release skill\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): preflight the claude credential and stop hiding auth failure…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-08-01T20:19:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "53a0e30891c0064fb407c45ff4d6dee0e534ad65",
          "body": "`make wt-new NAME=x` created the branch with a bare `git worktree add -b x` —\nno fetch, no reference to the remote — so it started at whatever the main\ncheckout's HEAD happened to be. A stale main silently handed every new feature\nbranch an old base, and the first /sync-main turned into a surprise r\n[…]\nhere a host-key or\ncredential prompt would hang the orchestrating agent with no output.\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "branch new worktrees off latest origin/main (#124)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-08-01T10:49:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "726448029419fb2360b7f1add3b444d65940b0d9",
          "body": "… breakdowns (#123)\n\n* make the standup export scannable: evidence rows, bulleted intros, pr breakdowns\n\nReplace the bare SHA-chip rows with structured evidence (kind chip, linked\nref, title, repo, glyphed status), add a member jump strip and blocker-first\ncards, fold overflow and PR commit breakdow\n[…]\no 2.47.0\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "make the standup export scannable: evidence rows, bulleted intros, pr…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-08-01T09:59:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0f43af016f36e1564325b5110d8d05fe007305ba",
          "body": "* one place for the headers every served document carries\n\nThree servers hand HTML to a browser and each grew its own `_send`. They\ndiverged the way duplicated code always does: the share server accumulated a\nfull protective header set and a policy per surface, while the two live boards\nsent a bare \n[…]\nserted\nto be a pure insertion.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "unify every browser surface on one theme and one chrome (#122)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T20:59:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12ce96a0751fdfcc85aef87eb11d0eefc7cfd2c8",
          "body": "yeaboi.ai was not in Google's index at all: no robots.txt, no sitemap.xml, no\ncanonical tags, and — because the docs nav is built by JS into a display:none\ncontainer — not one crawlable link between docs pages.\n\nscripts/gen_site_seo.py now owns the SEO head block, a crawlable footer, the\n?v= cache-b\n[…]\n1M context) <noreply@anthropic.com>\n\n# Conflicts:\n#\tREADME.md\n#\tdocs/docs/modes/index.html\n#\tdocs/docs/modes/retro.html\n#\tdocs/index.html\n#\tpyproject.toml\n\nCo-authored-by: Dev Person <dev@example.com>",
          "is_bot": false,
          "headline": "make the docs site indexable, and measure it (#121)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T20:02:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51df4c3d4b5f2e9943ba8354b5d96a3eed6a2ff9",
          "body": "* mark performance mode as beta across every surface\n\nPerformance ships as a first-class mode — a welcome card, five MCP tools, a\nCLI subcommand, a plugin skill and its own docs pages — with nothing saying\nits output has never been validated against a real team's tracker. For a mode\nthat drafts mate\n[…]\nnv vars.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "mark performance mode as beta across every surface (#116)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T18:51:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7db4fbe4da95c2a622f482dcd0761b88fd377ae8",
          "body": "…rors (#120)\n\n* ci: show claude sdk output in auto-version\n\nThe action prints only `Running Claude Code via SDK (full output hidden for\nsecurity)` and a bare `is_error: true`, so both Haiku outages so far have had\nto be diagnosed by elimination rather than by reading the error. The prompt and\ndiff a\n[…]\nfailure.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): unbreak the auto-version bump, and make it report its own er…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T18:03:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "71e54b9c69e67868584cec4a295ec6f642d884d5",
          "body": "* remove LAN sharing — the live boards are tunnel-only\n\nThe retro and poker boards advertised two addresses for one server: a LAN URL\nbuilt from a UDP-probed local IP, and a Cloudflare tunnel URL only if the host\npressed \"Share Remotely\". The LAN link works for one room, exposes the port to\neveryone\n[…]\nend rewrite shipped as 2.43.0.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "remove LAN sharing — the live boards are tunnel-only (#115)",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T17:36:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6cc73afe0ff1c1ab59df462cde1d0f076ae0321a",
          "body": "The old banner was a neon-sign graphic reading \"Scrum AI\" — stale branding\nfrom before the rename. Replaced with a flat dark banner carrying the\nyeaboi.ai wordmark, the docs-site tagline, and the pixel duck mascot,\nusing the palette from docs/assets/landing.css.\n\nGenerated with the duck sprite (base\n[…]\n0x400 — the generator's widest ratio is 21:9 and cropping to 3:1\nclipped the duck's feet. README renders it at width=800 either way.\n\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "replace readme banner with duck mascot artwork (#117)",
          "author_name": "Nikolai Main",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T16:26:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4f0a416a149f717a43ba6f208324228fd412dc71",
          "body": "… (#114)\n\n* fix(ci): compute the auto-version diff locally, not through the API\n\n`gh pr diff --name-only` returns HTTP 406 on any diff over 20000 lines,\nand the call sat inside an `if` condition where `set -e` does not apply —\nso the failure was indistinguishable from \"no files matched\" and fell\nint\n[…]\nrebuild.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix the auto-version guard that swallowed PR #111, and release 2.43.0…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T13:31:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d70f399b4fc59fc92d9d5b498b6cb5738c2eedb9",
          "body": "…vite on it (#111)\n\n* allowlist url schemes in every export\n\nA ticket whose `url` was `javascript:alert(1)` rendered as a live\nclick-to-execute link. `test_export_xss.py` could not catch it: its probe is\nmarkup-shaped, and html.escape() rewrites none of the characters in a scheme,\nso the value reach\n[…]\nnvite, and the retro\nboard's per-column composers and in-flow reaction tray.\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "migrate every browser surface to react + typescript, and build the in…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-31T13:10:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c3bc598454311d0077d45bd7f73b458d6040bdd",
          "body": "fix(ci): pin the dated haiku model id, and apply the version bump it missed",
          "is_bot": false,
          "headline": "Merge pull request #113 from dinho149/fix/auto-version-haiku-model",
          "author_name": "Nikolai Main",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:31:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7c1a49c17fd114fc6ea5e73e44ebf4670e801ba",
          "body": "The bot can't write it from this PR. claude-code-action refuses to run at\nall when the workflow file differs from the default branch's copy\n(\"Workflow validation failed... must have identical content\"), and this PR\nedits auto-version.yml. It exits as a *skip*, so the job goes green without\nthe model ever being called — which also means the model pin can't be\nverified until after merge.\n\nRestores the hand-written 2.42.0 entry.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Revert \"chore: let the bot write the 2.42.0 changelog entry\"",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:26:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "871f3e896fb5ae3aa6107c08afdafe13acbaf39f",
          "body": "Keeps the manual version bump (the bot can't retroactively bump for an\nalready-merged PR — it only ever sees the current PR's diff) but drops the\nhand-written entry, so the guard routes to changelog-only mode instead of\nskipping. That actually exercises the pinned model, which the skip path\nnever did.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: let the bot write the 2.42.0 changelog entry",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:25:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d1ae297df06ae2bf3fb73d3d9ade74b3b4d0d1ef",
          "body": "The `claude-haiku-4-5` alias stopped resolving between 2026-07-29 and\n2026-07-30. Every Auto Version Bump run since died on turn 1 in ~2s with\ntotal_cost_usd 0, while every sibling workflow on claude-sonnet-5 kept\npassing with the same OAuth token — and neither workflow file had changed\nin that wind\n[…]\n1.0, which is already tagged and released, so publish.yml would not have\nshipped any of it. Applied the minor bump and changelog entry by hand.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): pin the dated haiku model, and apply the bump it missed",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:24:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fa70be815f9fdf4717f1ca8e1a17a3325f4c99a3",
          "body": "TUI mascot: duck companion, boxed settings with keyboard focus, app-wide clicking, feedback composer",
          "is_bot": false,
          "headline": "Merge pull request #112 from dinho149/feature/tui-mascot",
          "author_name": "Nikolai Main",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:14:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "879b5001e9a1f2367dfbbb48efb3a897beb6e03b",
          "body": "`make lint` only runs `ruff check`, so a long logger.info line and a\ntrailing blank line in the generated sprite module slipped past locally and\nfailed CI's separate `ruff format --check` step.\n\nThe sprite blank line came from the generator emitting a separator after\nevery block including the last, so it would have returned on the next\nregeneration — trimmed there rather than in the output.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style: satisfy ruff format --check",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T11:09:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d9a47a2ebed222a7048538d1e1a3316ec71ac22e",
          "body": "The back/controls tabs ease their presence on every render, so rendering\nthe plain frame and then the composing frame left the pocket rows\ndiffering for reasons unrelated to the bubble — the test only failed when\nsomething earlier in the suite had left `_back_presence` non-zero.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(tui): pin tab presence in the composer overdraw test",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T10:56:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5c79dad4219c9c2a4469005fea4be3c078aed445",
          "body": "76 read as a slab across the screen. Still wide enough for all four types on one\nrow and a comfortable line of prose.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style(tui): trim the composer to 64 columns",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T10:38:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f99b9735d1af9453461039a945b4980de1a9f562",
          "body": "…ng box\n\nThe bubble was laid out inside the companion lane, and that lane's width feeds\nthe mode list's — so making it wider reflowed every description and truncated the\nbottom-left hint row, and keeping it narrow left a 42-column box to write in.\nNeither is necessary: _WelcomeFrame already composit\n[…]\nimum size there is no lane to draw over, so `f` opens\nthe full form instead of a composer that would render nothing while swallowing\nevery key.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): draw the composer over the frame so it can be a real writi…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-31T08:27:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "624a049f8ebb95ecff16e20af7e4a8ee00fe42d2",
          "body": "Widening the companion lane for the composer was the single cause of both\nfaults. The split feeds the mode list's own width, so a wider lane reflowed every\ndescription — growing the left column, which pushed the bottom-anchored duck down\n— and truncated the bottom-left hint row, dropping \"tips\" from\n[…]\nnd its colours were still the fixed constants, so it didn't fade\nwith the rest of the bubble. Both fixed, and the now-unused constants dropped.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): the composer must not resize the mode list",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T21:00:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "605434594f4c5023e5eb54bd6dd1db135ef04e25",
          "body": "The lane is bottom-anchored, so a bubble taller than the space available cropped\nthe DUCK rather than itself — his neck disappeared under the music pocket. The\nmessage area is now budgeted against the lane height (minus the duck, the tail\nand the bubble's own chrome), so it shrinks instead of growin\n[…]\ndler asks for it, the animation finishes\nit. Esc used to drop the state between frames, which is what made the bubble\nvanish rather than leave.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): keep the composer clear of the duck, and animate it in and out",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T20:50:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cbff7d2e87f8516ccd17e746f2adf4b552e7aff7",
          "body": "Only the rows carrying text get it, so the typed message reads as a block of\nwriting rather than loose lines under the two selectors. The wrap width drops by\nthe gutter's own columns, so a long message still breaks inside the box.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): a gutter block down the composer's message rows",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T20:45:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "44f2e27cf3393684efe1bc8f8409589df7ecf50a",
          "body": "… bubble\n\nThe Type/Area rows were a carousel — the options rotated around a fixed marker,\nso the words moved and the selection didn't. They are a fixed list now: the\nmarker moves along them and the window only slides when the selection would fall\noff an end, marked with … rather than ‹ › (which read\n[…]\nngelog highlights follow the same rule against their version heading. This\nreplaces the previous commit's guess, which pushed them further out.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): static composer selectors, plus paste and dictation in the…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T20:35:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "44ab935fca17b7d7d6a83784d8f7ebf894172868",
          "body": "The `f` shortcut no longer leaves the welcome screen. The duck's tip bubble\nbecomes a composer in place: Type and Area selectors over a message box, ↑/↓\nbetween the three fields, ←/→ to cycle a selector or move the cursor, Enter to\nsend, Esc to cancel. Composing widens the right-hand lane from 44 to\n[…]\nt as a side\neffect of un-indenting something else; the tips gallery and the changelog\nhighlights are back on PAD, under their section headings.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): feedback comes out of the duck, and tips loses its chrome",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T20:27:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "efef57c505ab339b71a0c1c686b9d98b111ef2c8",
          "body": "Brings in #106 (filesystem sandbox, secret redaction, write-tool gating,\nCodeQL), #107 (standup intelligence + the shared export visual system), #108,\n#109 (reporting overhaul: threaded generate, themes, deck styles, pptx) and\n#110. Six files conflicted.\n\nOurs, in full — the settings screen and its \n[…]\nPAD while this branch had replaced that import. Both now exist,\ncommented — do not collapse them.\n\nuv.lock regenerated rather than hand-merged.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "merge origin/main into feature/tui-mascot",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T19:31:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d00b3a1a91e1c76a930e90dce347431477b7bf1",
          "body": "…one click\n\nThe voice status was cropped mid-command. Its reason string appends a Linux\n`apt install libportaudio2` note, so no column width would ever hold it — a\nread-only status now flows onto continuation lines instead. The wrap happens at\nbuild time (_wrap_value), not at render: the whole layou\n[…]\n: the wrapped status left a\nfive-row shortfall across two boxes, which the old cap couldn't absorb, so the\ncolumns finished a line out of true.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): wrap long setting statuses, and make the back tab leave in …",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T16:41:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5438db3babb881d07a42e74d3c585ddfa93fd48f",
          "body": "The rows were indented two columns inside an already-indented box. That gutter\nexisted only to hold the focus marker — a leading glyph needs the gutter on\nEVERY row or the text jumps sideways when focus lands. Focus is a full-width\nbackground bar behind the row instead: it costs no columns, reads mo\n[…]\nbsurdly.\n\nThe focus bar is a background colour, so the tests covering it render styled\nsegments — there is nothing in the plain text to assert.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): flush setting rows and columns that end level",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T16:23:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ff252834bbd8e7030740ad3643904f50fbb94e9",
          "body": "Clicking while editing did nothing: the edit branch routed every key to the\nbuffer, so a click was swallowed and you had to press Esc first. A click now\ncommits what was typed and falls through to the normal routing, so it lands on\nwhatever it hit — another row, or a tab. A click on empty space is l\n[…]\n) in _input — Settings is also the only page that shows the tab\n  AND types into fields, so it brackets each in-place edit and 'c' types a 'c'.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): click straight to another setting, and bind controls to 'c'",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T16:14:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f4f30ccdcace4399d0e26818e86447bceb1a6e86",
          "body": "The animation on these two was the full-screen ANSI-Shadow wordmark played\nbefore the page — reveal, diagonal shine sweep, exit — not the page title I\ntook the shimmer off last commit. Both pages open instantly (bundled JSON, an\nempty form), so a shine sweep in front of them reads as a loader for a wait that\nisn't happening. `c` and `f` now land straight on the page.\n\nThe All Tips gallery keeps its entrance, so play_wordmark_intro stays.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): open changelog and feedback without the wordmark intro",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T10:18:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e1dc4138b6834dcc758a86e3e392360979f5c526",
          "body": "Both loops fed shimmer_tick a monotonic clock, which sweeps a travelling\nhighlight across the ASCII title — it reads as a loader on a page that isn't\nloading anything. Both builders already default it to None (the solid look), so\nthey just stop passing a clock. The typewriter subtitle stays.\n\nChange\n[…]\ng_text stays in changelog.py: it's a public, separately tested\nexporter rather than UI, so dropping it would remove a module API, not a button.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): static titles on changelog and feedback, drop changelog copy",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T10:04:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "50b5fda8453253daf9be0334412a87499f121d10",
          "body": "…ata dir\n\nThree things the boxed layout still got wrong.\n\nLayout. A row-based grid padded every box in a row up to the tallest one, so a\ntwo-row section sat in a six-row box beside a full one. The sections are dealt\ninto the shortest column instead, and each box is exactly as tall as its own\ncontent\n[…]\nhe Esc chokepoint\narms the retract before the screen gets a say, so an edit that eats the key has\nto un-arm it — same as popping a focus level.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): balanced setting columns, storage under system, in-place d…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T09:32:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b7c3ab38b9851315b57b7a199aaa289ae57865b5",
          "body": "The marker now lands at ~30s locally — right on the deadline, so the test fails\nabout as often as it passes. It's a liveness check (does the TUI reach\nmode-select in a real pty at all), not a performance budget, so the tight bound\nbuys nothing.",
          "is_bot": false,
          "headline": "test: give the pty boot smoke test real headroom",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T09:11:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "018edd6fe2ccf8bc47985ee8c7ad3f1e5f702cdb",
          "body": "Boxing the sections left the mouse as the only way to reach a value. Settings\nnow has three focus levels, so every field is reachable with arrows alone:\n\n  (-1,-1)  the tab bar   — left/right switch tabs, down enters the grid\n  (b, -1)  a section box — arrows walk the grid, Enter opens it\n  (b,  f) \n[…]\n  chokepoint arms the retract before the screen decides whether it's keeping the\n  key. Added `cancel_back_retract()` for screens that keep it.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): navigate and edit settings from the keyboard",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T09:10:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "952f17ab2c11cd93b3d0e9cfd87873ced805c692",
          "body": "Each heading section becomes its own rounded box with the heading as the box\ntitle, laid out in an adaptive column grid (two columns when there's room, one\nwhen a column would fall below _SETTINGS_MIN_BOX_W) — the same treatment the\nUsage screen already uses, flattened through the shared _render_to_\n[…]\n box border lands on the tab-bar rule, which puts the row text inside it at\nexactly the column the unboxed rows used — no text shifts sideways.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): box the settings sections like the usage dashboard",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-30T08:10:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7a493cc38ff36bfc3fc4ceea6ce90a3d22429e3b",
          "body": "It sat over by the music pocket; anchor it to the left tab strip instead,\nimmediately after back (and copy). draw_back_pocket now publishes where that\nstrip ends so the tab lines up, and the tab unrolls and expands rightward from\nits left edge rather than leftward.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): move the controls tab next to the back tab",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:30:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6dea462c1554e014d0ec1b549ebbe99f057cfd30",
          "body": "Both hub delete messages now come from the companion duck instead of the\npage: the confirmation replaces the red centred overlay (that whole popup\nblock, its slide-up animation and the body-trimming it needed are gone), and\nthe follow-up toast moves out of the subtitle row.\n\nThe confirmation is stic\n[…]\nlds, since it has to wait\nfor an answer rather than dissolving like a transient status. The result toast\nuses the normal fade-in/hold/fade-out.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): the duck asks for delete confirmation and reports the result",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:26:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "02063978ba679524ca4d4952ed30bf83da2e1f0f",
          "body": "Clicking the companion duck lifted his shades on the welcome screen only.\nThe chrome duck (the one riding along on every sub-page) now publishes its\nrect and plays the same SHADES_LIFT_SEQUENCE when poked, so the gag is\navailable wherever he appears.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): the double-shades gag works on every page's duck",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:18:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2a39a3dcd382104fd67cf1038a249d47f3992791",
          "body": "With no page-specific hints the drawer just repeated the back/copy tabs\nbeside it (e.g. Usage), so a page now qualifies for the tab only when it\nhands over controls of its own.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): only show the controls tab on pages with their own controls",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:14:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e9b5499ac8ec47bfea0ce72e50c6355d9be2ebb1",
          "body": "The '⌃C controls' label is redundant once the list it describes is on screen,\nso once expanded that row carries a control instead.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): hide the tab label while the controls drawer is expanded",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:10:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7ec6ee230249f5c9cc3354136a842ca7e1f5992e",
          "body": "The drawer's keys were right-justified in their column; left-align them so\neach key starts flush at the edge with the descriptions still in a column.\nThe collapsed tab now eases in on pages that qualify (unrolling leftward out\nof its right edge, mirroring the back tab's corner peel) and eases back out\non pages that don't — it was popping in and vanishing before. It only\nbecomes clickable once settled.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): left-align the controls rows and animate the tab in",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:09:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "052332f40e089b67413610bf8edb432b141fea84",
          "body": "…s drawer\n\nThe page-hint tab duplicated what the drawer already lists (and was getting\ncut off behind it), and the ctrl+P / ctrl+O rows repeat the music pocket\nsitting right next to them. Page hints are now drawer content only.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): drop the redundant hint tab and music rows from the control…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:04:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "afda2e206e90cfcf7657a27a935af11a2bb75120",
          "body": "A \"⌃C controls\" tab now sits permanently between the page hints and the\nmusic pocket. Ctrl+C grows the tab itself upward into a panel listing every\ncontrol available on the current screen — the page's own hints plus the\nglobal chords — easing its height and width so it unfolds rather than\nsnapping, \n[…]\n\nthat. Esc closes the drawer instead of navigating back when it's open.\n\nNot shown on the welcome screen, which already lists its own controls.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): persistent controls tab that expands upward on Ctrl+C",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T23:00:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e69b2e312813440dd0fd3c3d81913429d1eca8d8",
          "body": "- Settings values didn't change in the UI until a restart: set_config_value\n  only writes ~/.yeaboi/.env, and the page re-reads os.environ. Added\n  config.apply_config_value (write + export, clearing on empty) — the pairing\n  every other setter in that module already did by hand — and used it from t\n[…]\ning the settings status.\n- Usage: drop the always-on scrollbar — the boxes normally fit, so the track\n  only shows when they actually overflow.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): settings edits apply live; duck status fades in and out",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T22:42:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f460b6e2b1da6e81af2d5786b1706d208dab1eaa",
          "body": "…ocket\n\n- Generalise the left pocket: sibling tabs beside back are now a list of\n  (label, key) pairs peeling out of the same corner, so the copy tab is just\n  one entry and a page can add its own. Clicks report the tab's key.\n- Settings hands its controls to the chrome via _hint_tab, freeing the bo\n[…]\nbubble beside his head (_duck_say) rather\n  than printed as a body line.\n- Usage: wide section boxes span two columns instead of the full grid.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): duck speaks settings status; controls ride in the bottom p…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T22:29:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9ac0c5139a9236874ec489ceac8f0d64b6d8d757",
          "body": "Their values (the last-session timestamp, the session DB path) don't fit a\nthird-width column and were ellipsizing. Sections can now be flagged wide,\nwhich lays them out as full-width boxes stacked below the column grid.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): give Session History and Environment full-width usage boxes",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T22:16:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "470cbca918b3cd46b5fabc195b6b3bbeafe8fdbf",
          "body": "Each Usage section (LLM Provider, Lifetime Token Usage, Current Session,\nLocal Model Performance, Session History, Environment, Team Profiles) is\nnow its own rounded box with the section name as its title, and the boxes\nsit side by side in a grid whose column count follows the terminal width\n(1 when\n[…]\nrender_to_lines — hoisted out of\n_build_retro_screen to module level and now shared by both — keeping the\nviewport math and scrollbar accurate.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): box the usage sections and lay them out in columns",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T22:12:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ac4fe0b3a43b85ac0f9f8d855da4dc2763829f7",
          "body": "Generalise the left pocket into a peel helper so a sibling tab can share\nthe corner animation, and give copy-capable pages (flagged with _copy_tab)\na 'c copy' tab next to back. Clicking it presses 'c'. Usage drops its\ninline keyboard hint now that both affordances live in the chrome.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): add a 'c copy' chrome tab beside the back tab",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T21:53:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9ea4a618dcfd3255129965a4a5639b3edbcbbb20",
          "body": "The on-press retract snapped away the instant the key landed; hold the tab\nup for _BACK_RETRACT_DELAY (0.1s) after the press, then run the fast fold.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): hold the back tab a beat before folding it away",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T21:49:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ddfcac18c57aaae7711213e1b8ce6ed6ab0a3d0c",
          "body": "Three things kept the retract trailing into the next screen's entrance:\nthe latch only fired on a tab click (not Esc), the fold eased at the same\nrate as the glide-in, and the menu<->page transition frames still asked\nfor the tab. Now Esc and tab-clicks share one _esc() chokepoint that\nlatches the r\n[…]\n, the latched fold eases much faster, and the slide\nframes opt out via _no_back_hint. Measured: tab clears in ~0.1s from the\npress (was ~0.5s).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): fold the back tab away on press, not on arrival",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T21:46:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3ef1a1896ac786366dfdba3c223984b7f49bf658",
          "body": "… press\n\n- The companion duck was held off-screen for the whole return transition\n  (companion_intro=0) and only slid in afterwards, so it cleared and then\n  reappeared. _sweep_menu_in now takes companion_from and ramps the duck\n  in DURING the return wipe (from its sub-page corner), and the post-wi\n[…]\n a late animation. A retract latch set the instant the tab\n  is clicked overrides the current screen's target, so the fold triggers\n  on press.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): slide the duck back on menu return; retract the back tab on…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T21:39:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6273cc24d19c13fdd24c05584c5b7b8a9fcbe7ac",
          "body": "_settings_tab_bar takes a fractional tab position (pos) and interpolates\nthe bright underline span between adjacent tabs; the settings loop eases\n_tab_pos toward the active tab each frame, so switching tabs slides the\nunderline instead of jumping.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): slide the settings tab underline between tabs",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:38:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a25bc284f05135b4d0bf604310a4dcd8ce9da327",
          "body": "The config rows (and their create/scope sub-lines) sat 2 cols in from the\nsection headings; shift them left so the content aligns under each header.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): unindent settings rows to align with their section headings",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:33:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1bbac42e882723e03bcf6dfb944e90e8d5f43aca",
          "body": "Remove the explicit Back button from Performance (roster + detail) and\nthe 'Esc back' tail from the Usage, Changelog and Settings footer hints —\nthe app-wide back tab is the go-back affordance now. Tests updated.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): drop redundant back affordances now the back tab covers them",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:32:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c947cc7a2fbe9891af731e3371f33fc1e33d9e85",
          "body": "The bottom-left back tab now shows the go-back affordance, so the\nboard-required screen no longer needs the inline hint.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): drop redundant 'Press any key to go back' hint",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:24:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fba83cc468ccdf4f155fbd71be12402bc439da6e",
          "body": "Anchor the tab at the bottom-left corner and reveal it as a staggered\ndiagonal — the bottom border row opens first (corner ╯), then the text,\nthen the roof — so it reads as the corner peeling up. Retract reverses,\nfolding back down into the corner. Driven by the same eased presence.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): back tab peels up from the corner instead of sliding in",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:13:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ea39cc0fd430d8fd42cefc081d83a5dc58bf5d8d",
          "body": "Drive the tab from an eased presence (0..1) instead of a one-way slide:\ntarget 1 on back-capable screens glides it in, target 0 elsewhere glides\nit back out. The frame drives it every render (and the welcome frame\nretracts it), so leaving a back-capable screen slides the tab away rather\nthan vanishing it. Clickable only once mostly settled in.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): animate the back tab out (not just in)",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:06:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "58a75264a5cd602c066ed4df31ba3ab8b6304f0a",
          "body": "_build_run_hub_screen records the selected run card's Delete/Export\nbutton rects (panel._btn_regions); run_snapshot_hub hit-tests them (with\nx, before the y-only card regions) and reuses the existing focus==1/2\nEnter paths — delete-confirm popup / export picker. Covers retro, standup,\npoker, reporting, performance.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): make hub Delete/Export buttons clickable",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T19:02:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "531aeee616c90eb1c64506549120409b9064cc42",
          "body": "The back tab drew a closed floor under its text; mirror the music pocket\ninstead — the alcove hangs from the roof with corners rising at the walls\nand an open gap between, no bottom border.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): open bottom on the back tab to match the music pocket",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T18:57:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ab4168371d13e4dc78ca54b4cd74ae813a96633f",
          "body": "Attach _card_regions to _build_project_list_screen (absolute row spans per\ncard, tracked with real rendered heights) and hit-test clicks in the two\ninteractive project-list loops: a click selects the card and synthesises\nEnter to open it / start a new project or analysis. Mirrors the saved-runs\nhub. Card body only; edge Delete/Export buttons are not click targets.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): make project-list cards clickable (planning + analysis)",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T18:48:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1d7385f78b0135e84d19a60eeca35a133daaa198",
          "body": "A rounded 'go back' pocket mirroring the music bar, drawn on every\nback-capable screen (all but the main menu, which opts out via\n_no_back_hint). It slides in from the left on entry and is clickable:\nits rect is published from the render frame and read_key turns a click\nthere into Esc, so it works app-wide with no per-loop wiring.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): app-wide clickable 'go back' tab (bottom-left)",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T18:45:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "672a4325e3c373646dc738a5807e3544a8bb1006",
          "body": "'No engineers found' and the connect-a-tracker hint sat at _PAD while the\nsubtitle is at _PAD+2; align them under the subtitle.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): indent the performance empty-state to match its subtitle",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T18:32:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c057b9c10880f85b4595ccdc668363f8e4f5dfa4",
          "body": "The Board-required / export-status body sat at _PAD+4 while its heading\nand hint were at _PAD+2; align them all on the same column.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): un-indent the status-screen body to align with its heading",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-29T18:28:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "de7dfb638e4eaeceea9fe1999adfe9344b9db13d",
          "body": "… workflows (#110)\n\nClaude Review and Dependabot verify silently never ran on any PR that got an\nauto-version bump. auto-version pushed the bump with the default GITHUB_TOKEN,\nmaking the bump commit's CI run bot-actored; GitHub then emits no workflow_run\nevent for it. Combined with ci.yml's cancel-i\n[…]\n0 -> 2.41.0 to match pyproject.toml already on main —\npre-existing drift, not part of this change.\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "repair automation pipelines: restore dropped reviews, fix dead triage…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-29T12:43:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c42d6070b971c5387de60eddcea63da8edb550c",
          "body": "Wire mouse-click support into every button-row input loop across the\nmode-select flows and the session review pipeline: each loop keeps its\nlast-rendered panel, and a click is hit-tested via button_click() and\nrouted to the button under the cursor (synthesized as Enter). Covers the\nsnapshot detail v\n[…]\ner/reporting/performance pages, the analysis + roadmap\nresults, the preview/sprint-review flows, the confirm popups, and the\nphase review loop.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): make action-button rows clickable app-wide",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T17:51:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "918c8c33851d36f955f8a140d27a25dae28f2d7c",
          "body": "The standup/retro/poker/reporting/performance hubs couldn't be driven by mouse —\nyou couldn't click '+ New retro' (or a saved run) to open it. The builder now\nrecords each visible card's absolute row span on the panel (_card_regions), and\nthe shared hub loop hit-tests clicks against it: click a run \n[…]\nthe roster for\nPerformance). Regions use the real rendered heights (run cards 5 rows, the '+ New'\ncard 3), verified against the rendered frame.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): make the saved-runs hub cards clickable",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T17:11:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "773c17815166ccd1dfe058634847a4f9586d2e08",
          "body": "…unindented\n\nPer feedback: move the Join this retro block above the four-column grid table,\ntuck the 'Server ready — share the code' status note directly under its heading,\nand unindent the share code / LAN·remote·host URLs to align with the heading\n(dropping the extra level). Widen the grid slack so the four columns never wrap.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(retro): join info back on top (note under the heading), content …",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:55:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1203a72c627caa2514aad6cc232401d1322cd9a5",
          "body": "…lace\n\nRich's Live.start() unconditionally re-emits the enter-alt escape, which clears\nthe alternate buffer — a blank flash. When one full-screen page takes over from\nanother already in the alt-screen (notably the splash → menu handoff), that\nre-clear is the occasional flicker after the intro clears\n[…]\n) to skip the alt-enter when already in the alt-screen, while\nstill marking _alt_screen so the final stop() restores the normal screen on exit.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): don't re-clear the alt-screen when a screen takes over in-p…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:55:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a59facad1c8a61f240884a9d28b81f3cae8d74b1",
          "body": "… the bottom\n\nThe retro monitoring view stacked the four grids (What went well / didn't / Action\nitems / Demos) vertically with the join instructions on top. Put the four grid\ntitles + cards side by side in a 4-column table across the top, and move the join\ninstructions (share code, LAN/remote/host \n[…]\nndered\nto lines so it still scrolls line-by-line with the rest of the viewport; columns\nsize to the width and crop cleanly on narrow terminals.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(retro): lay the four grids out as a 4-column table, join info at…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:43:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "28eec95603e3bd8952406ef2ae4ec0049d7b7c99",
          "body": "… the terminal\n\nLive(screen=True).stop() unconditionally calls set_alt_screen(False) on the with\nexit — restoring the user's real terminal for an instant before the wizard/menu\nre-enters alt (the flash after the intro clears). Rich only calls it there to\nleave alt, and we own the alt-screen and hand\n[…]\nop\nset_alt_screen for the duration of stop(), then restore it. One continuous\nalt-screen: no flicker during the intro, no flash at the handoff.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): keep the alt-screen on exit so the handoff doesn't flash…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:30:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "05f1c1c197a9039d48f34241adb5c1ad2e08ef06",
          "body": "Remove the '!' glyph from the exclaim phase; the duck's rear-back-then-snap\nrecoil carries the exclamation on its own.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): drop the yellow exclamation mark",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:15:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3e54c733b1033def5d88f2e30eda5bb1b20fa84e",
          "body": "The scaler decoded to 1-bit, silently dropping the ░ light-shade that gives the\nmenu titles their pixel texture (the dots in counters/gaps — e.g. the Y in\nYEABOI). Decode to a 3-level grid (full/light/empty) so ░ survives the upscale;\nthe enlarged wordmark is now genuinely the menu letters, bigger, \n[…]\noved the checker/two-tone dithers (lego/cheese/carpet) — the glyphs\ncarry the texture themselves, so the compositor uses one flat brand colour.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): preserve the ░ light-shade when scaling the menu font",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T14:11:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e2556e08681e2298e6f8237916c4fea0158180ed",
          "body": "The half-block dither punched holes in the strokes (cheese); the dark shade was\nlego. Neither matched the menu titles, which keep every cell full and just tint a\nfaint subset darker. Do the same: render the enlarged wordmark solid (crisp ▀▄\nedges from the scaler) and, in the compositor, tint a checker subset to 72%\nbrightness — a subtle two-tone weave, no holes, low contrast.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): solid YEABOI with a subtle two-tone tint, matching the menu",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T13:50:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "06a979ac5a99f9835389911781cbf58f0dadaa8e",
          "body": "…re lego)\n\nThe ▓ dark-shade dither read as high-contrast lego studs. Switch the fill dither\nto a half-block (▄) — same colour, half-height cells — so the texture matches the\nmenu titles' own ▀▄ half-block pixelation instead of standing out as darker\nbricks. Only █ is dithered, so the letterforms are unchanged.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): texture YEABOI with half-blocks, not a dark shade (no mo…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T13:45:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c8a981c90b64ea1960fe84dc526619da22a8ec7a",
          "body": "- Replace the quack (bob + ripples that read as a vibration) with a single\n  exclamation: after landing the duck rears back with a '!', then snaps forward\n  as YEABOI bursts out.\n- Dither the enlarged wordmark's solid fill on a fine █/▓ checker (texture=True)\n  so it keeps the menu titles' pixel texture instead of reading as flat blocks;\n  the ▀▄ edges stay crisp (only █ is dithered).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(splash): clean exclamation + textured YEABOI wordmark",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T13:36:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "232599ab871003d63a4eadf00235d53d295f8858",
          "body": "The redesigned duck traverses the whole screen (jump in → waddle across), so the\nnon-buffered inline Live (screen=False) diff-redrew a dozen scattered rows every\nframe and tore badly. Switch the splash Live to screen=True — Rich buffers the\nalternate screen and writes one atomic full frame per refre\n[…]\nenter the alt-screen after the Live exits to keep the seamless\nsplash → wizard/menu handoff (one continuous alt-screen, no clear-to-shell gap).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(splash): run the intro double-buffered so it doesn't flicker",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T13:21:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a51ef46c75df77387e5835534e6b60602ba017f2",
          "body": "… wordmark clean\n\nNew brand-splash choreography replacing the walk-in-and-paint intro:\n1. the duck jumps in on an arc from off the left edge,\n2. quacks — a couple of head-bobs each spitting a widening sound ripple,\n3. YEABOI bursts out to his right in the MAIN-MENU block font, scaled up\n   (render_a\n[…]\n _build_run_frame/_run_wordmark_animation\nstay for the per-mode wordmark intros. Layout recomputes per frame so a resize\nmid-intro never tears.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(splash): redesign the intro — duck jumps in, quacks, waddles the…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T13:04:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c4810dc244aace6ba4d382bfc4debe429ee7ab81",
          "body": "The return transition's second phase used a fade-up-from-black for the other\ntitles. Swap it for the same top-left→bottom-right diagonal wipe the fresh-load\nintro uses, so returning reads identically: the mode you came from slides home\nfirst, then the rest scroll in around it.\n\nAdd a sweep_skip para\n[…]\nreen that holds one title fully shown\nwhile the sweep reveals the others, and reuse _sweep_menu_in (with sweep_skip)\nfor the slide's phase two.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): the rest scroll in with the diagonal wipe on menu return",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T12:46:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cd435d56b8b588ebbfd49f6a0e8282158a01bd23",
          "body": "Returning to the mode menu used to snap in cold (except the project-list Esc,\nwhich slides). Now every return replays an intro:\n\n- Cold return from a mode/hub → the mode you came from slides back down from the\n  top (the inverse of the select→page lift), then the other titles fade up around\n  it — '\n[…]\nenu_in;\nthe project-list Esc keeps its own (card-dismiss + slide) reverse transition and\nflags _reverse_animated so the loop doesn't double up.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): animate the menu back in on every return",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T12:35:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d53aff364d4a1f1b46b425e84fa8ff7b65d97cdb",
          "body": "The bright bar under the active tab ended on a hard edge against the dim\nshoulders. Step the last char on either end down to the mid accent so it fades\nout — full brightness across all inner chars, one dim level at each end, then\nthe dimmer shoulder chars, then the neutral rule.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): taper the active tab underline in three steps",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T12:14:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9884e965d3c9cdafe7910ea33e4e9f411d538aad",
          "body": "The section _heading helper always prepended a blank, so on the first heading\nit stacked on top of the subtitle's own trailing blank — two blank rows under\nthe subtitle. Skip the leading blank when the heading is the first body line;\na status message (when present) is still separated from the section by it.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): drop the doubled blank under the retro/poker subtitle",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T12:05:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "47019d83dc04bdbaf1c4386f4fcfe382e2602522",
          "body": "Mirror the Usage page: drop the Copy/Back action buttons for a lightweight\n'c copy · Esc back' keyboard hint aligned with the headings, and wire c/C to\ncopy and Esc/q to back in both run loops.\n\nPin each viewport line to a single row (no_wrap + crop) so a long changelog\nentry — its inline area tags \n[…]\nthe hint off the\nbottom where the crop and the music pocket swallow it. Update the stale\nbutton-assertion tests to check the hint text instead.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): replace Changelog/All-Tips button rows with keyboard hints",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T12:01:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5e6eafadd7f02dc08f889e51ff7c4826473d2747",
          "body": "…lide\n\nThe select→page slide eases every mode's title to end_offset=1 (one blank\nabove the title, matching the project-list layout). The saved-runs hub instead\nseated its title at selected_title_offset(0) — level with the menu's top row,\n~3 blanks down — so the instant the slide handed off to the hu\n[…]\npdate the stale Usage test: the Copy/Back button row became a keyboard\nhint, so assert the 'copy'/'back' hint text rather than a 'Back' button.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tui): stop the standup/retro/poker hub title dropping after the s…",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T11:37:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fb463d4af8ac6c3b65717928da8d9769af91cde2",
          "body": "Subtitle + hint were at _PAD (2), left of the title and their own body. Move\nthem to the title column (_PAD + 2) and the message body one level in.",
          "is_bot": false,
          "headline": "fix(tui): align the board-required/export-status subtitle with the title",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T11:18:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26465fcdbc15a6b0d10d3553a728858b72ddc59e",
          "body": "- Indent every secondary screen's subtitle to the title column (was 2, now 4),\n  matching the headings.\n- Usage screen: drop the doubled blank under the subtitle, remove the Copy/Back\n  button row for a keyboard hint (c copy · Esc back); wire 'c' to copy and Esc\n  to back in the loop.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): indent secondary subtitles + strip the Usage button row",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T11:14:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "371a49485bc32f57d3cc65070e2c8f29ad22e227",
          "body": "…de packing, pptx (#109)\n\n* reporting overhaul: threaded generate, themes, deck styles, smart slide packing, pptx\n\nBring Reporting mode to parity with analysis/standup and make the exported\npresentations business-ready:\n\n- threaded generation behind the shared progress screen (on_progress /\n  cancel\n[…]\nthropic.com>\n\n---------\n\nCo-authored-by: Dev Person <dev@example.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>",
          "is_bot": false,
          "headline": "reporting overhaul: threaded generate, themes, deck styles, smart sli…",
          "author_name": "Dinho",
          "author_login": "dinho149",
          "committed_at": "2026-07-28T11:02:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7a68177e9ac997dc92710105fa9e3887f43bd9f7",
          "body": "Every secondary screen (usage, standup, retro, poker, performance, reporting,\nanalysis, changelog, all-tips, roadmap, project list…) indented content via a\nmix of PAD and its _PAD alias, both 4 spaces — deeper than the title. Point the\nwhole file at one 2-space _PAD so headings land at the title's c\n[…]\nmn and value\nrows one level in, matching Settings. All PAD refs in the file collapse to _PAD;\nlen(_PAD)-based width math stays self-consistent.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): unify secondary-screen indentation with the Settings scheme",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:59:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a7bb19c05ab87bb993678b99e925b6f5d429a8ae",
          "body": "Clicking a row now turns its value into an inline edit field (buffer + block\ncursor) right on the settings screen — the rest of the rows stay visible —\nrather than opening a full-screen input. Type/backspace/arrows/paste edit the\nbuffer; Enter saves to .env (applies log level live), Esc cancels. Hid\n[…]\n-aware flow. The full-screen _settings_edit_field is replaced by\n_settings_edit_keypress; the hint switches to edit instructions while editing.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): edit config rows in place instead of a separate prompt",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:44:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cc570455701fe60e25a99eef21e340abb529e4f6",
          "body": "Each section heading already leads with a blank, so the extra blank after the\ntab bar doubled the gap before the first heading. Remove it and shift the\nviewport/​row-region math up one row to match.",
          "is_bot": false,
          "headline": "fix(settings): drop the doubled blank line under the tab bar",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:36:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "00f12351655bea9d446dcb01e6353445e2d0e5e1",
          "body": "Previously only the main menu showed the 'resize me' guard below the size\nfloor; settings, hubs, wizards and the rest rendered cramped/clipped. Add the\ncheck to MusicLive.get_renderable — the single chokepoint every screen renders\nthrough — so any screen under _MIN_WIDTH×_MIN_HEIGHT (84×40) shows the too-small\nduck instead. Test consoles bumped above the floor where they exercise other\nbehaviour.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): enforce the min terminal size on every screen",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:30:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3e4e89dfea5e50f33eb0bd79115584d53a48d925",
          "body": "Every env-backed row is now clickable: clicking opens an inline editor for that\nvariable, persists it to .env (set_config_value) and applies live where needed\n(log level). Rows carry their (env, label, masked) via an _EditableRow Text\nsubclass; the builder attaches per-row click regions (absolute ro\n[…]\n); Data Directory routes to the existing move-aware flow; read-only rows\n(Dictation status, Config File path) stay non-clickable. Hint updated.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): click any config row to edit its value",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:19:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6b0288ee832c240db35a37e2e7ec4311e343baf2",
          "body": "Extend the rule two chars past each end of the tab strip so the dimmer shoulder\nbeside the active tab stays visible when the first or last tab is selected.",
          "is_bot": false,
          "headline": "feat(settings): keep a 2-char margin on the tab underline",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:07:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd71ac6f6349efce4ab652b2d266cd8519abfbd5",
          "body": "Start the rule at the first tab's left edge (no longer poking out left of\nCredentials) and end it at the last tab's right edge.",
          "is_bot": false,
          "headline": "feat(settings): span the tab underline exactly under the tab strip",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:05:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "484842a11583083ab52575bc183952c72e4a3e79",
          "body": "The rule ran nearly edge-to-edge; end it just past the last tab so it reads as\na compact tab underline rather than a full-width divider.",
          "is_bot": false,
          "headline": "feat(settings): shorten the tab-bar underline to the tab strip",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T10:02:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c16f13e4ed2cebb9a3c5a63db898abe993f4d5b2",
          "body": "Refine the tabbed Settings screen per feedback:\n- Underline-style tab bar: labels over one continuous horizontal rule, the\n  segment under the active tab accent-bright with dimmer flanking chars, no\n  vertical dividers. Clicks hit-test attached tab regions (labels + rule rows).\n- Group into 3 broad \n[…]\n Drop the 'Current configuration' subtitle; align content indent with the\n  SETTINGS title (headings at the title's column, rows one level in).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): underline tab bar, 3 grouped tabs, aligned indent",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T09:58:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "409cfefa029dd7d6fae1dff96fab6391787523f6",
          "body": "Replace the long scrolling all-sections list + action-button row with a tabbed\nview: a top tab bar (Provider, Jira, Azure, GitHub, Notion, Storage, Standup,\nVoice, Bedrock, Advanced) switches which config section is shown. ←/→ (and Tab)\ncycle tabs; clicking a tab jumps to it (tab_click in _click.py \n[…]\none: Esc = Back, and\nEnter runs the section's context action — data-dir editor on Storage, log-level\ncycle on Advanced, setup wizard elsewhere.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): tabbed section view with a clickable tab bar",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T09:33:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e52a8dcff307f7cd98340713fad2a89ad9cc0fe9",
          "body": "The formatter stripped button_click from the import while it was briefly\nunused mid-edit; clicking a destination would have raised NameError.",
          "is_bot": false,
          "headline": "fix(export-picker): restore dropped button_click import",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T09:33:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81decc8f29156808705db10a48508ffd8d011592",
          "body": "First slice of app-wide click support. New src/yeaboi/ui/shared/_click.py:\nparse_click() decodes click events, button_click() maps a click to a\nbuild_action_buttons index by hit-testing the ACTUAL rendered frame (scans for\nthe ╭──╮ button runs), so it's robust to top-flowed vs bottom-anchored rows,\nvariable title heights, and popup shifts — no per-screen geometry. Wired into\nthe shared export-destination picker and the output-share screen.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): add shared click hit-testing + wire export/share buttons",
          "author_name": "neakoh",
          "author_login": "neakoh",
          "committed_at": "2026-07-28T09:01:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 66,
      "commits_last_year": 442,
      "latest_release_at": "2026-08-02T11:01:11Z",
      "latest_release_tag": "v2.47.1",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 7,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 0.7
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "yeaboi",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "agile",
            "ai-agent",
            "ai-scrum-master",
            "azure-devops",
            "cli",
            "jira",
            "llm",
            "mcp",
            "planning-poker",
            "project-management",
            "retrospective",
            "scrum",
            "sprint-planning",
            "standup",
            "tui",
            "Development Status :: 4 - Beta",
            "Environment :: Console",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: MIT License",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Topic :: Software Development :: Libraries :: Application Frameworks"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/yeaboi/",
          "is_deprecated": false,
          "latest_version": "2.47.1",
          "repository_url": "https://github.com/dinho149/yeaboi.ai",
          "versions_count": 48,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 5329,
          "first_published_at": "2026-07-16T13:02:12.224821Z",
          "latest_published_at": "2026-08-02T11:00:51.613679Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 2,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 4
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "example"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [
        "Makefile",
        "desktop-pet/node_modules/json-stringify-safe/Makefile",
        "desktop-pet/node_modules/progress/Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "desktop-pet/node_modules/boolean/tsconfig.json",
        "desktop-pet/node_modules/define-data-property/tsconfig.json",
        "desktop-pet/node_modules/es-define-property/tsconfig.json",
        "desktop-pet/node_modules/es-errors/tsconfig.json",
        "desktop-pet/node_modules/gopd/tsconfig.json",
        "frontend/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 584773,
      "source_files_sampled": 688,
      "oversized_source_files": 25,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 18378
    },
    "dependencies": {
      "manifests": [
        "frontend/package.json",
        "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": [
        "npm",
        "pypi"
      ],
      "dependencies": [
        {
          "name": "preact",
          "manifest": "frontend/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.29.1"
        },
        {
          "name": "langchain",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "langgraph",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "langchain-anthropic",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "rich",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "prompt-toolkit",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "python-dotenv",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "PyGithub",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "azure-devops",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "jira",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "atlassian-python-api",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "notion-client",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "langgraph-checkpoint-sqlite",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "holidays",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "segno",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        }
      ],
      "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": 3,
        "merged_prs": 114,
        "open_issues": 1,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 14
      },
      "bus_factor": 1,
      "bot_contributors": 2,
      "top_contributors": [
        {
          "type": "User",
          "login": "neakoh",
          "commits": 207,
          "avatar_url": "https://avatars.githubusercontent.com/u/114689967?v=4"
        },
        {
          "type": "User",
          "login": "dinho149",
          "commits": 108,
          "avatar_url": "https://avatars.githubusercontent.com/u/64692956?v=4"
        },
        {
          "type": "User",
          "login": "nikomain",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/208644664?v=4"
        }
      ],
      "contributors_sampled": 3,
      "top_contributor_share": 0.653
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "auto-version.yml",
        "backlog-groomer.yml",
        "ci-sentinel.yml",
        "ci.yml",
        "claude-review.yml",
        "claude.yml",
        "codeql.yml",
        "dependabot-auto.yml",
        "feedback-remediation.yml",
        "flaky-test-hunter.yml",
        "publish.yml",
        "security-scan.yml",
        "smoke.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".eslintrc",
        ".eslintrc.json"
      ],
      "has_editorconfig": true,
      "has_linter_config": true,
      "has_precommit_config": true
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json",
        "uv.lock",
        "yarn.lock"
      ],
      "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": 3,
            "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": "15 out of 15 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/14 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": 10,
            "reason": "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": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "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": 8,
            "reason": "SAST tool detected but not run on all commits",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file 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": 5,
            "reason": "5 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "8f4d56290f6118a5fc290628b8373ad44caf6bf5",
        "ran_at": "2026-08-02T11:04:28Z",
        "aggregate_score": 5.9,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": true,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-08-02T11:03:46Z",
      "oldest_open_prs": [
        {
          "number": 125,
          "created_at": "2026-08-01T13:26:45Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 130,
          "created_at": "2026-08-01T20:31:36Z",
          "last_comment_at": "2026-08-01T20:39:53Z",
          "last_comment_author": "claude"
        },
        {
          "number": 131,
          "created_at": "2026-08-02T10:32:18Z",
          "last_comment_at": "2026-08-02T10:33:40Z",
          "last_comment_author": "claude"
        }
      ],
      "last_merged_pr_at": "2026-08-02T10:58:29Z",
      "ci_last_conclusion": "SKIPPED",
      "oldest_open_issues": [
        {
          "number": 105,
          "created_at": "2026-07-27T10:22:01Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/dinho149/yeaboi.ai",
    "host": "github.com",
    "name": "yeaboi.ai",
    "owner": "dinho149"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": "The weighted overall 65 is calibrated to 75 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 65,
            "calibrated": 75,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 75,
      "inputs": {
        "security": 59,
        "vitality": 81,
        "community": 33,
        "governance": 46,
        "calibration": "2026-08-02",
        "engineering": 100,
        "ai_readiness": 82,
        "weighted_overall_raw": 65
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 81,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "commits_last_year": 442,
              "human_commit_share": 0.99,
              "days_since_last_push": 0,
              "active_weeks_last_year": 7
            },
            "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": "7/52 weeks with commits",
                "points": 4.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 7
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "442 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 442
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "exceptional",
            "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": 66,
              "latest_release_tag": "v2.47.1",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 0.7
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "66 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 66
                    }
                  }
                ],
                "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.7 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.7
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "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": "at_risk",
        "name": "Community & Adoption",
        "value": 33,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 2,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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,
              "readme_badges": null,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (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
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 62,
            "inputs": {
              "packages": [
                "yeaboi"
              ],
              "dependents": null,
              "ecosystems": "pypi",
              "total_downloads": null,
              "monthly_downloads": 5329
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "5,329 downloads/month across pypi",
                "points": 49.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 5329,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "weak",
        "name": "Sustainability & Governance",
        "value": 46,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 21,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 3,
              "top_contributor_share": 0.653
            },
            "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 65% of commits",
                "points": 7.8,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 65
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "3 contributors",
                "points": 4.1,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "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": "at_risk",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 31,
            "inputs": {
              "merged_prs": 114,
              "open_issues": 1,
              "closed_issues": 0,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 14,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "114/128 decided PRs merged",
                "points": 26.7,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 114,
                      "decided": 128
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/14 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "weak",
            "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": 47,
            "inputs": {
              "followers": 3,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "dinho149",
              "public_repos": 38,
              "account_age_days": 2282
            },
            "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": "3 followers of dinho149",
                "points": 4.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 3,
                      "login": "dinho149"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "38 public repos, account ~6 yr old",
                "points": 23.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 38
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "yeaboi"
              ],
              "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": "48 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 48
                    }
                  }
                ],
                "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": "exceptional",
        "name": "Engineering Quality",
        "value": 100,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "exceptional",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": true,
              "has_precommit_config": true
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "13 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "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": ".eslintrc, .eslintrc.json",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc, .eslintrc.json"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 9.6,
                "status": "met",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "15 out of 15 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "exceptional",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "agile",
                "ai-agent",
                "ai-scrum-master",
                "azure-devops",
                "claude",
                "cli",
                "jira",
                "langgraph",
                "llm",
                "mcp",
                "mcp-server",
                "planning-poker",
                "python",
                "retrospective",
                "scrum",
                "scrum-master",
                "sprint-planning",
                "standup",
                "terminal",
                "tui"
              ],
              "has_wiki": true,
              "homepage": "https://yeaboi.ai/",
              "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": "https://yeaboi.ai/",
                "points": 15,
                "status": "met",
                "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": "20 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 20
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 59,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "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": 59,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 5.9
            },
            "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": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "15 out of 15 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/14 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": "update tool detected",
                "points": 7.5,
                "status": "met",
                "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": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "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 detected but not run on all commits",
                "points": 4,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "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": "5 existing vulnerabilities detected",
                "points": 3.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 3
            },
            "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": "excellent",
        "name": "AI Readiness",
        "value": 82,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 18378
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "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": "99 of 99 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 99,
                      "sampled": 99
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json",
                "uv.lock",
                "yarn.lock"
              ],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [
                "Makefile",
                "desktop-pet/node_modules/json-stringify-safe/Makefile",
                "desktop-pet/node_modules/progress/Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "desktop-pet/node_modules/boolean/tsconfig.json",
                "desktop-pet/node_modules/define-data-property/tsconfig.json",
                "desktop-pet/node_modules/es-define-property/tsconfig.json",
                "desktop-pet/node_modules/es-errors/tsconfig.json",
                "desktop-pet/node_modules/gopd/tsconfig.json",
                "frontend/tsconfig.json"
              ],
              "agent_commit_share": 0.9,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0.01
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile, desktop-pet/node_modules/json-stringify-safe/Makefile, desktop-pet/node_modules/progress/Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile, desktop-pet/node_modules/json-stringify-safe/Makefile, desktop-pet/node_modules/progress/Makefile"
                    }
                  }
                ],
                "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": ".eslintrc, .eslintrc.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc, .eslintrc.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "90 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 90,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "1 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 1,
                      "sampled": 100
                    }
                  }
                ],
                "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": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 584773,
              "source_files_sampled": 688,
              "oversized_source_files": 25
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python with type-check config (desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "desktop-pet/node_modules/boolean/tsconfig.json, desktop-pet/node_modules/define-data-property/tsconfig.json, desktop-pet/node_modules/es-define-property/tsconfig.json, desktop-pet/node_modules/es-errors/tsconfig.json, desktop-pet/node_modules/gopd/tsconfig.json, frontend/tsconfig.json",
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "25/688 source files over 60KB",
                "points": 53,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 688,
                      "oversized": 25
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "example"
              ],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "example",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "example"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "top": [
        "library",
        "application"
      ],
      "labels": [
        "library",
        "mcp-server",
        "web-ui"
      ],
      "scores": {
        "cli": 2,
        "tui": 2,
        "web-ui": 4,
        "library": 6,
        "mcp-server": 5
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:pypi",
          "weight": 6
        },
        {
          "tier": "dependencies",
          "label": "web-ui",
          "source": "dep:preact",
          "weight": 4
        },
        {
          "tier": "structure",
          "label": "mcp-server",
          "source": "mcp_signal",
          "weight": 3
        },
        {
          "tier": "tags",
          "label": "cli",
          "source": "tag:cli",
          "weight": 2
        },
        {
          "tier": "tags",
          "label": "mcp-server",
          "source": "tag:mcp-server",
          "weight": 2
        },
        {
          "tier": "tags",
          "label": "tui",
          "source": "tag:tui",
          "weight": 2
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": true,
      "consumed_by_code": true
    },
    "metrics_version": "2.5.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index pypi:yeaboi@2.47.1; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-08-02T11:04:47.299171Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/d/dinho149/yeaboi.ai.svg",
  "full_name": "dinho149/yeaboi.ai",
  "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 v2.5.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenPyPI.