Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-29 16:18 UTC

cosxai / product-design

Internal design system — chrome-themed component library for cosX. shadcn-style copy-paste source, 11 chrome variants.

TypeScript · CSSSin licencia detectada★ 0 estrellas⑂ 0 forksdesde may 2026Ver en GitHub ↗

cosxai/product-design tiene un índice de salud de 42 sobre 100, lo que lo sitúa en la banda En riesgo. Su puntuación más alta es AI Readiness (62/100) y la más baja, Community & Adoption (26/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

42
global / 100
En riesgo

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

42
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

COSXOrganización
3 seguidores1 repositorio públicodesde ago 2025

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
npm@cosxai/ui0.20.0512364hace 0 días
npm@cosxai/blocks0.12.1389024hace 8 días

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

37En riesgo · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
6.9/36Cadencia de commits — 10/52 semanas con commits
18/18Volumen de commits — 113 commits en el último año
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Datos de entrada utilizados
commits_last_year113
human_commit_share1
days_since_last_push0
active_weeks_last_year10
Cómo se puntúa
0/27Publica versiones — sin versiones publicadas
0/36Recencia de las versiones — sin versiones
0/27Cadencia de publicación — sin versiones
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count0
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

26Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
0/22.5Licencia — no se detectó ningún archivo de licencia
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_licenseno
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno
Cómo se puntúa
52.7/80Descargas mensuales — 9013 descargas/mes en npm
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packages@cosxai/ui, @cosxai/blocks
dependents
ecosystemsnpm
total_downloads
monthly_downloads9013
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

56Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
46.8/46.8Resolución de issues — 100% de issues cerradas
38.2/38.3Aceptación de PR — 11/11 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs11
open_issues0
closed_issues2
issue_closed_ratio1
closed_unmerged_prs0
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
4.3/25Alcance del propietario — 3 seguidores de cosxai
4.2/25Trayectoria — 1 repos públicos, cuenta de ~0 años
Datos de entrada utilizados
followers3
owner_typeOrganization
is_verified
owner_logincosxai
public_repos1
account_age_days358
Cómo se puntúa
25/25Publicado y resoluble — 2 paquete(s) en npm
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 64 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packages@cosxai/ui, @cosxai/blocks
ecosystemsnpm
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

48En riesgo · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
0/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_testsno
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

36En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
4.5/7.5Branch-Protection — branch protection is not maximal on development and all release branches
0/2.5CI-Tests — sin datos
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5Licencia — license file not detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — sin datos
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
1.5/7.5Vulnerabilities — 8 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate3,6
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, packaging, signed_releases. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

62Moderado · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 96 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,96
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes3054
Cómo se puntúa
0/18Arranque con un solo comando
0/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — apps/docs/tsconfig.json, packages/blocks/tsconfig.json, packages/ui/tsconfig.json
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 63 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_testsno
lockfilespnpm-lock.yaml
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configsapps/docs/tsconfig.json, packages/blocks/tsconfig.json, packages/ui/tsconfig.json
agent_commit_share0,63
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — TypeScript (tipado estático)
55/55Tamaños de archivo manejables — 0/139 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageTypeScript
largest_source_bytes45.781
source_files_sampled139
oversized_source_files0

Datos clave

0estrellas de GitHub
1contribuidores
113commits en los últimos 12 meses
0días desde el último push
0versiones publicadas
1factor bus
0issues abiertas
npmecosistemas de paquetes

Advertencias de recopilación de datos

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Más detalle

OpenSSF Scorecard 3.6 / 10
3.6agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-29 16:18 UTC

10Binary-Artifactsno binaries found in the repo
6Branch-Protectionbranch protection is not maximal on development and all release branches
n/dCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/dPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
2Vulnerabilities8 existing vulnerabilities detected
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 928,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "CSS": 134193,
        "HTML": 1806,
        "TypeScript": 617044
      },
      "pushed_at": "2026-07-28T18:55:24Z",
      "created_at": "2026-05-26T22:03:08Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-28T18:58:08Z",
      "description": "Internal design system — chrome-themed component library for cosX. shadcn-style copy-paste source, 11 chrome variants.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "CSS"
      ]
    },
    "owner": {
      "blog": null,
      "name": "COSX",
      "type": "Organization",
      "login": "cosxai",
      "company": null,
      "location": null,
      "followers": 3,
      "avatar_url": "https://avatars.githubusercontent.com/u/224823687?v=4",
      "created_at": "2025-08-05T15:18:07Z",
      "is_verified": null,
      "public_repos": 1,
      "account_age_days": 358
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [],
      "recent_commits": [
        {
          "oid": "c1ea6bdd4e2274ffe224a53b59a09b00572a7ac2",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge feature/command-item-disabled — CommandItem disabled (v0.20.0)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-28T18:55:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8fb4a51ca823904a20de57fb2f5c4ba3e7184fd3",
          "body": "A disabled row renders (dimmed) but is skipped by arrow-key nav, never\nauto-selected (the default highlight lands on the first enabled row),\nignores hover/click, and never runs. For coming-soon teasers — distinct\nfrom secret (which hides the row). Derive an effective selection index so\na disabled item is never highlighted. Version 0.19.0 -> 0.20.0.\n\nUnblocks product-meta's ⌘K \"Agent (Coming soon)\" item.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(command): CommandItem disabled — dimmed, non-selectable teaser rows",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-28T18:55:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "16af7d0bff88893c32fd1ab4ed581190fc4310d7",
          "body": "…hange (v0.19.0)\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge feature/command-palette-onquerychange — CommandPalette onQueryC…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-28T17:06:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "44ef000a84820c8870a400d707a9f55c5892eb66",
          "body": "The palette owns its query in local state and exposed it nowhere, so a\nconsumer couldn't drive an async command source (type → debounce → fetch\n→ show results). Add an optional, backward-compatible onQueryChange prop\nthat fires on every keystroke and on the open reset-to-empty. The open\neffect reads\n[…]\nrun it (which would clear the query each render).\n\nUnblocks product-meta global document search in the command palette.\nVersion 0.18.2 → 0.19.0.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(command): CommandPalette onQueryChange for async command sources",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-28T16:56:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dc924926b1824b974c7e0878ed92a23c5e87da84",
          "body": "The 2026-07-19 scrollbar slimming used only the standard\nscrollbar-width/scrollbar-color properties, which Chromium learned\nin 121 — older engines fell back to the classic Windows arrow-button\ngutters (QA: Ben). Add the ::-webkit-scrollbar layer as fallback;\nengines with standard-property support ignore the pseudo-elements\nwhen scrollbar-width is set, so the blocks never conflict.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.18.2 — webkit scrollbar fallback for Chromium < 121",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-24T09:38:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6fa99b80f19e3a41f701f88abe8be490ebfec1b3",
          "body": "useKeyboardHotkey's skipInputs guard treated any focused\ncontentEditable as \"user is typing\" — canvas components (Univer's\nread-only grid in product-meta) park focus in a hidden cell-editor\nhost, which silenced the ⌘K/Ctrl+K palette entirely. Containers\nmarked data-hotkey-passthrough=\"true\" now bypass the editable\ncheck, mirroring the convention product-meta already uses for its\nviewer hotkeys.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.18.1 — hotkey passthrough containers",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-23T21:20:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6987640951266d01c4c3651882eb1ad6474501bb",
          "body": "…ReactNode to render\n\nPassing consumer JSX through context state re-render-looped: content\ngets a fresh identity every consumer render, so the registration\neffect fired setPanel each time, the context value changed, the\nconsumer re-rendered, and around it went until OOM. The bar now\nrenders an EMPTY\n[…]\nlag) flows through context state.\n\nBreaking: both hooks now RETURN a ReactNode the consumer must render\n(previously void).\n\nrelease(ui): v0.18.0\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(actionbar)!: portal-host panel/toast slots — hooks now return a …",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-22T22:44:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "433748a2ba652e9017eced6dc278dc16989e3654",
          "body": "… crash)\n\n0.17.0 placed the design#13 panel effects after the empty-state and\nphone-collapsed early returns, so the hook count changed whenever the\nbar transitioned between those states and React threw 'Rendered more\nhooks than during the previous render'.\n\nrelease(ui): v0.17.1\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(actionbar): move panel-slot hooks above early returns (hook-order…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-22T22:32:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "154b8673a3c86f4f07cc5b5e92f9b8c38a5a7866",
          "body": "…onBarToast (design#13)\n\nThe bar gains a bar-intrinsic popover slot, sibling of the status\ndot: the BAR owns positioning (docked above itself, centered,\nfollowing drag natively, viewport-clamped, outside-click + Escape\nclose) and the chrome themes own the panel's visual identity via\n.ck-actionbar-pa\n[…]\noses #13. First consumer: metaroom's notification center, which\ndeletes its querySelector+poll anchoring hack on adoption.\n\nrelease(ui): v0.17.0\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): ActionBar panel + toast slots — useActionBarPanel / useActi…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-22T22:24:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "edf6d0d8ff0972e9bb7a29c6fe90a2bbe4017f30",
          "body": "新原语,自 product-meta CustomerPicker 抽象(QA 2026-07-21:输入未确\n认与已确认视觉无差异,弱网下拉不出导致误以为已选)。模型:输入框常驻\n可编辑承载进行中状态;确认卡(title/subtitle/× + extra 插槽)承载已确\n认状态,由父组件受控。commit 路径:点选/Enter/失焦自动(结果精确匹配\n优先,否则 allowFreeEntry 自由输入 —— 不依赖下拉是否渲染,弱网可用);\n无法 commit 的文字失焦转 invalid 态(红框 + invalidHint)。\n\nrelease(ui): v0.16.0\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): Combobox — async-search commit picker with blur auto-commit",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-21T14:57:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4938359555164f9f76e75196dbfb485ff82c6782",
          "body": "The v0.9.0 read-only placeholder filled the whole box with\ncurrentColor when bakedValue=true — signed PDFs rendered checked\nboxes as black squares, nothing like the tick signers saw in the\nform UI (QA 2026-07-21, mesh doc 019f83ed). Replace the fill with an\ninline SVG tick stroked in currentColor so themed docStyles keep\ncontrolling the colour; unchecked boxes are unchanged.\n\nrelease(blocks): v0.12.1",
          "is_bot": false,
          "headline": "fix(blocks): doc-checkbox checked state draws a tick, not a solid fill",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-21T11:10:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2adb365484b3950a0509cada605df7daed68f287",
          "body": "Windows/Linux classic scrollbars rendered as heavy opaque gutters\nagainst the editorial surfaces; standard scrollbar-width/color slims\nand tints them from the theme border token. macOS overlay bars are\nunaffected.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.15.1 — themed thin scrollbars",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-19T18:28:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "390eafa026e2d84ddf4b984108fba72306f04486",
          "body": null,
          "is_bot": false,
          "headline": "release(ui): bump to 0.15.0 (version was left out of 86f8d5f)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T22:30:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "86f8d5f76a25d4bee2c9e5f3811d3dc86ddf55d7",
          "body": "Radiogroup-semantics segmented switch (roving tabindex, arrow-key\nwrap, per-option disabled + disabledHint). First consumer: the share\ndialog's delivery-mode switch in product-meta.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.15.0 — SegmentedControl primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T22:23:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c87258446334e358689a7b31bd7513b406c98187",
          "body": "A secret item is invisible to every query except an exact\n(case-insensitive) match of its phrase — never in empty listings,\nnever via partial matches. Powers hidden debug/test menus (metaroom's\n'cosxai' fixtures menu) on top of the existing grouped palette.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.14.0 — CommandItem.secret cheat-code gating",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T21:20:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3a1b196b5b61f6325b02212fbd9561d0a4e85a9c",
          "body": "…LETTE\n\n- SIGNER_PALETTE / signerColor exported: the canonical per-party\n  colours, so the in-doc pill and product-layer binding badges stop\n  disagreeing (QA: green S2 badge next to an orange SIGNER 2 pill)\n- BlockList gains partyLabels?: readonly string[] — the pill renders\n  the roster name (UPPE\n[…]\nthe block's EFFECTIVE\n  recipient (cascade-aware), falling back to 'SIGNER N'\n- pill background is signerColor(index) instead of a single accent\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.12.0 — party-aware SIGNER pill + shared SIGNER_PA…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T18:51:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c17af9068c4294d6660ba45acf8dfbf8e05a5815",
          "body": "A doc-signature inside a recipientIndex-carrying doc-section\n(section-level party binding, e.g. the imported MSA) showed no\nSIGNER N pill — the affordance only read the block's own\nrecipientIndex while interactivity already followed the cascade.\nPill, caption fallback and data-recipient-index now use\nresolveRecipientIndex(block, cascade); own index still wins.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.11.4 — SIGNER pill honours the recipient cascade",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T18:01:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "22db45fef2874ce6b5a0965e7461f22074e5a117",
          "body": "dataroom parity: rows no longer drives the placeholder minHeight —\nan unfilled textarea reads exactly like a doc-input line; filled or\nbaked content grows the box naturally (the signing fill surface\nalready auto-grows via scrollHeight).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.11.3 — doc-textarea empty state is one line tall",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T16:11:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "479aa715bfd4ad74291d1f5b02b966cb73f978b9",
          "body": "0.13.4 capped the canvas/input at maxWidth:100%, but the wrapper's\nwidth:fit-content sized itself to the canvas's intrinsic 480px, so\nthe 100% the children resolved against was the overflowing wrapper —\nphones still clipped. Cap the wrapper too.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.5 — SignaturePad wrapper capped at container width",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T12:05:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5991547daf547299044d09d32a5c3db2212c8d02",
          "body": "…w containers\n\nPhone signing surface (metaroom /sign): the 480px default canvas\noverflowed <480px viewports. maxWidth:100% + border-box; drawing\naccuracy unaffected — pointer handlers already rescale through\ngetBoundingClientRect.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.4 — SignaturePad canvas/input never overflow narro…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-18T10:42:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3fa2a9a51e6f696fba2e19b11bb3631182283a30",
          "body": "The image height followed the PLACEHOLDER line height (24px in the\neditorial seed), squashing the signature to a sliver.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.11.2 — baked signature ink renders at 48px",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T20:16:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eeab58ca55899afa0d41e640f45b54c1a21d43a4",
          "body": "The drawn-restore effect re-ran on mode change and painted the old\ntyped capture back onto the drawn canvas right after the clear\neffect wiped it. Restore now runs on mount only.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.3 — SignaturePad mode switch starts from a clean pad",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T18:05:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "63aefcc92ef14942a4be0103c2536f57c1647d4f",
          "body": "Drop the name/date/'Signed' caption + consent snippet under the\nbaked signature image (dataroom parity: audit page, the doc's Date\nfield row and the in-doc consent callout carry those; the 'Signed'\nfallback carried no information). The DocuSeal certificate link\nstays — the unique verifiable artefact.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.11.1 — baked signature renders ink only",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T16:47:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "70d4b876120d803ff2a7e08d549617502fbc95e0",
          "body": "fonts.ready alone never fetches an @font-face-registered face the\npage doesn't otherwise render — the canvas fillText silently fell\nback to the system cursive (Apple Chancery calligraphy, not a\nhandwriting look). fonts.load() forces the fetch before painting.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.2 — SignaturePad actively loads the typed font",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T16:41:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b6a2f8748c497ccaee80c83aa3320d61c6ef8a0e",
          "body": "… the typed repaint\n\nEffect ordering: the clear-on-mode-switch effect was declared after\nthe typed-repaint effect, so switching to typed mode with a\nprefilled name painted then immediately wiped the pad. Clear now\nruns FIRST (declaration order) and skips the mount run so a\nparent-held captured value survives first render.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.1 — SignaturePad mode-switch clear no longer wipes…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T16:36:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "99d46cad811299e5f869054878b053092448a812",
          "body": "Per-block render override consulted for every block in the tree\n(incl. section children / two-column halves / field-table\nvalueBlocks) with the effective recipientIndex from the\nrecipient-cascade. Lets the signing surface swap only its own\nparty's signable blocks while keeping full default chrome.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.11.0 — BlockList blockOverride hook",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T14:59:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9debf1bc854135db9a1671d10db646e1f88f0de0",
          "body": "New <CopyField> — read-only value + embedded Copy button in one\n36px field frame, matching Input's suffix-addon chrome (muted slab,\nhairline divider, radius-sm). Mono ellipsized value, click-to-select\nfallback, \"Copied ✓\" flash with reserved width so the layout doesn't\njitter. Graduated from product\n[…]\nhe URL box\nand separate COPY button read as two disconnected controls (Ben's\nfeedback: put Copy inside the URL box, make it a proper component).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.13.0 — CopyField primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T11:52:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "57640916d858e7b648469d857ffad714ffcc72be",
          "body": null,
          "is_bot": false,
          "headline": "feat(blocks): 0.10.3 — SIGN HERE tighter against the line",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T00:19:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a001efddcbdaf6e0ad1acee150e6e36ee9e17285",
          "body": "Verifying agent-dataroom's convention (DocBlocks.tsx:216-249):\nsigned / auto-filled values REPLACE the AUTO-FILLED hint but the\ndashed line UNDERNEATH stays as a \"fillable field\" cue. Signature\nblocks are different — the whole line + label vanish once signed,\nreplaced by the signature image.\n\nThe li\n[…]\nApplied to both DocInputPlaceholder + DocTextareaPlaceholder for\nconsistency (textarea autoFill lands rarely today but same rule).\n\nBump: 0.10.1 → 0.10.2 (patch — visual refinement, no schema change).",
          "is_bot": false,
          "headline": "feat(blocks): 0.10.2 — signed value renders as dark sans content",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T00:09:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0e93a9cfb644c0645311c2899285b6678102622c",
          "body": "Ben's screenshot review of 0.10.0: the SIGN HERE affordance shipped\nas plain grey uppercase text (label style), but agent-dataroom's\nreference has a colored pill for \"SIGNER N\" + mono font caption\nfor both \"SIGN HERE\" and \"AUTO-FILLED AT SIGNING\". Reads as a\nproper interaction affordance rather than\n[…]\nen. Blocks package renders one consistent\nbrand-colored pill; product decorates as it sees fit.\n\nBump: 0.10.0 → 0.10.1 (patch — visual refinement, no schema change).\nTag blocks-v0.10.1 → auto-publish.",
          "is_bot": false,
          "headline": "feat(blocks): 0.10.1 — SIGN HERE pill + mono font for signing hints",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-17T00:03:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "027677ddf97a1161983e72eb039fd89dd0f87dad",
          "body": "Two visible-state improvements for template authors previewing a\nsignable doc + signers viewing the /sign page:\n\n## DocSignaturePlaceholder — SIGN HERE prompt\n\nEmpty signature block previously rendered as just a dashed line\nwith a tiny \"Signature · Signer N\" caption below. Hard to tell it\napart from\n[…]\ned\nautoFillHintCopy() helper.\n\nReused by both signable text types now, consistent visual language.\n\nBump: 0.9.0 → 0.10.0 (minor — additive visual, no schema change).\nTag blocks-v0.10.0 → auto-publish.",
          "is_bot": false,
          "headline": "feat(blocks): 0.10.0 — SIGN HERE affordance + doc-input autoFill hint",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-16T23:44:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "866765faa93758bfa68002b882005392c0fbbaae",
          "body": "Three additive schema changes bringing the four signable block types\nto full parity so mesh's runtime autoFill resolution + the upcoming\nadmin config UI (M5+ Phase 3) can treat them uniformly.\n\n## Schema\n\n- DocTextareaBlock.autoFill — same enum as DocInputBlock\n  (signing-date | signer-name | signer\n[…]\nenders filled\n  (background: currentColor) so signed docs visibly differ from\n  unsigned ones.\n\nBump: 0.8.1 → 0.9.0 (minor — additive schema, no breaking API\nchange). Tag blocks-v0.9.0 → auto-publish.",
          "is_bot": false,
          "headline": "feat(blocks): 0.9.0 — signable schema parity + checkbox cascade",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-16T21:34:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c2e6219cb369cc58b96d53a8298e797323981450",
          "body": "DocSectionView rendered `<span>§{b.num}</span>`, injecting a § in\nfront of every section number. Ben flagged it against the NDA\nreference which uses plain \"1.\", \"2.\" — the § was unintended\nstyling on my part when the block was first drafted.\n\nCallers that want the § can put it in the num field explicitly\n(num=\"§1\"). Bare num renders as-is.\n\nBump: 0.8.0 → 0.8.1 (patch: no API change, visual regression fix\nfor consumers rendering doc-section — currently just mesh's NDA\nseed via product-meta).",
          "is_bot": false,
          "headline": "fix(blocks): drop hardcoded § prefix from doc-section num",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-16T19:44:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fba4334d89e2af3a32346a5a099652dced031a49",
          "body": "M5 · Signing prerequisite (Phase B0). Companion release to\n@cosxai/blocks 0.8.0.\n\n- `SignaturePad` primitive — typed + drawn e-signature capture,\n  emits image/png dataURL via canvas.toDataURL.\n  - Typed mode: signer types their name; canvas paints in Caveat\n    cursive with auto-fit font size. `doc\n[…]\n\n    on remount so continued strokes overlay rather than start blank.\n\nConsumed by product-meta's upcoming SignDocumentPage / SigningCommitBar.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.12.0 — SignaturePad primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-16T13:08:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fae2550a9c73882aff23d93b1fe3d2d05d473c64",
          "body": "…scade\n\nM5 · Signing prerequisite (Phase B0). Metaroom will consume this\nversion to build the interactive signing surface.\n\n- `ProseBlock.consentRole` + `CalloutBlock.consentRole` markers so a\n  template author can flag one block as the NDA/contract consent copy.\n  The signing service will snapshot \n[…]\n client / server cascade cannot drift.\n\nPurely additive; no breaking API changes vs 0.7.1. Existing\nnon-signing consumers see the same renders.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.8.0 — signing consent + baked-mode + recipient ca…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-16T13:07:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "202ca7ba32274e2c148d445e1c4c947fc4e100f5",
          "body": "QA follow-up on 0.11.1: dropping the bar chrome swap entirely made\nadmin mode ON read too subtle — the shield fill alone at the far\nleft is easy to miss when the eye is on the primary actions.\n\nRestore the border-colour swap (accent when admin ON) but leave\nbackground alone. Two-cue signal now:\n- bo\n[…]\nshield glyph fills (local, confirms the toggle)\n\nKeeps the 0.11.1 fix intact — no whole-bar background tint, so no\nhue-collision on item hover.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.11.2 — restore accent border on admin toggle",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-15T16:05:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "884eacdfbf0bc32d869262afce9ae4aa1ea77451",
          "body": "QA feedback: the admin-mode toggle was too heavy.\n\n- Whole-bar coral tint + accent border on admin ON competed with the\n  shield toggle for visual signal and produced awkward hue shifts\n  under the item hover overlay (cool grey `--ck-bg-muted` on the\n  tinted warm background composited to a slight g\n[…]\nhe\n  extra emphasis.\n- Drop the scale-up + spring transition (they were compensating for\n  the missing state signal that the fill now carries).\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.11.1 — actionbar admin toggle polish",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-15T15:19:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "09595243389ea159b19a9cf34e7af8edfda223c6",
          "body": "QA-reported 2026-07-15: three classes of block_doc viewer crashes\nand a text-overflow bug, all rooted in @cosxai/blocks.\n\nClass A · schema drift → `d.map is not a function`\nEvery renderer that walks a schema-declared list was calling\n.map() blindly. Hand-edited draft JSON, agent-generated content\nth\n[…]\nuard only kicks in for a run without one.\n\nZero API surface change. Consumers on 0.7.0 upgrade by bumping\ntheir dep — no code changes required.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.7.1 — array guards + long-text overflow wrap",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-15T09:57:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c07baab32361c4352911a3c8fca0e715bb7c193e",
          "body": "New <SidePanel> in the layout bucket. Right-docked, backdrop-less\npanel that slides in from the right edge and pushes main content\nleft via `--ck-sidepanel-width` (stamped on :root while open). For\neditors, activity feeds, share managers, and other admin surfaces\nwhere the reader should keep interac\n[…]\nl-width, 0px));\n\nDeliberately separate from --ck-rightrail-width so a transient\nSidePanel doesn't narrow persistent right-rail chrome + topbar.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.11.0 — SidePanel primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-14T21:11:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd4d093470eaa4e1442a41dd931ee4cc297193da",
          "body": "release(blocks): v0.7.0 — appearance out of package, nested DocStyle",
          "is_bot": false,
          "headline": "Merge pull request #12 from cosxai/release/blocks-v0.7.0",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T22:48:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e44a5a3cedcf9536c5538e33a6a5e6973b5f3a23",
          "body": "- styles.ts: restore index signature on DocStyle to preserve the\n  \"unknown block-type keys ignored\" forward-compat promise. Without\n  it, a doc authored against a newer package that adds a block\n  type would trip TS excess-property errors when its docStyle is\n  loaded here.\n- styles.ts: clarify the\n[…]\n\n  resolveStyle before applying column-specific alignStyle +\n  widthStyleFor overlays (schema-trusted, applied last).\n\nTypecheck + build clean.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(blocks): PR #12 Copilot findings",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T22:47:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7112de17f37f4fc29222bd9cc543ee7616d0996e",
          "body": "Breaking release. Strips APPEARANCE (fontFamily, colors, spacing,\nborders, dimensional theme values) from INTERNAL_DEFAULTS; those live\nin DATA now (product-mesh's documents.draft_style +\ndocument_commits.style JSONB, seeded by template_seeds.go's\nbuildSeedDraftStyle).\n\nDocStyle shape change: flat {\n[…]\neditorial bank in seed + migration\n000042 backfill) merges first, then this v0.7.0 npm publish, then\nmesh htmlproc pin bump, then SPA pin bump.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.7.0 — appearance out of package, nested DocStyle",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T22:15:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cd71301d9f153d1a827a4608f7ade8b68f854d4f",
          "body": "fix(blocks): 0.6.1 — purge CSS var refs + explicit fontFamily on every block root",
          "is_bot": false,
          "headline": "Merge pull request #11 from cosxai/fix/blocks-heading-serif-fallback",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T21:27:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ec90a8c2ade678114ee37c274b0b68ff100c407",
          "body": "Following review: extend the fix from \"h1 fontFamily fallback\" to a\nfull audit of styles.ts. The plan's core premise is content = fully\nself-contained; any block-root style that omitted fontFamily was\nimplicitly deferring to the consumer's body font (Geist in SPA and\nhtmlproc alike, but only by acci\n[…]\n etc.).\n\nDownstream ripple:\n- mesh htmlproc pin bump 0.6.0 → 0.6.1 (build workflow auto-fires)\n- SPA has ^0.6.0 so picks up 0.6.1 automatically\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(blocks): 0.6.1 — audit-scope expansion, purge CSS var refs",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T21:21:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0ac2bad74a94d2316ff37e8f40eac01b671c2744",
          "body": "htmlproc-rendered PDFs came out with h1 in Geist (default body sans)\ninstead of Playfair Display, because @cosxai/blocks v0.6.0's\nINTERNAL_DEFAULTS didn't set fontFamily on the heading levels — SPA\nwas picking up Playfair via metaroom's @cosxai/ui chrome-editorial\nCSS element rule (`html[data-ck-chr\n[…]\nm: mesh htmlproc pin bump 0.6.0 → 0.6.1 required (build\nworkflow auto-fires on the pin bump). SPA has ^0.6.0 so picks up\n0.6.1 on next install.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(blocks): v0.6.1 — h1/h2 pick up serif display font",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T21:13:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0d528eebae874fc0375160c2ba9fb5cd42a3b78c",
          "body": "release(blocks): v0.6.0 — data-driven inline styles",
          "is_bot": false,
          "headline": "Merge pull request #10 from cosxai/feature/blocks-inline-style-v0.6",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T20:18:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7de632fee4e07d8d2b03ded3e14bf559c0912b4e",
          "body": "1. styles.ts:146 stale reference — comment claimed \"see\n   BlockRenderer.test.tsx for the pin\" but no test file exists at\n   v0.6.0 (vitest harness deferred to follow-up). Rewritten to\n   describe the actual validation path: downstream SPA viewer +\n   htmlproc PDF smoke.\n\n2. TwoColumnView backward-c\n[…]\nxtraction\n   fallback that lifts the value out of `w-[<value>]` and applies\n   it as inline width, preserving the old behaviour for those docs.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: PR #10 review — 2 Copilot findings",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T20:17:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5d0cde0e00827a5c47b355490ea42268f147638f",
          "body": "BREAKING: BlockRenderer emits inline `style={...}` on every element\ninstead of Tailwind className strings. Consumers no longer need to\nbundle Tailwind CSS to render @cosxai/blocks output correctly.\n\nMotivation: product-mesh's htmlproc sidecar had no Tailwind bundle,\nso downloaded PDFs painted as uns\n[…]\n harness deferred (see workdoc) — no test infra existed at\nv0.5.x. Downstream integration smokes (SPA viewer + htmlproc PDF)\ngate this release.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(blocks): v0.6.0 — data-driven inline styles",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-13T18:48:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "863e42eda2e61f72527b382fd61c7428e7d42302",
          "body": "BREAKING: removes Slide, Doc, and BrandProvider from the public API.\n\nThe 0.5.0 release completes the M4.5 收尾 split: chrome (page shells,\nbrand slots, sizing, page counters, print CSS) belongs to the\nconsumer, not the shared content package. Content (block schema,\nBlockRenderer / BlockList, per-type\n[…]\nump in lockstep\n\n- product-mesh htmlproc — `cmd/htmlproc/package.json` → `\"0.5.0\"` exact\n- product-meta — `web/package.json` → `\"^0.5.0\"`\n\nCompanion changes ship as separate PRs in each consumer repo.",
          "is_bot": false,
          "headline": "release(blocks): v0.5.0 — content-only package",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-10T12:21:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "21109d5fae44f747e377f8f83e6f0408d9cace70",
          "body": "Match the PDF viewer's minimal chrome pattern in the block_doc\nviewer: a mono \"Page N / Total\" label strip above the frame, plain\npage content inside, nothing else. Removes the in-frame running\nheader from BOTH viewer mode AND renderMode (the 0.3 renderMode\nstrip is subsumed by this rewrite).\n\nBefor\n[…]\n still exported from the package for backward compat but no\nlonger wired to any chrome slot. Templates will supersede\nBrandProvider entirely.\n\nConsumers (mesh htmlproc + product-meta) will pin ^0.4.0.",
          "is_bot": false,
          "headline": "release(blocks): v0.4.0 — PDF-style viewer chrome for Slide + Doc",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-10T09:06:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a41ca3e2ed0d4c1c14361ffbee2379f0038d855a",
          "body": "Thumbnails are a picture of authored content, not workspace-branded\nviewer chrome. Slide/Doc's `renderMode=true` branch now drops the\nbrand-derived decoration on every page:\n\n- Header logo `<img>` no longer renders (both Slide + Doc)\n- Slide's confidential-line on the top-right no longer renders\n- S\n[…]\nce-scoped decoration, but it's\nactually part of the rendered page. Thumbnails should be neutral\nuntil templates carry brand explicitly.\n\nConsumers (mesh htmlproc + product-meta) will follow with pins.",
          "is_bot": false,
          "headline": "release(blocks): v0.3.0 — Slide/Doc suppress brand chrome in renderMode",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T22:34:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "40dd2c24957ea841dbc8456a67ec2d30b991658b",
          "body": "* feat(blocks): emit dist/ so Node consumers skip runtime TS transpile\n\nPublishing source TypeScript worked for SPA consumers (Vite / esbuild\ntranspile in the pipeline) but broke the mesh htmlproc sidecar's\nplain Node runtime — it crashed on startup with ERR_UNKNOWN_FILE_EXTENSION\nloading node_modul\n[…]\n exports — the emitted bundle is now directly\nconsumable by plain Node 20+.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Emit dist/ so Node consumers skip runtime TS transpile (#9)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T17:43:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b39a7bc3fffc77ed289d12677f5ba522776750a9",
          "body": "* feat(blocks): extract @cosxai/blocks package from product-meta\n\nNew workspace package holding the block-based content renderer\nthat was previously living inside product-meta/web/src/components/\nblock-doc/. Consumed by two independent parties: product-meta SPA\n(interactive viewing / draft preview /\n[…]\nso consumers on ^0.1.0 auto-pick up the\nimprovements on their next install.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Extract @cosxai/blocks: shared block renderer + Slide/Doc chrome (#8)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T17:02:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "50532c2a78dcefb11f9fc5a69e18c5d7fc07b79b",
          "body": "…e (v0.10.4)\n\nTwo coupled fixes for admin mode's cross-page state leak.\n\n## Session-only\n\nWas: adminMode persisted to localStorage as \\`<storageKey>:admin\\`.\nNow: state lives in useState only.\n\nProblems the persistence caused:\n- Page reload came back in elevated state without explicit user\n  opt-in \n[…]\n\n- Consumers previously relying on the persistence (there were none)\n  now see fresh state per session — write to \\`<storageKey>:admin\\`\n  yourself if you need the old behaviour on a specific surface.",
          "is_bot": false,
          "headline": "fix(actionbar): session-only admin mode + auto-reset on context chang…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T13:19:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "79b25d296698649631ec9fbb1c83c868914e8a5b",
          "body": "Symmetric counterpart to adminOnly. Together they let pages pick\nbetween two shapes without a kit-level \"mode\":\n\n- **additive** (default): normal items unmarked stay visible in\n  both modes; admin items marked adminOnly appear alongside when\n  the shield is on.\n- **exclusive**: normal items marked h\n[…]\n# API\n\n- Additive minor: `hiddenInAdmin?: boolean` on `ActionBarItem`.\n  Undefined = current behaviour (stay visible in admin mode).\n- No changes to `adminOnly` semantics; the two flags stack cleanly.",
          "is_bot": false,
          "headline": "feat(actionbar): hiddenInAdmin flag on ActionBarItem (v0.10.3)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T13:11:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ed21b7dbcf814a1a9313b03c524254a023644c03",
          "body": "…1.0)\"\n\nThis reverts commit 806e63f936abbc0ba9d14e72e18119639bc28180.",
          "is_bot": false,
          "headline": "Revert \"breaking(actionbar): admin mode = exclusive replacement (v0.1…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T13:05:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "806e63f936abbc0ba9d14e72e18119639bc28180",
          "body": "Ben's usage of adminOnly landed on the shape where the admin\nbuttons are conceptually a DIFFERENT toolset (Manage Share,\nActivity, Version History) — not just extra buttons layered on top\nof the normal Comment / Download / Share. 0.10.x's additive\nsemantics made both sets show at once when admin mod\n[…]\n normal ones)\n- OR accept the new mode-switch UX (in practice, this is what most\n  surfaces want)\n\n## Bumped\n\n0.10.2 → 0.11.0 (minor; semantic behaviour flip even though the\ntype surface is unchanged)",
          "is_bot": false,
          "headline": "breaking(actionbar): admin mode = exclusive replacement (v0.11.0)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T13:03:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "56ec65b913a5e7d57161dca0a55626b14a7056ad",
          "body": "….10.2)\n\nTwo follow-ups after Ben's review of 0.10.1's borderless-sliders\nattempt.\n\n## Shield glyph restored\n\n0.10.1 swapped the shield for a sliders icon in the name of\nsemantic match. Ben preferred the shield's visual weight, only\ndisliked the outer ring — which we already dropped in 0.10.1. So:\ns\n[…]\nmount); can add an exit\n  transition later if the asymmetry bites\n\nInjects one additional keyframe (`ck-actionbar-admin-enter`) into\nthe existing pulse-keyframe stylesheet at module load — idempotent.",
          "is_bot": false,
          "headline": "fix(actionbar): shield glyph back + spring motion on admin toggle (v0…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T12:34:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c0c9bb529f743363a6ee2071dd523a21128281fb",
          "body": "Ben's design review of v0.10.0: the bordered circle around the\nshield glyph was heavier than the surrounding grip + item icons and\nread as inconsistent. Same button, three changes:\n\n- Drop the border + circle background — transparent bg, no border,\n  same shape as the drag grip and the item icons ar\n[…]\ncontrols\" instead of \"security/protected\"\n  — better semantic match for admin mode's actual behaviour\n\nNo API changes; still auto-appears when any adminOnly item exists,\nstill persists per storageKey.",
          "is_bot": false,
          "headline": "fix(actionbar): admin toggle borderless + sliders icon (v0.10.1)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T12:08:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7885424c1d6a47b64b51c23397ebe801a80455f7",
          "body": "…10.0)\n\nCross-viewer pattern for elevated-privilege actions. Reusable across\nthe block_doc viewer, PDF viewer, future document surfaces.\n\n## New — ActionBarItem.adminOnly\n\n```ts\nitems.push({\n  key: 'block-doc-history',\n  label: 'History',\n  icon: <HistoryIcon />,\n  onClick: () => navigate(...),\n  hi\n[…]\n.0 (minor; additive — no breaking changes to existing\n  ActionBarItem shapes)\n- Existing consumers work unchanged; adminOnly defaults to\n  undefined which is treated as \"regular item, always visible\".",
          "is_bot": false,
          "headline": "feat(actionbar): admin-only items + auto-appearing shield toggle (v0.…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-09T11:57:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b28febc3dc5a65043a13bedec6590ab192bd19ef",
          "body": "`npm install -g npm@latest` on the publish workflow started shipping\na broken libnpmpublish that errors with `Cannot find module\n'sigstore'` under --provenance. The v0.9.0 tag failed to publish\nbecause of this regression.\n\nPin to 11.5.0 — the minimum version that supports OIDC Trusted\nPublishing, per the surrounding comment — until upstream fixes the\nsigstore bundling.",
          "is_bot": false,
          "headline": "fix(ci): pin publish workflow to npm@11.5.0",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-08T22:30:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b6ba9c1612a1c1fd66152ec87205eaf3d33244b",
          "body": "Ships @cosxai/ui@0.9.0 · two new primitives for the ActionBar mode-\nswap pattern that product-mesh's M4.5 block_doc viewer needs.\n\n## ActionBarModeHandle\n\nFloating peek button positioned above the ActionBar's centred bottom\nplacement. Slim 44×6 accent pill at rest, sitting ~4px above the\nbar's top e\n[…]\nres .github/workflows/publish-ui.yml (npm\n  Trusted Publishing)\n- Consumer bump: product-meta needs `@cosxai/ui@^0.9.0` in\n  Phase G-I\n\nWorkdoc: docs/workdocs/2026-07-09_feature-actionbar-mode-handle/",
          "is_bot": false,
          "headline": "feat(actionbar): ActionBarModeHandle + useActionBarMode (M4.5 Phase F)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-08T22:28:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "55a649b028bc0fe2cc9b46d682c2a83cc7ba1080",
          "body": "…ne can't drop the loader\n\nRoot cause of the recently-discovered Windows font bug (see\nproduct-meta commit 83629e2): Vite 6 + @tailwindcss/vite 4.x\nsilently drops the fonts.css `@import url(https://fonts.googleapis.com/...)`\nbecause it sits 5 levels deep in the cascade (main.tsx →\nstyles/index.css →\n[…]\n.8.4\n- Build the SPA\n- `grep -c gstatic dist/assets/*.css` → 100+ hits (was 0 in 0.8.3)\n- Windows browser → H1 renders in Playfair Display (was Times\n  New Roman); mono in Geist Mono (was Courier New)",
          "is_bot": false,
          "headline": "release(ui): v0.8.4 · inline @font-face declarations so Vite 6 pipeli…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-08T11:57:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bf85b12349fdd6292176dbd2ceb3b3d37f402c6c",
          "body": "…ct labels\n\nTooltip's tooltipStyle hard-coded `whiteSpace: nowrap` +\n`textOverflow: ellipsis` — any content longer than the 320px\nmaxWidth got silently cut with an ellipsis. Fine for compact chrome\nlabels (\"Clean\", \"Ready · 6d ago\") where a taller tooltip would\nchurn the layout, but wrong for the mo\n[…]\nranch only matters when content\nwould need multiple lines. So no consumer breaks; those with\ntruncated hints simply start showing the full text.\n\nBump to 0.8.3 for the tag-driven npm publish workflow.",
          "is_bot": false,
          "headline": "fix(tooltip): wrap long content by default; opt-in truncate for compa…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-03T00:44:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "64f456490f2e6b08edd28e1288f7d7099c583490",
          "body": "Tooltip was hard-coded to hover above the trigger, so a star button\nnear the top of the topbar (star icon on a card at the visible edge\nof the doc list) painted the tooltip into the browser's chrome\ngutter where it was clipped and unreadable.\n\nAdd a third placement value `\"auto\"` that prefers top bu\n[…]\nom). Existing consumers that passed no\nplacement get the new smart behaviour by default — a strict\nimprovement.\n\nExplicit `\"top\"` / `\"bottom\"` still honoured verbatim for callers\nthat want to opt out.",
          "is_bot": false,
          "headline": "feat(tooltip): auto placement — flips to bottom near the viewport top",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-01T21:51:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "537308f6166b0ad9136782d4bdace4f792796373",
          "body": "Consumers with existing getByTestId('…') queries were breaking when\nthey swapped from native <input> to Checkbox / Radio because the\nprops didn't include data-testid. Add an explicit optional prop\nforwarded to the visual button so tests keep working without a\nper-file rewrite.",
          "is_bot": false,
          "headline": "feat(primitives): forward data-testid on Checkbox + Radio",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-01T20:38:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6d7adaadba1c731dc0cce05d46abd6c014cff01a",
          "body": "Native <input type=\"radio\"> renders as the OS accent (blue on\nmacOS) which doesn't respect --ck-accent and looks inconsistent\nalongside our custom-styled Checkbox. Radio mirrors Checkbox's\nAPI surface (checked / onChange / label / suffix / disabled) with\na circle border + centered dot for the checke\n[…]\n benefits\nfrom the browser's \"one selected at a time\" invariant + form-post\nsemantics if consumers want them. Consumers can still just wire\n`checked` + `onChange` per option and ignore the form angle.",
          "is_bot": false,
          "headline": "feat(primitives): add Radio primitive paired with Checkbox",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-01T20:32:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7cbbb29c818fc6e31856babfd88446535bd68777",
          "body": "The 0.7.0 chip added `padding: 0 4px` + `font-weight: 500`. Both\ngrew the overlay's glyph advance without matching change in the\nunderlying transparent textarea, so every character after\n`@Ben Zhang` drifted right by ~8px (screenshot showed the caret\nbetween \"s\" and \"d\" while the user was typing at the end). The\nchip now conveys \"highlighted\" via background + colour + a tight\nborder-radius only; layout stays character-for-character in sync.\n\nBump to 0.7.1.",
          "is_bot": false,
          "headline": "fix(MentionCombobox): drop chip padding + font-weight — caret alignment",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-01T11:25:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "464721f72579bb08bcd2301701a68769b4e50195",
          "body": "MentionCombobox grows an optional `mentionNames?: readonly string[]`\nprop. When provided and non-empty, the primitive draws a mirrored\noverlay behind the textarea that highlights each `@Name` (matched\nlongest-first, whitespace-bounded) as an accent-tinted chip while\nthe user is still composing. Text\n[…]\nded at meta 1ac452e and reverted at 63db991\nbecause the transparent-glyph textarea broke on rows=1).\n\nAlso exports `splitByMentionNames` — the same segmenter, useful\nfor previews outside the composer.",
          "is_bot": false,
          "headline": "release(ui): v0.7.0 — MentionCombobox mentionNames highlight overlay",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-07-01T11:18:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "73a1f8de2e8e558a9ce005d97203a48be2e36fa5",
          "body": "New primitive `<MentionCombobox<T>>` — controlled textarea + async\ndropdown for `@`-style mentions. Headless: consumer injects the data\nsource (`loadCandidates(query, signal)`), the row renderer\n(`renderItem`), the insertion contract (`getInsertionText`), and the\nReact key extractor. The primitive o\n[…]\nwed silently. Other errors call `onLoadError` or fall back\n  to `console.warn`.\n- No \"Searching…\" hint — the dropdown's presence is the signal.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.6.0 — MentionCombobox headless generic primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-30T21:04:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b42f2867d203711da64b4a2e5e90491eeb161952",
          "body": null,
          "is_bot": false,
          "headline": "Merge: Button loading prop (v0.5.0)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-26T16:22:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd6fb1fb44401db72b4d8dedd6e870e57f94d447",
          "body": "Phase-0 stub had only `variant`. Every consumer reinvented the\n\"button is doing async work\" state with `disabled={busy}` + a\nlabel swap. Hoist the pattern into the kit:\n\n- `loading?: boolean | undefined` — when true, renders a leading\n  CSS ring spinner (`.ck-btn-spinner`, inherits `currentColor` so\n[…]\ninteractive-elements rule in code-style.md;\nthe Phase-0 stub didn't, which blocked dialog autoFocus on submit\nbuttons.\n\nCHANGELOG entry + apps/docs/Loading section ship alongside.\n\nrelease(ui): v0.5.0",
          "is_bot": false,
          "headline": "feat(Button): add loading prop + ring spinner",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-26T16:22:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1b7c8f6033391c94b5c2eba97121bf6682b26367",
          "body": "The kit's `.ck-actionbar-label` already collapses below 768 px\n(physical keyboard isn't a given on phones, icons + tooltips do\nthe wayfinding), but the `hint` span — the kbd badge that\nadvertises \"C\" / \"S\" / etc. — had no class and stayed visible.\nResult: a phone bar read as [icon] C [icon] S, which\n[…]\ness without a hardware keyboard.\n\nTag the hint with `ck-actionbar-hint` and add it to the same\ndisplay: none rule. Single-line CSS + single class addition; no\nAPI change, no consumer migration needed.",
          "is_bot": false,
          "headline": "release(ui): v0.4.11 — hide ActionBar shortcut hint on phone",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-25T14:24:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4a9900e5b68dab9731ee45cbac7fc47b1c3313a3",
          "body": "… gutters\n\nConsumers (product-meta) reported the post-migration kit Modal\nread flatter than the local Dialog wrappers it replaced — the\ncard looked like another tier of card on the page instead of\na surface that took over. Three changes:\n\n- New `--ck-shadow-overlay` token, defaulted to a layered sha\n[…]\n24-px gutter — `20px 24px`\n  on header, `20px 24px 24px` on body, `16px 24px` on footer.\n  Earlier mix (16/20, 20, 14/20) read as three slots with\n  different paddings rather than one coherent column.",
          "is_bot": false,
          "headline": "release(ui): v0.4.10 — lift Modals with a new overlay shadow + larger…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-24T21:26:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6594dfc68130582d9531444e32830c4169de5d47",
          "body": "Consumer (product-meta) cross-referenced agent-dataroom's modals,\nwhich use `bg-black/60 backdrop-blur-sm` (4 px) — distinctly more\nseparation than our 2 px. Bump to 8 px so the page surface clearly\ndrops out of focus when a modal opens; the card itself sits above\nthe blurred layer so content stays crisp. Also stamp the\n`-webkit-backdrop-filter` so Safari < 18 / WebKit embeds get the\neffect instead of falling through.",
          "is_bot": false,
          "headline": "release(ui): v0.4.9 — deepen Modal backdrop blur to 8 px",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-24T21:09:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25ff4379702a10626b26228f073287c0c0619949",
          "body": "- chrome-editorial: add the `[data-ck-navitem]:not([data-active=\"true\"]):hover`\n  rule that sketch / ambient / riso / neobrutalism / terminal already\n  carry. Editorial was the only chrome where rail items had no hover\n  feedback — product-meta consumers noticed against the cards /\n  actionbar items\n[…]\nly set color + cursor, so the corner control looked like static\n  decoration. Same hover token as the rest of the kit's interactive\n  surfaces.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.8 — editorial NavItem hover + Modal close-button hover",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-24T15:41:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ab97d94f825444700be1aedcc127f612e00c47f8",
          "body": "…sures (#7)\n\nThe previous `useMemo` gate keyed on `[items.length, keys.join('|')]`\nsuppressed identity updates whenever length + keys were stable, which\nis exactly the case for a selection-mode toolbar whose buttons are\nfixed but whose `onClick`s close over changing state. Items registered\nonce on f\n[…]\ny (already documented); without it the\neffect loops on register → setState → re-render. The hook docstring\nspells the trade-off out explicitly.\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(actionbar): useActionBarItems no longer freezes stale onClick clo…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-24T10:47:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ac790f08a80b19cea0863fb3528d83108e7088d",
          "body": "release(ui): v0.4.6 — stronger ActionBar disclosure hover blend",
          "is_bot": false,
          "headline": "Merge pull request #6 from cosxai/fix/actionbar-hover-stronger-tint",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-20T14:32:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aed6e2e0d33a17b5f31a17bf0334e6fc7e441447",
          "body": "Bump child hover overlay from 18% → 30% accent. 18% composited\non top of the wrapper's --ck-accent-muted bg (8–14% accent per\nchrome) only reached ~30% effective saturation — at that low\nsaturation translucent orange / coral / blue all wash out to\nsalmon, so the hover lost its hue identity against t\n[…]\nolid\n--ck-accent text right beside it. 30% pushes past the dilution\ninflection so the workspace's actual brand colour is\nrecognisable on hover.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.6 — stronger ActionBar disclosure hover blend",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-20T14:31:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c5154414faab39f3def3a2f3721b107f1dd5154e",
          "body": "…ildren (#5)\n\nChild buttons inside an open ActionBarMenuGroup were stacking a gray\nhover background on top of the wrapper's --ck-accent-muted pill, which\nreads as a hue collision (most obvious on the editorial coral chrome).\nActionBarMenuGroup now stamps a ck-actionbar-group--open class on its\nwrapp\n[…]\nly. Closed groups + standalone buttons\nkeep the existing gray hover.\n\nNo API surface change — consumers bump the dep version and the fix\nlands.\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.5 — accent-tinted hover for ActionBar disclosure ch…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-20T14:19:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1e93e7019523533d74c87c30793c4e4d93c56ff",
          "body": "…ildren\n\nChild buttons inside an open ActionBarMenuGroup were stacking a gray\nhover background on top of the wrapper's --ck-accent-muted pill, which\nreads as a hue collision (most obvious on the editorial coral chrome).\nActionBarMenuGroup now stamps a ck-actionbar-group--open class on its\nwrapper wh\n[…]\nly. Closed groups + standalone buttons\nkeep the existing gray hover.\n\nNo API surface change — consumers bump the dep version and the fix\nlands.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.5 — accent-tinted hover for ActionBar disclosure ch…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-20T14:18:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "053c23d83246c127dff278805f45c1c835e0429e",
          "body": "Every chrome hardcoded its primary-button text colour to pair with\nits OWN signature accent (editorial near-black on coral, ambient\nwhite on saturated blue, sketch paper-white on sketch-blue, riso\nnear-black on pink, neobrutalism black on pastel). Consumer\noverride of --ck-accent-light-override flip\n[…]\n #fff or near-black) and stamp\n--ck-accent-fg alongside the override knob. Swiss chrome already\nuses --ck-bg-canvas for primary fg — untouched.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.4 — primary-button text reads from --ck-accent-fg",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-15T14:44:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b24441f3928328b68cab414d00162f86699e46bd",
          "body": "…iso / sketch chromes\n\nEditorial, riso, and sketch were setting --ck-accent (and sometimes\nhover/active) to literal hex values, silently bypassing the\ndocumented --ck-accent-light-override / --ck-accent-dark-override\nbrand-override knob. Consumer apps stamping their brand colour saw\nthe chrome stay \n[…]\nmer impact: product-meta's BrandProvider can drop its\naccent-family mirror workaround (a98324f) and go back to stamping\njust the override knob.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.4.3 — respect --ck-accent-*-override in editorial / r…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-15T14:24:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fb35187b0816e93570cdc6797ed10739d0e1a6a1",
          "body": "Input.tsx adds `minWidth: 0` to the `.ck-input-field` wrapper so\nthe field can shrink past its inner addon-wrap's nowrap suffix\ncontent when hosted inside a flex/grid parent. Long suffixes\n(e.g. `.meta.test.cosx.dev`) previously set a min-content floor\nthat pushed mobile viewports horizontally. prod\n[…]\n.ck-input-addon-wrap:has(:disabled)` dims the suffix / prefix\nalong with the input so a disabled `slug + .domain` stack reads\nas one disabled unit. `:has()` ships in all evergreen browsers\nsince 2023.",
          "is_bot": false,
          "headline": "release(ui): v0.4.2 — Input min-width + disabled visual",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-06T22:04:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f20c3bf7c14c5b537df95d0fe4978805e6fd8415",
          "body": "The 0.4.0 release left CJK in the editorial chrome dropping to\nsystem *sans-serif* CJK fallbacks (PingFang SC on macOS, SimSun on\nWindows) when Latin was already rendering in Playfair Display — a\nstyle mismatch the eye reads as broken even though the names are\nlegible. Adding Noto Serif SC fixes the\n[…]\ngh-contrast-serif pairing.\n\nPatch bump (0.4.0 → 0.4.1) since this is an additive visual tweak;\nno API changes, consumers don't need code edits.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(fonts): add Noto Serif SC to editorial-chrome serif stack (0.4.1)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-01T21:28:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c3d9a34f78a19ac3a06a41453c83b6bb2e2f917a",
          "body": "Two issues stacked on top of each other in consumer SPAs:\n\n1. fonts.css declared @font-face pointing to \"/fonts/Geist-Regular.otf\"\n   etc. — a path each consumer was expected to provision under their\n   own public/fonts/. When they didn't, Cloudflare's SPA fallback\n   returned index.html with Conten\n[…]\nb font loaded; every modern\n   OS already ships one of these.\n\nBump 0.3.4 → 0.4.0 (minor feat). publish-ui.yml fires on the\nui-v0.4.0 tag push.\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(fonts): Google Fonts CDN + CJK system-font fallback (0.4.0) (#4)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-06-01T20:40:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0dc6cc2b12f8d548488639efdf91cceb843d954b",
          "body": "…nWidths\n\nContinuing the 0.3.3 centering fix:\n\n1. Bar padding is now `0 6px` (symmetric) instead of `0 6px 0 0`.\n   Right-only padding made the grip sit flush against the left curve\n   while the rightmost element (now the status dot) had visible\n   breathing room — pushing the leading items a few pi\n[…]\n the right side when both spacers were\n   active in the centered-leading-items case. Aligning to 0 makes\n   the two spacers behave identically.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.3.4 — symmetric ActionBar padding + matched spacer mi…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-31T22:40:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dfd7023a62edd2b71bd74fa4cf60f42ea7d8dc08",
          "body": "…us dot\n\nA solo leading item (e.g. \"Theme · Light\" after the chrome control\nwas hidden) packed left next to the grip, leaving a visible gap\nbefore the right-anchored status dot — read as unbalanced.\n\nFix: insert a balancing leading flex spacer when the right side\nholds ONLY a status dot (no trailing\n[…]\ning items centre between grip and dot. When trailing\nitems are present, they retain right-anchor and leading goes back\nto natural left packing.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.3.3 — center solo leading items between grip and stat…",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-31T22:28:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6cd7b3609ab12ed28122f6aaa07d879a242c867",
          "body": "The empty-state guard was `items.length === 0` only, so an app whose\nsole consumer was `useActionBarStatusDot` (no `useActionBarItems`)\nwould see no bar at all. Now renders when EITHER items are registered\nOR statusDot is set.\n\nDiscovered while wiring product-meta's SyncStatusIndicator: when\nmounted alone in a test harness with no other items, the dot was\nregistered but the bar was hidden.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.3.2 — ActionBar renders for status-dot-only consumers",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-31T22:03:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9ff00ac054ad363f5f2a21c7d3e4c8c595728673",
          "body": "Adds `useActionBarStatusDot({color, title?, onClick?, pulse?} | null)`\nhook. Renders a bar-intrinsic coloured dot at the right edge of the\nfloating ActionBar, mirroring the left-edge drag grip — system chrome,\nnot registry content. Left grip says \"you can move this thing\"; right\nstatus dot says \"her\n[…]\nHANGELOG.md` — 0.3.1 entry\n- `packages/ui/package.json` — 0.3.0 → 0.3.1\n\nWorkspace typecheck green; additive change, no breaking modifications.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.3.1 — ActionBar status-dot slot",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-31T21:58:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d08de2f623991ae5672d0011dca4894f860401ee",
          "body": "Adds `slot?: 'leading' | 'trailing'` to ActionBarItem. Trailing items\nrender after a flex spacer so they pin to the right edge of the bar\nregardless of registration order — system status indicators (sync,\nidentity, connection) belong here, where page items registering\nlater can't shuffle them.\n\nDefa\n[…]\nckage.json` — 0.2.10 → 0.3.0\n- `docs/workdocs/2026-05-31_feature-actionbar-trailing-slot/` —\n  design rationale + slot-local grouping decisions\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.3.0 — ActionBar trailing slot (#3)",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-31T21:25:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be689f53fb3c95678d8093f4edf844eaf6f6db06",
          "body": "Anchors styled as buttons (<a class=\"ck-btn\">) inherited the\nbrowser's default underline because the base .ck-btn rule didn't\nexplicitly clear text-decoration. Tailwind preflight (meta) masked\nthis — its global anchor reset already stripped the underline — but\nconsumers without Tailwind (mesh's embedded auth pages) surfaced the\nbug on the verify-email success page's \"Continue to [Product] →\"\nCTA.\n\nOne-line fix in index.css; no API change.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.10 — text-decoration none on .ck-btn",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-30T20:12:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "33de8c59bd6ef54d19fce9d14d6e1907415b183f",
          "body": "Add `*, *::before, *::after { box-sizing: border-box }` to base.css.\n\nModern reset best practice (Eric Meyer 2014, Tailwind preflight,\nBootstrap, modern-normalize). Without it, `min-height: 100vh` +\npadding silently extends elements beyond the viewport because the\ndefault `content-box` model stacks \n[…]\nso no behaviour change there. Consumers without\npreflight (mesh's server-rendered auth pages) get it now.\n\nMinor bump — additive, non-breaking.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.9 — global box-sizing reset",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-30T15:46:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "58f87b75bcf26617a6aa25de9f1e14e2d69755ad",
          "body": "ActionBarButton wraps the icon prop in a .ck-actionbar-icon span:\nunicode glyphs (◐ ☀ ☾ ◇) rendered tiny next to the heavier 13 px\nbutton label, and there was no hook for callers to size the\nglyph individually — bare strings render as text nodes which CSS\ncan't target. The span lands at 16 px with a\n[…]\n-mesh's auth pages — both can remove\ntheir local .ck-actionbar-icon / .mesh-auth-actionbar__icon\noverrides once they're on v0.2.8.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.8 — ActionBarButton built-in icon wrapper",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-29T09:52:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ce45792331254eaca431ad534536c0d7ab31fbff",
          "body": "The capture-phase scroll listener fired for the popover's own\nlistbox scroll too, which closed it the moment you tried to\nbrowse a long option list. Now we filter scrolls whose target is\ninside the popover, and re-position the popover (instead of\nclosing) on outer / page scrolls.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.7 — Select popover stays open during scroll",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T16:37:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cc966fe6bda160e830dcf59c1702256847117384",
          "body": "- Popover now portaled to document.body + position:fixed against\n  trigger rect, so Card / Drawer / Dialog parents with\n  overflow:hidden can't clip it.\n- New searchable + searchPlaceholder props add an input at the\n  top of the popover with case-insensitive label filtering;\n  Arrow / Home / End / E\n[…]\nd list.\n- Closes on page scroll (matches Radix / Headless UI default;\n  avoids the popover drifting off the trigger while paging).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.6 — Select Portal + searchable",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T16:23:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f06d66911156070ee9919c2972dc727bed4e6d71",
          "body": "Custom listbox (not native <select>) so popup styling actually\nresponds to chrome overrides. Full keyboard a11y (Space/Enter\nopen, Arrows/Home/End navigate, Enter commit, Esc cancel, Tab\nadvance, A-Z/0-9 typeahead). Trigger mirrors .ck-input shape;\nterminal chrome override included as the canonical example for\nthe other chromes that want a divergent look.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.5 — Select primitive",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T16:11:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "845534ff33de241316c6caec6e06662be8ff6a37",
          "body": "Anchor default-color fix — bare <a> now uses --ck-accent across\nevery chrome instead of the browser's visited-purple. See\nCHANGELOG for the per-chrome before/after.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release(ui): v0.2.4",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T15:35:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "420d103e8cb3bfb3a6f2606dfe6d15189da24cc9",
          "body": "Without a base rule, browser default visited-link purple bleeds\nthrough every chrome — most visibly on terminal-chrome dark mode\n(indigo on near-black). Adds an anchor base in base.css using\n--ck-accent so every chrome's own accent flows through (terminal=\ngreen, editorial=coral, swiss=red, etc.). v\n[…]\nlanded in product-mesh's embedded\ncopy. Will roll out to consumers on the next @cosxai/ui release;\nno version bump in this commit.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ui): default anchor color to --ck-accent",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T15:33:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7d76736c951fdabd9ab899a72e8f81928d81bcfa",
          "body": "Configures two workers via env: `design` (prod) and `design-stag`\n(staging). Serves apps/docs/dist as static assets with SPA fallback\nso react-router-dom routes work on direct URL hits.\n\nFixes the CF Workers Build error where `npx wrangler deploy` was\nrunning at the workspace root and bailing out. Deploy command on\nCF should now be `cd apps/docs && npx wrangler deploy` (add\n`--env staging` for the staging project).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "build(docs): add wrangler.jsonc for cloudflare workers deploy",
          "author_name": "Ben Z.",
          "author_login": "benwk",
          "committed_at": "2026-05-28T14:01:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 0,
      "commits_last_year": 113,
      "latest_release_at": null,
      "latest_release_tag": null,
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 10,
      "days_since_latest_release": null,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 25,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@cosxai/ui",
          "exists": true,
          "license": "UNLICENSED",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@cosxai/ui",
          "is_deprecated": false,
          "latest_version": "0.20.0",
          "repository_url": "https://github.com/cosxai/product-design",
          "versions_count": 64,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 5123,
          "first_published_at": "2026-05-27T23:24:41.126000Z",
          "latest_published_at": "2026-07-28T18:55:49.910000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "@cosxai/blocks",
          "exists": true,
          "license": "UNLICENSED",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@cosxai/blocks",
          "is_deprecated": false,
          "latest_version": "0.12.1",
          "repository_url": "https://github.com/cosxai/product-design",
          "versions_count": 24,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 3890,
          "first_published_at": "2026-07-09T16:16:17.162000Z",
          "latest_published_at": "2026-07-21T11:11:24.622000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 8
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "apps/docs/tsconfig.json",
        "packages/blocks/tsconfig.json",
        "packages/ui/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 45781,
      "source_files_sampled": 139,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 3054
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "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"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 11,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 2,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "benwk",
          "commits": 113,
          "avatar_url": "https://avatars.githubusercontent.com/u/26141189?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": false,
      "ci_workflows": [
        "publish-blocks.yml",
        "publish-ui.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "pnpm-lock.yaml"
      ],
      "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": 6,
            "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": null,
            "reason": "no pull request found",
            "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/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 2,
            "reason": "8 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "c1ea6bdd4e2274ffe224a53b59a09b00572a7ac2",
        "ran_at": "2026-07-29T16:18:48Z",
        "aggregate_score": 3.6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-28T18:55:53Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-13T22:48:27Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/cosxai/product-design",
    "host": "github.com",
    "name": "product-design",
    "owner": "cosxai"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 42,
      "inputs": {
        "security": 36,
        "vitality": 37,
        "community": 26,
        "governance": 56,
        "engineering": 48
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "at_risk",
        "name": "Vitality",
        "value": 37,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "commits_last_year": 113,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 10
            },
            "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": "10/52 weeks with commits",
                "points": 6.9,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 10
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "113 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 113
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "critical",
            "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": 1,
            "inputs": {
              "releases_count": 0
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "no releases published",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases_published",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 26,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "critical",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "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": 66,
            "inputs": {
              "packages": [
                "@cosxai/ui",
                "@cosxai/blocks"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 9013
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "9,013 downloads/month across npm",
                "points": 52.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 9013,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "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": "moderate",
        "name": "Sustainability & Governance",
        "value": 56,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 16,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 11,
              "open_issues": 0,
              "closed_issues": 2,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "11/11 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 11,
                      "decided": 11
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 38,
            "inputs": {
              "followers": 3,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "cosxai",
              "public_repos": 1,
              "account_age_days": 358
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "3 followers of cosxai",
                "points": 4.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 3,
                      "login": "cosxai"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "1 public repos, account ~0 yr old",
                "points": 4.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 1
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@cosxai/ui",
                "@cosxai/blocks"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "2 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 2,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "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": "64 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 64
                    }
                  }
                ],
                "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": "at_risk",
        "name": "Engineering Quality",
        "value": 48,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 30,
            "inputs": {
              "has_ci": true,
              "has_tests": false,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 36,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 36,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 3.6
            },
            "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": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "8 existing vulnerabilities detected",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 1
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 62,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.96,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 3054
            },
            "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": "96 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 96,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 31,
            "inputs": {
              "has_nix": false,
              "has_tests": false,
              "lockfiles": [
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "apps/docs/tsconfig.json",
                "packages/blocks/tsconfig.json",
                "packages/ui/tsconfig.json"
              ],
              "agent_commit_share": 0.63,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "apps/docs/tsconfig.json, packages/blocks/tsconfig.json, packages/ui/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "apps/docs/tsconfig.json, packages/blocks/tsconfig.json, packages/ui/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": "63 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 63,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 45781,
              "source_files_sampled": 139,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/139 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 139,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-29T16:18:53.780730Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/cosxai/product-design.svg",
  "full_name": "cosxai/product-design",
  "license_state": "absent",
  "license_spdx": null
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasnpm.