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

linkdata / jaws

Javascript and WebSockets enabling dynamic webpages

GoMIT★ 6 estrellas⑂ 2 forksdesde jul 2022Ver en GitHub ↗

linkdata/jaws tiene un índice de salud de 67 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (90/100) y la más baja, Community & Adoption (29/100). Se actualizó por última vez hace 3 días. Una sola persona concentra la mayor parte del trabajo reciente.

67
global / 100
Moderado

Í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.

67
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

Johan LindhCuenta personal
10 seguidores44 repositorios públicosdesde ago 2012

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
Gogithub.com/linkdata/jawsv0.601.0-292hace 7 días

Métricas por categoría

Vitalidad

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

90Excelente · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 3 días
19.4/36Cadencia de commits — 28/52 semanas con commits
18/18Volumen de commits — 1209 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1209
human_commit_share1
days_since_last_push3
active_weeks_last_year28
Cómo se puntúa
27/27Publica versiones — 100 versiones publicadas
36/36Recencia de las versiones — última versión hace 34 días
27/27Cadencia de publicación — una versión cada ~14,5 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count100
latest_release_tagv0.600.0
releases_from_tagsno
days_since_latest_release34
mean_days_between_releases14,5
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?

29Crítico · 18% del índice global
Cómo se puntúa
11.3/60Estrellas — 6 estrellas
0/25Forks — 2 forks
0/15Observadores — 1 observadores
Datos de entrada utilizados
forks2
stars6
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
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_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

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.2/22.5Distribución de commits — el principal contribuyente firma el 99% de los commits
2.7/13.5Amplitud de contribuyentes — 2 contribuyentes
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Datos de entrada utilizados
bus_factor1
contributors_sampled2
top_contributor_share0,99
Cómo se puntúa
43.6/46.8Resolución de issues — 93% de issues cerradas
35.6/38.3Aceptación de PR — 150/161 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/12 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs150
open_issues4
closed_issues55
issue_closed_ratio0,932
closed_unmerged_prs11
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
7.5/25Alcance del propietario — 10 seguidores de linkdata
24/25Trayectoria — 44 repos públicos, cuenta de ~13 años
Datos de entrada utilizados
followers10
owner_typeUser
is_verified
owner_loginlinkdata
public_repos44
account_age_days5088
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en go
35/35Recencia de publicación — última publicación hace 7 días
20/20Historial de versiones — 292 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/linkdata/jaws
ecosystemsgo
any_deprecatedno
min_days_since_publish7

Calidad de Ingeniería

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

74Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 3 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — .golangci.yml
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 10 out of 10 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno

Documentación

60Moderado
Cómo se puntúa
30/30README
0/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
10/10Topics — 11 topics
10/10Wiki
Datos de entrada utilizados
topicsdynamic-web, dynamic-webpages, go, golang, websocket, websockets, echo-framework, react, ui, frontend, web
has_wiki
homepage
has_readme
has_docs_dirno
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?

88Excelente · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — sin datos
2.5/2.5CI-Tests — 10 out of 10 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/12 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
5/5Fuzzing — project is fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — sin datos
5/5Pinned-Dependencies — all dependencies are pinned
5/5SAST — SAST tool is run on all commits
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — sin datos
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate8,5
Excluidos de la puntuación (sin datos o no aplicable): branch_protection, packaging, signed_releases. Los pesos restantes se han renormalizado.
Cómo se puntúa
35/35Dependencias directas libres de avisos conocidos — ninguna dependencia directa tiene un aviso conocido
0/25Dependencias indirectas libres de avisos conocidos — el conjunto transitivo no es separable de las dependencias de desarrollo y prueba en este alcance
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories0
affected_packages0
assessed_packages6
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Dependencias indirectas libres de avisos conocidos, Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejaron 6 dependencias resueltas con OSV. Este repositorio no publica ningún paquete que el índice resuelva, por lo que se evaluó en su lugar el grafo de dependencias del repositorio. Ese grafo mezcla fijaciones de desarrollo y prueba con las dependencias distribuidas, de modo que solo se puntúan las dependencias declaradas en tiempo de ejecución; los hallazgos transitivos se informan como contexto y quedan excluidos de la puntuación. No se analiza la alcanzabilidad.

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.

66Moderado · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
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_files
agent_instruction_max_bytes
Cómo se puntúa
12.6/18Arranque con un solo comando — go.mod (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
11/11Configuración de lint / formato — .golangci.yml
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — lockfile
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 100
5/8Mantenimiento automatizado — automatización de dependencias configurada, no observada en los commits muestreados
10/10OpenSSF Scorecard: Pinned-Dependencies — all dependencies are pinned
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
54.1/55Tamaños de archivo manejables — 3/193 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes110.794
source_files_sampled193
oversized_source_files3
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — examples
Datos de entrada utilizados
example_dirsexamples
has_mcp_signalno
api_schema_files

Datos clave

6estrellas de GitHub
2contribuidores
1209commits en los últimos 12 meses
3días desde el último push
100versiones publicadas
1factor bus
4issues abiertas
Goecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

Más detalle

Historial de estrellas y forks 0 ★ / 2 ⇿
0Estrellas
2Forks
100Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

111222212022-082024-082026-07
Mayor 0Menor 84Parche 16

Cada punto abarca 4 días.

OpenSSF Scorecard 8.5 / 10
8.5agregado

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-27 14:07 UTC

10Binary-Artifactsno binaries found in the repo
n/dBranch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests10 out of 10 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/12 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
10Fuzzingproject is fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
10Pinned-Dependenciesall dependencies are pinned
10SASTSAST tool is run on all commits
10Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
10Vulnerabilities0 existing vulnerabilities detected
Dependencias directas 5
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/coder/websocketv1.8.15go.mod
Gogithub.com/linkdata/deadlockv0.5.5go.mod
Gogithub.com/linkdata/jqv0.2.0go.mod
Gogithub.com/linkdata/secureheadersv1.1.1go.mod
Gogithub.com/linkdata/staticservev1.1.8go.mod
Todas las dependencias 6

Conjunto completo de dependencias resueltas según el grafo de dependencias de GitHub: 5 paquetes directos y 1 indirectos (transitivos). El cierre transitivo es completo cuando el repositorio incluye un lockfile.

RegistroPaqueteVersiónRelación
Gogithub.com/coder/websocketv1.8.15directa
Gogithub.com/linkdata/deadlockv0.5.5directa
Gogithub.com/linkdata/jqv0.2.0directa
Gogithub.com/linkdata/secureheadersv1.1.1directa
Gogithub.com/linkdata/staticservev1.1.8directa
Gogithub.com/petermattis/goidv0.0.0-20260330135022-df67b199bc81indirecta
Avisos de dependencias 0

Este repositorio no publica ningún paquete que el índice resuelva, así que se evaluó su propio grafo de dependencias — 6 paquetes, que incluyen también fijaciones de desarrollo y prueba que nunca se distribuyen: 0 tienen avisos conocidos, de los cuales 0 son directas.

Ningún aviso conocido afecta a las dependencias evaluadas.

Un aviso significa que la versión registrada en el grafo de dependencias cae dentro del rango afectado de un aviso. No se analiza la alcanzabilidad, y el grafo incluye fijaciones de desarrollo y prueba: un hallazgo puede referirse al utillaje y no al software distribuido.

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "dynamic-web",
        "dynamic-webpages",
        "go",
        "golang",
        "websocket",
        "websockets",
        "echo-framework",
        "react",
        "ui",
        "frontend",
        "web"
      ],
      "is_fork": false,
      "size_kb": 4245,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 1283245,
        "CSS": 291,
        "JavaScript": 29022
      },
      "pushed_at": "2026-07-23T18:01:30Z",
      "created_at": "2022-07-25T11:04:31Z",
      "owner_type": "User",
      "updated_at": "2026-07-23T17:58:43Z",
      "description": "Javascript and WebSockets enabling dynamic webpages",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://linkdata.se/",
      "name": "Johan Lindh",
      "type": "User",
      "login": "linkdata",
      "company": null,
      "location": "Sweden",
      "followers": 10,
      "avatar_url": "https://avatars.githubusercontent.com/u/2185977?v=4",
      "created_at": "2012-08-20T22:03:58Z",
      "is_verified": null,
      "public_repos": 44,
      "account_age_days": 5088
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.600.0",
          "kind": "minor",
          "published_at": "2026-06-23T07:37:08Z"
        },
        {
          "tag": "v0.500.0",
          "kind": "minor",
          "published_at": "2026-06-01T08:16:34Z"
        },
        {
          "tag": "v0.400.0",
          "kind": "minor",
          "published_at": "2026-04-15T13:42:07Z"
        },
        {
          "tag": "v0.300.0",
          "kind": "minor",
          "published_at": "2026-04-01T10:54:21Z"
        },
        {
          "tag": "v0.205.0",
          "kind": "minor",
          "published_at": "2026-03-26T11:47:28Z"
        },
        {
          "tag": "v0.204.0",
          "kind": "minor",
          "published_at": "2026-03-25T13:34:47Z"
        },
        {
          "tag": "v0.203.0",
          "kind": "minor",
          "published_at": "2026-03-24T10:02:01Z"
        },
        {
          "tag": "v0.202.0",
          "kind": "minor",
          "published_at": "2026-03-18T14:28:14Z"
        },
        {
          "tag": "v0.201.0",
          "kind": "minor",
          "published_at": "2026-02-18T14:33:51Z"
        },
        {
          "tag": "v0.200.0",
          "kind": "minor",
          "published_at": "2026-02-12T10:20:35Z"
        },
        {
          "tag": "v0.118.0",
          "kind": "minor",
          "published_at": "2025-10-06T11:47:06Z"
        },
        {
          "tag": "v0.117.0",
          "kind": "minor",
          "published_at": "2025-08-26T08:15:12Z"
        },
        {
          "tag": "v0.116.0",
          "kind": "minor",
          "published_at": "2025-08-25T07:08:05Z"
        },
        {
          "tag": "v0.115.0",
          "kind": "minor",
          "published_at": "2025-08-20T08:03:20Z"
        },
        {
          "tag": "v0.114.0",
          "kind": "minor",
          "published_at": "2025-08-19T09:38:36Z"
        },
        {
          "tag": "v0.113.0",
          "kind": "minor",
          "published_at": "2025-08-18T11:19:37Z"
        },
        {
          "tag": "v0.112.0",
          "kind": "minor",
          "published_at": "2025-08-14T10:40:37Z"
        },
        {
          "tag": "v0.111.0",
          "kind": "minor",
          "published_at": "2025-08-06T09:56:22Z"
        },
        {
          "tag": "v0.110.0",
          "kind": "minor",
          "published_at": "2025-07-07T10:05:18Z"
        },
        {
          "tag": "v0.109.0",
          "kind": "minor",
          "published_at": "2025-03-12T10:16:19Z"
        },
        {
          "tag": "v0.108.0",
          "kind": "minor",
          "published_at": "2025-02-17T10:52:38Z"
        },
        {
          "tag": "v0.107.0",
          "kind": "minor",
          "published_at": "2025-02-17T10:24:43Z"
        },
        {
          "tag": "v0.106.5",
          "kind": "patch",
          "published_at": "2025-02-17T10:10:59Z"
        },
        {
          "tag": "v0.106.3",
          "kind": "patch",
          "published_at": "2025-02-14T10:58:37Z"
        },
        {
          "tag": "v0.106.2",
          "kind": "patch",
          "published_at": "2025-02-14T10:43:54Z"
        },
        {
          "tag": "v0.106.0",
          "kind": "minor",
          "published_at": "2025-01-31T11:19:22Z"
        },
        {
          "tag": "v0.105.0",
          "kind": "minor",
          "published_at": "2024-12-18T07:12:17Z"
        },
        {
          "tag": "v0.104.0",
          "kind": "minor",
          "published_at": "2024-12-17T13:17:20Z"
        },
        {
          "tag": "v0.103.0",
          "kind": "minor",
          "published_at": "2024-12-16T07:15:35Z"
        },
        {
          "tag": "v0.102.0",
          "kind": "minor",
          "published_at": "2024-12-13T12:48:42Z"
        },
        {
          "tag": "v0.101.0",
          "kind": "minor",
          "published_at": "2024-12-09T07:35:11Z"
        },
        {
          "tag": "v0.100.0",
          "kind": "minor",
          "published_at": "2024-12-06T10:29:01Z"
        },
        {
          "tag": "v0.99.1",
          "kind": "patch",
          "published_at": "2024-12-05T12:07:31Z"
        },
        {
          "tag": "v0.99.0",
          "kind": "minor",
          "published_at": "2024-12-03T09:52:11Z"
        },
        {
          "tag": "v0.98.0",
          "kind": "minor",
          "published_at": "2024-12-03T09:27:56Z"
        },
        {
          "tag": "v0.97.0",
          "kind": "minor",
          "published_at": "2024-12-03T06:46:48Z"
        },
        {
          "tag": "v0.96.0",
          "kind": "minor",
          "published_at": "2024-11-29T10:06:31Z"
        },
        {
          "tag": "v0.95.0",
          "kind": "minor",
          "published_at": "2024-11-29T09:31:45Z"
        },
        {
          "tag": "v0.94.0",
          "kind": "minor",
          "published_at": "2024-11-29T09:27:27Z"
        },
        {
          "tag": "v0.93.0",
          "kind": "minor",
          "published_at": "2024-11-25T08:00:49Z"
        },
        {
          "tag": "v0.92.0",
          "kind": "minor",
          "published_at": "2024-11-21T11:24:22Z"
        },
        {
          "tag": "v0.91.0",
          "kind": "minor",
          "published_at": "2024-11-21T09:43:03Z"
        },
        {
          "tag": "v0.90.0",
          "kind": "minor",
          "published_at": "2024-11-21T09:07:24Z"
        },
        {
          "tag": "v0.89.0",
          "kind": "minor",
          "published_at": "2024-11-21T08:44:59Z"
        },
        {
          "tag": "v0.88.0",
          "kind": "minor",
          "published_at": "2024-11-21T08:27:45Z"
        },
        {
          "tag": "v0.87.0",
          "kind": "minor",
          "published_at": "2024-11-20T13:05:05Z"
        },
        {
          "tag": "v0.86.0",
          "kind": "minor",
          "published_at": "2024-11-14T13:03:15Z"
        },
        {
          "tag": "v0.85.0",
          "kind": "minor",
          "published_at": "2024-11-14T12:52:42Z"
        },
        {
          "tag": "v0.84.0",
          "kind": "minor",
          "published_at": "2024-11-13T09:59:51Z"
        },
        {
          "tag": "v0.83.0",
          "kind": "minor",
          "published_at": "2024-11-11T10:51:01Z"
        },
        {
          "tag": "v0.82.0",
          "kind": "minor",
          "published_at": "2024-11-11T09:58:53Z"
        },
        {
          "tag": "v0.81.0",
          "kind": "minor",
          "published_at": "2024-11-08T12:39:48Z"
        },
        {
          "tag": "v0.80.0",
          "kind": "minor",
          "published_at": "2024-11-06T08:01:31Z"
        },
        {
          "tag": "v0.79.0",
          "kind": "minor",
          "published_at": "2024-09-24T12:02:42Z"
        },
        {
          "tag": "v0.78.2",
          "kind": "patch",
          "published_at": "2024-09-18T11:21:47Z"
        },
        {
          "tag": "v0.78.1",
          "kind": "patch",
          "published_at": "2024-09-18T11:14:51Z"
        },
        {
          "tag": "v0.78.0",
          "kind": "minor",
          "published_at": "2024-09-18T10:56:41Z"
        },
        {
          "tag": "v0.77.0",
          "kind": "minor",
          "published_at": "2024-08-21T07:38:26Z"
        },
        {
          "tag": "v0.76.0",
          "kind": "minor",
          "published_at": "2024-08-12T08:00:37Z"
        },
        {
          "tag": "v0.75.2",
          "kind": "patch",
          "published_at": "2024-06-28T09:47:32Z"
        },
        {
          "tag": "v0.75.1",
          "kind": "patch",
          "published_at": "2024-06-28T09:44:59Z"
        },
        {
          "tag": "v0.75.0",
          "kind": "minor",
          "published_at": "2024-06-28T09:39:08Z"
        },
        {
          "tag": "v0.74.1",
          "kind": "patch",
          "published_at": "2024-06-14T09:47:01Z"
        },
        {
          "tag": "v0.74.0",
          "kind": "minor",
          "published_at": "2024-06-14T09:40:05Z"
        },
        {
          "tag": "v0.73.0",
          "kind": "minor",
          "published_at": "2024-06-13T10:33:33Z"
        },
        {
          "tag": "v0.72.0",
          "kind": "minor",
          "published_at": "2024-06-13T07:41:39Z"
        },
        {
          "tag": "v0.71.0",
          "kind": "minor",
          "published_at": "2024-05-30T10:31:51Z"
        },
        {
          "tag": "v0.70.0",
          "kind": "minor",
          "published_at": "2024-05-30T07:24:39Z"
        },
        {
          "tag": "v0.69.0",
          "kind": "minor",
          "published_at": "2024-05-29T09:28:00Z"
        },
        {
          "tag": "v0.68.0",
          "kind": "minor",
          "published_at": "2024-05-28T06:07:45Z"
        },
        {
          "tag": "v0.67.0",
          "kind": "minor",
          "published_at": "2024-05-27T09:55:05Z"
        },
        {
          "tag": "v0.66.0",
          "kind": "minor",
          "published_at": "2024-05-24T11:01:35Z"
        },
        {
          "tag": "v0.65.0",
          "kind": "minor",
          "published_at": "2024-05-24T06:52:32Z"
        },
        {
          "tag": "v0.64.0",
          "kind": "minor",
          "published_at": "2024-05-24T06:28:15Z"
        },
        {
          "tag": "v0.63.2",
          "kind": "patch",
          "published_at": "2024-04-29T10:35:53Z"
        },
        {
          "tag": "v0.63.1",
          "kind": "patch",
          "published_at": "2024-04-29T10:07:42Z"
        },
        {
          "tag": "v0.63.0",
          "kind": "minor",
          "published_at": "2024-04-29T05:17:33Z"
        },
        {
          "tag": "v0.62.0",
          "kind": "minor",
          "published_at": "2024-04-26T12:17:02Z"
        },
        {
          "tag": "v0.61.0",
          "kind": "minor",
          "published_at": "2024-04-18T09:46:38Z"
        },
        {
          "tag": "v0.60.0",
          "kind": "minor",
          "published_at": "2024-04-10T08:18:27Z"
        },
        {
          "tag": "v0.59.0",
          "kind": "minor",
          "published_at": "2024-03-08T08:59:57Z"
        },
        {
          "tag": "v0.58.0",
          "kind": "minor",
          "published_at": "2024-03-07T11:59:05Z"
        },
        {
          "tag": "v0.57.0",
          "kind": "minor",
          "published_at": "2024-02-28T12:05:24Z"
        },
        {
          "tag": "v0.56.0",
          "kind": "minor",
          "published_at": "2024-02-26T11:47:52Z"
        },
        {
          "tag": "v0.55.0",
          "kind": "minor",
          "published_at": "2024-02-26T10:20:05Z"
        },
        {
          "tag": "v0.54.0",
          "kind": "minor",
          "published_at": "2024-02-21T12:29:48Z"
        },
        {
          "tag": "v0.53.1",
          "kind": "patch",
          "published_at": "2024-02-21T09:59:30Z"
        },
        {
          "tag": "v0.53.0",
          "kind": "minor",
          "published_at": "2024-02-19T12:41:15Z"
        },
        {
          "tag": "v0.52.0",
          "kind": "minor",
          "published_at": "2024-02-16T11:34:14Z"
        },
        {
          "tag": "v0.51.1",
          "kind": "patch",
          "published_at": "2024-02-16T08:06:29Z"
        },
        {
          "tag": "v0.51.0",
          "kind": "minor",
          "published_at": "2024-02-15T12:37:42Z"
        },
        {
          "tag": "v0.50.0",
          "kind": "minor",
          "published_at": "2024-02-14T11:57:05Z"
        },
        {
          "tag": "v0.49.0",
          "kind": "minor",
          "published_at": "2024-02-12T11:49:00Z"
        },
        {
          "tag": "v0.48.0",
          "kind": "minor",
          "published_at": "2024-02-12T08:45:13Z"
        },
        {
          "tag": "v0.47.0",
          "kind": "minor",
          "published_at": "2024-02-08T09:23:04Z"
        },
        {
          "tag": "v0.46.2",
          "kind": "patch",
          "published_at": "2024-02-02T06:57:29Z"
        },
        {
          "tag": "v0.46.1",
          "kind": "patch",
          "published_at": "2024-01-29T11:20:18Z"
        },
        {
          "tag": "v0.46.0",
          "kind": "minor",
          "published_at": "2024-01-29T10:08:58Z"
        },
        {
          "tag": "v0.45.1",
          "kind": "patch",
          "published_at": "2024-01-25T11:16:14Z"
        },
        {
          "tag": "v0.45.0",
          "kind": "minor",
          "published_at": "2024-01-25T10:42:49Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "a71480a083e0efa28f6bcb5db716d93699dca694",
          "body": "…et subscribes (#220)\n\nFixes #215. Session.Close now queues one Reload frame onto each associated Request's wsQueue (delivered when its WebSocket connects) and broadcasts a key-targeted what.Update purely as a wake-up for an already-running process loop, so a Request still in its pending window is r\n[…]\noad classification is tightened so only the internal nil-destination dirty-render tick is droppable; every addressed message, including tag- and key-targeted Updates, fails-fast an overloaded Request.",
          "is_bot": false,
          "headline": "fix: reload associated Requests on Session.Close before their WebSock…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-23T17:58:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1e0d9dbd86c8b09aa538aea01698ffac3f080014",
          "body": "…casts (#211)\n\n* fix: remove the Jaws.Replace broadcast method (#199)\n\nJaws.Replace broadcast a what.Replace frame that swapped each matching DOM\nnode for the supplied HTML but left the corresponding server-side Element\nregistered. The replacement HTML normally carried no JaWS id attribute, so\nafter\n[…]\nx malformed plural doc link in Jaws.Broadcast\n\nThe [Element]s doc link rendered literally because the trailing s made it\nan invalid doc-link target. Rephrase as \"matched [Element] values\" so it\nlinks.",
          "is_bot": false,
          "headline": "fix: close #199 — remove Jaws.Replace and reject Replace/Remove broad…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T20:44:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6fd13a23986c5b01d05376416b729d75e12c97c7",
          "body": "…d (#214)\n\nTagExpand's cycle detector identified active slice nodes by first-element\npointer alone, so aliased views into the same backing array with different\nlengths (or, for a named slice TagGetter that observes cap, different\ncapacities) were mistaken for cycles. The nested slice was skipped, si\n[…]\n.\n\nCompare pointer, length and capacity, which together fully identify a slice\nheader. A genuine self-referential slice re-enters with an identical header and\nis still detected as a cycle.\n\nFixes #203",
          "is_bot": false,
          "headline": "fix: identify slice nodes by pointer, length and capacity in TagExpan…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T19:57:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "852aa2bd5e472245dade5b836ffc2bbfd7d6e4c6",
          "body": "…205)\n\nAddTemplateLookuper validates only runtime comparability, but a value that\nis Go-comparable yet not equal to itself — a struct carrying a NaN — passes\nthat check while never matching in slices.Contains or the removal predicate.\nAdds of such a value are not deduplicated and RemoveTemplateLooku\n[…]\nout removing it.\n\nDocument on AddTemplateLookuper and RemoveTemplateLookuper that the lookuper\nmust compare equal to itself, and add TestTemplateLookuperNonReflexiveNotRemovable\nto guard the behavior.",
          "is_bot": false,
          "headline": "docs: document reflexive-equality requirement for TemplateLookuper (#…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T19:35:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "591331fc937587e1d27e2e508023062defca2fd8",
          "body": "The Date widget renders any bound year, but its input handler parses with\nthe fixed-width \"2006-01-02\" layout, so only years 1..9999 round-trip: a\nbound year of 10000 or more renders with five digits yet a browser edit of\nthat value fails to parse, returning an event error and leaving the bound\nvalue unchanged.\n\nDocument the supported year range on InputDate.JawsInput, the InputDate type,\nand NewDate, and add TestInputDate_YearRangeRoundTrip to guard the boundary.",
          "is_bot": false,
          "headline": "docs(ui): document Date widget four-digit-year round-trip limit (#204)",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T19:32:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d84b62247c068907e408442308cfeeca9ad1e37",
          "body": "html.EscapeString leaves a raw carriage return unescaped, so a multiline\nattribute value read back from the DOM had its CR turned into LF (browser\ninput-stream preprocessing rewrites raw CR and CRLF to LF before tokenization).\n\nAppendAttrValue now encodes each CR as the numeric character reference &\n[…]\nnts callers to AppendAttrValue.\n\nTests model getAttribute and HTMLTextAreaElement.value semantics with the\nstandard library html.UnescapeString, keeping the dependency surface stdlib-only.\n\nFixes #202",
          "is_bot": false,
          "headline": "fix: round-trip carriage returns in HTML attribute values (#202)",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T19:25:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "83c8556127bb7e966d930487da2d380cc15be478",
          "body": "An HTML range input carries an implicit browser domain of min=\"0\", max=\"100\", step=\"1\". Range emits none of those attributes, so a bound value outside that domain or off the step grid is silently clamped and rounded by the browser and echoed back through the setter, overwriting server state.\n\nDocume\n[…]\ning that callers must supply explicit min/max/step attributes as params when the defaults do not cover the bound value's domain, and add a test guarding that those params render verbatim.\n\nCloses #201",
          "is_bot": false,
          "headline": "docs(ui): document Range browser-default bounds (#201)",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T18:58:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5a29406020be7df65a9e783b6821cdd64f6c64b9",
          "body": "fix: reject the framework-owned \"id\" attribute in attribute helpers",
          "is_bot": false,
          "headline": "Merge pull request #210 from linkdata/fix/attr-helpers-reserved-id-198",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T17:51:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78c13ccef74ad1c7845e37986f93c1791cbe9926",
          "body": "- Fix the flaky normal-attribute control test: use a non-running\n  jw.NewRequest(nil) whose process loop cannot drain wsQueue underneath\n  the assertion, instead of newTestRequest.\n- Wrap only the rejected call in the debug-panic recovery so the\n  error-identity and queue assertions also run under -race.\n- Add a node-backed jaws.js behavioral test covering case-insensitive\n  SAttr/RAttr rejection and that jawsMessage keeps processing later\n  orders in the same frame after the guard throws.",
          "is_bot": false,
          "headline": "test: address review of the id-attribute rejection tests",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T17:48:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7d6a874d522cbf14821857811298d1488d7cf1a",
          "body": "Element.SetAttr/RemoveAttr and Jaws.SetAttr/RemoveAttr accepted any\nattribute name, including \"id\". A managed DOM node is addressable only by\nits JaWS Jid, and every wire command resolves its target via\ndocument.getElementById, so setting or removing \"id\" stranded the\nserver-side Element with an unr\n[…]\nthe\nnew ErrReservedAttribute sentinel via reportMisuse and sending nothing,\nmirroring how Jaws.Insert guards a negative child index. Add a client-side\nguard in jaws.js as defense in depth.\n\nFixes #198",
          "is_bot": false,
          "headline": "fix: reject the framework-owned \"id\" attribute in attribute helpers",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T17:35:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "56367742e95ccf0ef78695ccf7eae60b8d7d9cc7",
          "body": "…flow-197\n\nfix: gate full tag rendering behind the debug/race build tags (#197)",
          "is_bot": false,
          "headline": "Merge pull request #209 from linkdata/fix/tagstring-cyclic-stack-over…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T17:22:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16ce510fadc0551070004c1d179f03da6dc2c2c7",
          "body": "TagString formatted tags with fmt's %#v, and Message.String / Element.String\nformatted their tag Dest / tag list with %v. Handing an arbitrary tag to fmt is\nunsafe: fmt has no cycle or size bound, so a self-referential or oversized tag\noverflows the stack or exhausts memory. This is not confined to \n[…]\nevelopment and -race builds keep full detail.\n\nBecause -race and -tags debug select the debug renderer, CI also runs the suite\nwithout them so the crash-safe release path is exercised too.\n\nFixes #197",
          "is_bot": false,
          "headline": "fix: gate full tag rendering behind the debug/race build tags",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-22T17:17:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "11a6eea21362bd9e02fc03f18203d8e90ec5ab11",
          "body": "fix: don't render nil JsVar Ptr through value-receiver callbacks (#196)",
          "is_bot": false,
          "headline": "Merge pull request #208 from linkdata/fix/jsvar-nil-ptr-render-lock-196",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T20:27:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7dd5e7a1255c251eda0a8dc32022251f2307a25",
          "body": "Rendering a JsVar bound to a nil pointer passed the typed-nil Ptr to\nElement.ApplyGetter, which saw a non-nil interface and invoked a\nvalue-receiver tag.TagGetter (or InitHandler) through the nil pointer,\npanicking. Because the write lock was released with a bare Unlock rather\nthan a deferred one, t\n[…]\n Ptr is nil. A nil Ptr now renders with no initial\ndata and no bound-value tag, as NewJsVar documents, and a panic from a\nsupported callback or from marshaling can no longer leak the lock.\n\nFixes #196",
          "is_bot": false,
          "headline": "fix: don't render nil JsVar Ptr through value-receiver callbacks",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T20:21:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7ac9bbf66378e4fc408477e236c2b445b7d6fb81",
          "body": "refactor: consolidate Request lifecycle flags into an atomic int32 state",
          "is_bot": false,
          "headline": "Merge pull request #207 from linkdata/fix/request-lifecycle-state",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T20:16:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0354fdcd9c50d7e3e017d0b7d5b6c4229c8addc",
          "body": "The strengthened Close-race test passed onPanic func(any){}, discarding any panic\nrecovered from TestServe's process/recycle goroutine; only the synchronous setup\npanic was asserted. A panic escaping recycle — notably finishLocked's terminal-state\nassertion after a terminal->running resurrection — w\n[…]\nection: forcing an\ninconsistent terminal state before recycle makes finishLocked's assertion escape and\nis now caught (per-element handler panics remain recovered inside process and are out\nof scope).",
          "is_bot": false,
          "headline": "test: capture TestServe onPanic in the Close-race test",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T20:12:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f550239e46e3d9acdd021c482fa474247879d89a",
          "body": "…se-race test\n\n- finishLocked doc: state that both rq.mu and jw.mu are required, and why. claim\n  runs its reqPending->reqClaimed CAS under rq.mu while startServe runs its\n  reqClaimed->reqRunning CAS under jw.mu (not rq.mu), so both locks are needed to\n  keep finishLocked's read-then-store atomic a\n[…]\ns a terminal->\n  running resurrection regression.\n\n- TestFinishLockedTerminalStatePanicsInDebug: hold jw.mu as well as rq.mu, matching\n  the documented finishLocked contract and production lock order.",
          "is_bot": false,
          "headline": "refactor: address review — accurate finish/release docs, stronger Clo…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T20:04:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "45fa1d2df0663f8aa03122fe8ef0c1df76f3aee1",
          "body": "Replace the three separate lifecycle flags on Request (registered bool,\nrunning atomic.Bool, claimed atomic.Bool) with a single reqState int32 held\nin Request.state, making the transitions explicit and race-safe:\n\n    reqUnclaimable -> (terminal; created after Jaws.Close)\n    reqPending -> reqClaime\n[…]\ncycle benchmarks), old = separate flags, new = int32 state:\n\n    B/op        geomean  -3.65%  (e.g. 401 -> 385, 416 -> 400)\n    sec/op      geomean  -2.51%\n    allocs/op   geomean   0.00%  (unchanged)",
          "is_bot": false,
          "headline": "refactor: consolidate Request lifecycle flags into an atomic int32 state",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T19:48:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e23d53f982535a17bf22adc559160dd00d9cefcb",
          "body": "Baseline benchmark (no behavior change) covering NewRequest -> UseRequest ->\nstartServe -> recycle, which the existing create/recycle and high-water benchmarks\ndo not exercise. Landed before the lifecycle-state consolidation so benchstat has\nbefore/after samples for the claim/start path.",
          "is_bot": false,
          "headline": "test: add BenchmarkRequestClaimStartFinish for the lifecycle CAS path",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T19:06:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "395e7ec544e4c21d9f2583d284d0c434134a6469",
          "body": "fix: never reuse Request identities, pool only buffers (#195)",
          "is_bot": false,
          "headline": "Merge pull request #206 from linkdata/fix/195-stable-request-identity",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T18:13:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e569de99011734d347376eeb462db59cd9a21fc1",
          "body": "…key guarantee\n\nThe Request godoc no longer claims all identity-targeted operations are never\nretargeted. It defines the never-reused identity as the *Request pointer (GC'd,\nnever handed out again, so a retained pointer never aliases another connection), and\nscopes the operational guarantee to desti\n[…]\nistered\nRequests: a Request created by NewRequest after Jaws.Close is unregistered and installs\nno tombstone, so two post-close calls could receive the same key — harmless, since\nneither is claimable.",
          "is_bot": false,
          "headline": "docs: scope exported Request identity to the pointer; qualify README …",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T18:05:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0580bf47a75459c3559be799ef4831240b32bdb0",
          "body": "…ing + destKey resolution\n\nThe previous wording claimed \"pointer-derived operations never reach a different\nconnection\", which is false: Request.Dirty dirties matching Elements on other live\nRequests by design, and an Alert/Redirect message queued before completion carries a\nkey.Key destination that\n[…]\niases another connection, and destKey returns zero once the Request has finished so\nit cannot hand back the finished destination — and explicitly note it is not a\nblanket pointer-derived-safety claim.",
          "is_bot": false,
          "headline": "docs: narrow destKey's post-completion guarantee to pointer non-alias…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:58:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0b338d5299b62a5920eb4ce17721cc29934209cb",
          "body": "A key VALUE (a copied key.Key, a queued wire.Message.Dest, or a browser /jaws/<key>\nURL) can outlive the *Request. While the finished Request stays reachable its key is\nheld reserved by a nil tombstone, so a stale destination matches nothing; but after\nthe Request is collected the tombstone is remov\n[…]\ns lifetime would make the absolute guarantee\nhold, but at the cost of an unbounded jw.requests leak (one dead entry per request\never created), so the cleanup-based, correctly-scoped guarantee is kept.",
          "is_bot": false,
          "headline": "docs: scope stale key-value matching to the tombstone lifetime",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:51:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "926e11668b777da5706e6ed791fc32d1b8ef6eea",
          "body": "…nt to reachability\n\nTestEarlyCallbackPreservesInitialRenderIdentity now captures the key before the early\ncallback and asserts it is unchanged afterward, instead of merely checking it is\nnonempty; the comment says the key stays stable and nonzero (the finished Request is\nunregistered), not \"valid\".\n[…]\nis collected the\ntombstone is cleaned up and the key becomes eligible for random reuse, by which point\nno stale destination referencing it can remain. A wantMessage test comment is\nlikewise qualified.",
          "is_bot": false,
          "headline": "docs: assert key stability in the #195 test; scope key non-reassignme…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:34:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f57d5b7d8779deb7ebbec7d52dc5e8831b4ba425",
          "body": "Documentation and test-name accuracy.\n\nQualify the early-teardown contract: clearing the collections forgets the\nalready-rendered elements and tags (a later GetElements finds nothing), but a\nsubsequent NewElement repopulates rq.elems and is again findable by Jid. Correct the\nlocking claim — the lock\n[…]\ninished, or detached from this Session\". The\nTestSession_ProducersSkipRecycled fixture comment now says the snapshot is taken\nunder sess.mu and processed after releasing it, not taken after unlocking.",
          "is_bot": false,
          "headline": "docs: qualify post-teardown lookup/locking; finish lifecycle terminology",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:25:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "df868e176f72b706436093311347d1f10ee645e3",
          "body": "…op rebind fixture\n\nDocumentation and test-fixture accuracy.\n\nEarly teardown clears the reusable collections (element list, tag map, dirt list,\nmessage queue) while leaving the individual Element fields and the Jid counter\nintact. Describe it as race-safe rather than non-destructive: releaseBuffersL\n[…]\ntached Request (its own nonzero key, session == nil), which is what the\nproducers' skip branch actually guards; the real snapshot-vs-finish race is covered\nby TestSessionCloseDoesNotReachLaterRequest.",
          "is_bot": false,
          "headline": "docs: describe early teardown as race-safe (not fully preserving); dr…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:18:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "986ca7a36993d0b7d85049754bb8738248c95f5b",
          "body": "…Request guarantee\n\nDocumentation-only, refining the lifecycle contract.\n\nThe Request type doc no longer equates the end of the initial HTTP render with the\nRequest finishing: the render handler returning normally leaves the Request pending\nuntil UseRequest claims it for the WebSocket. The Request f\n[…]\ns its buffers (retirement preserves them); the wantMessage and\nProducersSkip test comments no longer say recycle zeroes JawsKey (the key is\npreserved — only registered flips and destKey returns zero).",
          "is_bot": false,
          "headline": "docs: separate pointer ownership from completion; scope the finished-…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T17:09:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0f9204e57fc2e2994ad83981cb392faeb9c5a5c7",
          "body": "Documentation-only. The Request type doc no longer claims lifecycle completion\nalways releases buffers and leaves empty, useless collections: it distinguishes\ncompletion after WebSocket serving (which releases buffers to the pool) from\nretirement of an unclaimed Request (which preserves Elements and\n[…]\ne pool reusing a *Request: recycle now tombstones the key and only buffers are\npooled, so those tests exercise finished/unregistered requests and distinct later\nidentities rather than reused pointers.",
          "is_bot": false,
          "headline": "docs: correct Request lifecycle contract (completion vs retirement)",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T16:18:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1e4396620b591586d0ca97043b65d564664db180",
          "body": "Third review round.\n\nreleaseBuffersLocked clears only the live length of the reusable buffers, not their\nfull capacity. Every path that shrinks a buffer already zeroes the vacated entries\n(getSendMsgs and drainTailScript for wsQueue, makeUpdateList for todoDirt,\nslices.DeleteFunc for elems), so the \n[…]\n The README drops the removed render gate and, in the\nmaintainer checklist, distinguishes completion (releases buffers) from non-running\nretirement (which preserves them for the initial HTTP handler).",
          "is_bot": false,
          "headline": "fix: clear only live buffer length; add teardown-race regression tests",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T15:49:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4ab6eaf62832be0f4e9d7539aef4cd429b5da9c9",
          "body": "Second review round.\n\nRemove the initial-request-context render gate. The request context is not a\nreliable render-completion barrier: it is canceled when the client connection\ncloses (before the handler returns) and a detached/background context stays live\nafter it returns, so the gate could admit \n[…]\ncontext render still returns 204 and records\nErrJavascriptDisabled; TestReleaseBuffersLockedZeroesWsQueue drains to zero length\nbefore releasing to prove the backing array is cleared through capacity.",
          "is_bot": false,
          "headline": "fix: drop unreliable render gate; clear queue capacity; correct docs",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T15:28:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b9d93db4e3ad723ae2b26c7bc05d9ed275e78939",
          "body": "…stone\n\nFollow-up to the identity-stable change, addressing four review findings.\n\nTeardown no longer mutates render-visible state: releaseBuffersLocked stops\nclearing Element.ui/handlers and resetting lastJid, which raced an initial\nrenderer still inside JawsRender (those fields are read lock-free)\n[…]\nd-reuse model.\nTests decouple the initial-render request from the WebSocket request (distinct in\nproduction) and cover the render gate, the forced-key tombstone, and a live\nJawsRender racing teardown.",
          "is_bot": false,
          "headline": "fix: address review — render gate, non-destructive teardown, key tomb…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T15:01:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6c4a14fb6565e1f475a7a676bc9a55d557c6a7ef",
          "body": "Jaws.ServeHTTP could recycle a Request while its initial HTTP renderer\nstill held the pointer: an early or malformed GET /jaws/<key> claimed a\nstill-rendering Request, failed the WebSocket upgrade, and the deferred\nstopServe cleared the Request and returned it to a sync.Pool. Once reused\nfrom the po\n[…]\n remain pooled, so the change adds only one small\nRequest allocation per request: negligible for real pages and vanishing at\n1000 elements (BenchmarkRequestLifecyclePooling, impl=pooled).\n\nFixes #195.",
          "is_bot": false,
          "headline": "fix: never reuse Request identities, pool only buffers (#195)",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T13:58:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "634f8c9eab4c8bdfcd192b74bd5b0c51e12e45ee",
          "body": "fix: require \"type/\" prefix when matching MIME families in PreloadHTML",
          "is_bot": false,
          "headline": "Merge pull request #194 from linkdata/fix/182-preload-mime-family-slash",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:46:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fdc3958de09fd90a80bf04b4721bf55a0bc6f42d",
          "body": "Test_PreloadHTML computed its expected font preload link with\nstrings.HasPrefix(fontMime, \"font\"), a case-sensitive check without the\ntrailing slash. Since PreloadHTML now matches \"font/\" case-insensitively,\na platform returning \"FONT/woff2\" would emit as=\"font\" while the test\nexpected the bare preload form, failing spuriously. Mirror the production\nclassification so the expectation tracks the code on any MIME table.",
          "is_bot": false,
          "headline": "test: classify font family case-insensitively in expectation",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:43:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba0964dfa323966d29413b0d1651c34dba3deb58",
          "body": "assets.PreloadHTML classified MIME families with HasPrefix(mimetype,\n\"image\") and \"font\", so unrelated types such as \"imagery/*\" and\n\"fontastic/*\" were treated as images or fonts. That let non-image\nresources be emitted as favicons and non-font resources receive font\npreload metadata. Matching was a\n[…]\nike \"IMAGE/*\" or \"FONT/*\".\n\nMatch on the \"image/\" and \"font/\" prefixes case-insensitively so only\ngenuine image/* types qualify as favicons and only genuine font/* types\nreceive font preload handling.",
          "is_bot": false,
          "headline": "fix: require \"type/\" prefix when matching MIME families in PreloadHTML",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:37:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb2182a30c64c28bbf7124700329d4eca957b489",
          "body": "fix: truncate inbound Set/Call data at first tab in wire.Parse",
          "is_bot": false,
          "headline": "Merge pull request #193 from linkdata/fix/181-set-call-truncate-at-tab",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:33:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "43c932d965a3b36b5605dfc67a7a7c4019d42e76",
          "body": "wire.Parse documents that inbound Set and Call data is best-effort and\nends at the first tab, but it assigned the whole remainder after the Jid\nfield to Data, so a tab-separated suffix from an untrusted frame leaked\npast the documented boundary into Set/Call handling.\n\nCut the verbatim Set/Call fiel\n[…]\n so only the recoverable\nprefix survives, matching the parser contract. Non-Set/Call frames and\ntab-free Set/Call frames are unaffected, so existing Append/Parse round\ntrips are unchanged.\n\nFixes #181",
          "is_bot": false,
          "headline": "fix: truncate inbound Set/Call data at first tab in wire.Parse",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:27:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7cc53f304846228d7d455a6e9680bd5ab30110b9",
          "body": "fix: WsMsg.FillAlert panics on nil error (#180)",
          "is_bot": false,
          "headline": "Merge pull request #192 from linkdata/fix/180-fillalert-nil",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T08:23:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5366996a0bacc5a465cde9c7e81c2690c49c574f",
          "body": "FillAlert called err.Error() unconditionally, panicking on a nil error.\nTreat nil as an empty message so optional-error paths produce a\ndeterministic danger alert instead of crashing, and document the\nbehavior. Add a regression test covering nil alongside the existing\nescaping cases.\n\nFixes #180",
          "is_bot": false,
          "headline": "fix: handle nil error in WsMsg.FillAlert without panicking",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:52:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "577c7c6bf1cb66c2577598d435f50a84133f542a",
          "body": "fix: terminate the Request on non-finite floats and non-reflexive UI values",
          "is_bot": false,
          "headline": "Merge pull request #191 from linkdata/fix/179-terminate-on-nonfinite",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:48:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b07ca728682aa9d8da8e9c47746fee7f30be88f",
          "body": "…cile outputs\n\nA GetElementByJid == nil check is also satisfied by a created-then-deleted Element, so\nit did not prove the \"no child created\" guarantee. Because Jids are monotonic, both\nprevalidation tests now create a probe Element after the abort and assert it receives\nthe expected next Jid; a cre\n[…]\nile directly and asserts all four returned\noperation sets are empty, so UpdateContainer has nothing to queue — observing the\nreconciliation outputs rather than asserting the absence of ops indirectly.",
          "is_bot": false,
          "headline": "test: prove \"never created\" via monotonic-Jid probe and observe recon…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:43:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4cd18422522f3498a530236c4221caf8e3b023bb",
          "body": "…dation tests\n\nTestContainerValidatesWholeSliceBeforeRender proved no rendering or commit but not the\nstated \"no child created\" guarantee. Assert via the Request registry that the Jid a\nvalid prefix child would have taken is unused, so NewElement was never reached.\n\nAdd TestContainerUpdateValidatesW\n[…]\nor the pool. Assert the existing child is not removed, the new\nvalid child is not created (its would-be Jid is unused), and u.contents is unchanged —\nwhich precludes any queued Remove/Append/Order op.",
          "is_bot": false,
          "headline": "test: prove no-child-created and no-partial-reconciliation in prevali…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:34:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e6c0ea3d231979dc393ba0282ffe26652b67c76",
          "body": "…ger tests\n\n  - Add b.ResetTimer() after fixture creation in BenchmarkContainerValidateChildren so\n    the one-time benchChildren allocation is excluded; -benchtime=1x now reports 0 B/op\n    and 0 allocs instead of the setup cost.\n\n  - Documentation precision: Element.JawsUpdate now says \"nil UI int\n[…]\ninerValidatesWholeSliceBeforeRender: a usable child\n    preceding an unusable one is neither rendered nor committed, pinning that the\n    pre-lock scan validates the whole slice before any child work.",
          "is_bot": false,
          "headline": "fix: address review round 5 — benchmark honesty, doc precision, stron…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:22:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "efb4e92407ac8d13fd1d201cba91394bf57ee83e",
          "body": "…ed benchmark\n\n  - Clarify that only a nil interface is special. A typed nil (e.g. (*Widget)(nil)) is\n    comparable and equal to itself, so NewErrUnusableUI reports it usable and the\n    containers reconcile it normally; whether its methods tolerate a nil receiver is\n    the UI implementation's res\n[…]\nred-recover scan is ~63% faster than per-child validation,\n    but end-to-end container updates are statistically level with main: this is a\n    no-regression change, not a claimed end-to-end speedup.",
          "is_bot": false,
          "headline": "fix: address review round 4 — typed-nil UI semantics, nil docs, focus…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-21T07:00:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae55a3d4f1bb2783d674660c6cd9946e23618c88",
          "body": "… regression\n\n  - NewErrUnusableUI(nil) returned nil, so a nil UI passed container validation and\n    later panicked in JawsRender. Reject nil explicitly (clear \"nil is not usable\"\n    message), and make Element.JawsRender/JawsUpdate treat a nil UI as a no-op so a\n    direct NewElement(nil) yields a\n[…]\ntest to assert the logger callback ran,\n    so the check cannot pass vacuously. Update contract docs and the JAWS skill to\n    describe the container-level guard and NewElement's debug-only assertion.",
          "is_bot": false,
          "headline": "fix: address review round 3 — nil UI, error wording, and append-heavy…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T21:22:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "95f12619fadb61237ba2d714d2dca9845e513345",
          "body": "…pecific error\n\n  - ContainerHelper cancelled the Request while holding u.mu (reconcile validated\n    each child inside the lock). Request.Cancel runs the user logger synchronously,\n    which the locking contract forbids under a lock: a logger re-entering the\n    container deadlocks. Validate the wh\n[…]\n update the tracked JAWS skill's comparability\n    rules to require reflexivity and describe all-build cancellation.\n\n  - Handle the previously blank-assigned render error in the container regression.",
          "is_bot": false,
          "headline": "fix: address review round 2 — cancel outside the container lock, UI-s…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T20:35:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3266b02c42185f308a6ee5e104b3b011356b3b1b",
          "body": "…ch overflow\n\nFollow-up to review feedback on the non-finite/non-reflexive termination change:\n\n  - Container reconcile hashed a wanted child UI before reaching the NewElement\n    guard, so an interface-held slice/map (runtime-incomparable) panicked instead\n    of cancelling. Validate each child wit\n[…]\n/JawsContains contract docs and the Number/Range docs to require\n    reflexivity and describe all-build Request cancellation, replacing the stale\n    debug-only-panic and blank/default-render wording.",
          "is_bot": false,
          "headline": "fix: address review — guard container reconcile, keep bind guard, cat…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T20:01:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7d2e698f8f92dda362fee6d57468b25d01afb070",
          "body": "…values\n\nReplace the scattered NaN/±Inf handling with a uniform fail-fast policy. A\nnon-finite float64, or a UI value that is not equal to itself (issue #179),\nhas no valid rendering, wire, or map-key representation, so log the cause and\nterminate the offending Request instead of blanking, deduping,\n[…]\natForT keeps its\nfinite-out-of-range check (an infinity now falls out as ErrFloatOutOfRange) and\nno longer rejects finiteness itself. Removes the now-unused exported\nbind.ErrFloatNotFinite (breaking).",
          "is_bot": false,
          "headline": "fix: terminate the Request on non-finite floats and non-reflexive UI …",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T19:36:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5d38e35eb27c14857013b905dd4e788fb91779ba",
          "body": "fix(ui): render whole-page Handler dot as template data, not a tag",
          "is_bot": false,
          "headline": "Merge pull request #190 from linkdata/fix/178-page-dot-not-tag",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:54:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5c99c8195206bb620a1341db56b885203a9a3018",
          "body": "Render each request through a fresh per-request *pageTemplate so the UI stays\ncomparable as a map key regardless of the page dot. Ordinary html/template data\nsuch as a slice or map is not usable as a tag; a bare pageTemplate value\ncarrying it in its Dot any field is not comparable at runtime and tri\n[…]\niv).\n\nAdd a regression test rendering slice and map page dots (guarded with\ntag.NewErrNotComparable so it exercises the non-comparable path), and reword the\nhandler tests to describe current behavior.",
          "is_bot": false,
          "headline": "fix(ui): keep whole-page UI comparable for non-tag page dots",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:50:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cdae354ad179377f407efc79965fd3bfacc00d97",
          "body": "Add public-API regression tests for ui.Handler: a string dot and a struct\ndot render (the issue #178 repro), a missing template returns HTTP 500 with a\nlogged error, an execute error after output keeps the partial 200 body, a\npartial ui.Template still rejects a string dot, and a tag-valued page dot still\nrenders. Package coverage stays at 100% under -race.",
          "is_bot": false,
          "headline": "test(ui): cover Handler dot rendering and render-failure status",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:35:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7e758f3d285adfeb59723af65c254e4a14f57ae7",
          "body": "ui.Handler documents that each request renders the named template with dot\nexposed through With.Dot, with no tag-eligibility restriction. Whole-page\nrendering went through Template.render, which tag-expands the dot; a primitive\nvalue such as a string was rejected with ErrIllegalTagType and ServeHTTP\n[…]\nutput (for example a missing template) instead of a blank\n200. Once bytes are committed the partial body is left as-is, matching the\nbest-effort execution semantics documented on Template.\n\nFixes #178",
          "is_bot": false,
          "headline": "fix(ui): render whole-page Handler dot as template data, not a tag",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:35:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "56c7135b9638dd3ad854e3d084a449cd3a7e6506",
          "body": "…ation\n\nFix numeric input adapter reconciliation",
          "is_bot": false,
          "headline": "Merge pull request #189 from linkdata/fix/176-numeric-input-reconcili…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:15:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d695f4e931e392664ac6243dde7396094c396481",
          "body": "Add adapter subtests for negative int truncation and uint truncation, and\nparameterize the widget reconciliation test over both Number and Range.\n\nRefine the MakeSetterFloat64 doc: the converted value matches the underlying\nsetter's current value, not the setter itself.",
          "is_bot": false,
          "headline": "test(bind,ui): cover negative/uint truncation and range reconciliation",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T18:09:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad05b591f9a18fb5a4fb2e7908247f5c1a06442d",
          "body": null,
          "is_bot": false,
          "headline": "fix(bind): reconcile converted numeric inputs",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T17:30:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3d6d7d449a646d743a56798aac3c9e90b6aa812",
          "body": "fix(ui): apply initial select getter",
          "is_bot": false,
          "headline": "Merge pull request #188 from linkdata/fix/177-select-initial-getter",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T17:17:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b0aad94adc97f0fd8ca6c3fe395e86fe78cd4a1",
          "body": null,
          "is_bot": false,
          "headline": "test(ui): cover appended select initialization",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T16:56:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb1ce4425a1268ad4500d8e27ccebb9159d92f18",
          "body": null,
          "is_bot": false,
          "headline": "fix(ui): apply initial select getter",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T16:42:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18cdc998c407c9354d8c86054c367a037ad2b9d9",
          "body": "…ract\n\ndocs: define BoolArray removal contract",
          "is_bot": false,
          "headline": "Merge pull request #187 from linkdata/docs/175-boolarray-removal-cont…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:53:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "125c1344758fbab9ce4727b4b4c80e3967492d2c",
          "body": null,
          "is_bot": false,
          "headline": "docs: define BoolArray removal contract",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:49:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fab336bdc5f4228b62502be5f8842f914a8b209a",
          "body": "Enforce MaxPendingRequestsPerIP as a hard cap",
          "is_bot": false,
          "headline": "Merge pull request #186 from linkdata/fix/174-strict-pending-cap",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:46:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18b6b306ce500b4d059141c3f31f29e4245114df",
          "body": "When every pending request for an IP is fresh, retire the least recently\nwritten one instead of the oldest-created one, and guard the eviction\nloop against spinning under jw.mu if retirement ever declines a victim.",
          "is_bot": false,
          "headline": "fix: evict least recently written pending request",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:43:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "075cb258589d4d8587b24db9e72e3f8c7597efc2",
          "body": null,
          "is_bot": false,
          "headline": "fix: enforce pending request limit",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:24:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "31ce40bf34844760b102ae169f9c40d924cb29f8",
          "body": "fix: isolate response header values",
          "is_bot": false,
          "headline": "Merge pull request #185 from linkdata/fix/173-response-header-ownership",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:16:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad3effaed6ef1df0bede3e2aa2e3fd3bfb4468ea",
          "body": null,
          "is_bot": false,
          "headline": "refactor: set content security policy header",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:12:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3154b3716238134952c196091457da808a0a04f8",
          "body": null,
          "is_bot": false,
          "headline": "fix: isolate response header values",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T15:05:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "96931906ac39621bc2908726a1907c965f16e704",
          "body": "…er-lock\n\nAvoid calling response writers while holding the Jaws lock",
          "is_bot": false,
          "headline": "Merge pull request #184 from linkdata/fix/172-newsession-responsewrit…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T14:55:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5328b3555dd13a1dca88b8f425657570a49dc9d0",
          "body": null,
          "is_bot": false,
          "headline": "docs: clarify NewSession lock boundary",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T14:51:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6e26fb161e96fbd67ff61cbcf62486ac70fbca25",
          "body": null,
          "is_bot": false,
          "headline": "fix: avoid NewSession writer deadlock",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T14:46:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "384702b967a4ab9db95f603968432eaf552c8b12",
          "body": "Fix ConnectFn failure cleanup for non-reading peers",
          "is_bot": false,
          "headline": "Merge pull request #183 from linkdata/fix/171-connectfn-error-blocking",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T14:29:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b13b13863fd663962634b09c33c04260f5f3cbf",
          "body": null,
          "is_bot": false,
          "headline": "fix: close websocket on ConnectFn failure",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T14:22:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18d636e05532e9d5cc58e7040e660bdb729faeef",
          "body": "Deliver broadcasts issued by ConnectFn",
          "is_bot": false,
          "headline": "Merge pull request #170 from linkdata/fix/161-connectfn-broadcasts",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T13:18:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6249ed09870e9fcfe0e5aec653077fc02f52e9d8",
          "body": null,
          "is_bot": false,
          "headline": "refactor: simplify ConnectFn subscription flow",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T13:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0f2a56a87065fa3f322139934b2e9e5f08cb635",
          "body": "Signed-off-by: Johan Lindh <johan@linkdata.se>",
          "is_bot": false,
          "headline": "Fprint",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T13:04:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2c6f8ad445385215f27e7031240644e762f45e42",
          "body": null,
          "is_bot": false,
          "headline": "fix: deliver ConnectFn broadcasts",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T13:02:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d8826c5485f37d13f73a25398d287bacefad4be",
          "body": "fix: render debug tags outside request lock",
          "is_bot": false,
          "headline": "Merge pull request #169 from linkdata/fix/162-debug-render-lock",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T12:36:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "be4748d0d6bf64643159dbf4b4c835a9b35c6549",
          "body": null,
          "is_bot": false,
          "headline": "refactor: narrow debug tag snapshot helper",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T12:33:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0467fd005d670e3c3dba5dd1eccc155087df19b",
          "body": null,
          "is_bot": false,
          "headline": "fix: render debug tags outside request lock",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T12:19:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fbdda8dac4d01e75733f2cbbf4c02bfc99f23407",
          "body": "fix(setup): root empty-prefix static assets",
          "is_bot": false,
          "headline": "Merge pull request #168 from linkdata/fix/163-setup-empty-prefix-assets",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T11:38:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f4ac2574b14d6b41b44d516e9e9fd5a47e73c7b",
          "body": null,
          "is_bot": false,
          "headline": "docs(setup): define StaticServe name escaping",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T11:32:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99961acdb9a42fbebd69f17a09ac25a2d57c1ee1",
          "body": null,
          "is_bot": false,
          "headline": "fix(setup): root empty-prefix static assets",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T09:47:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e23534b732e58cb9805b838c625df5de1bcea50e",
          "body": "docs: define UI element multiplicity",
          "is_bot": false,
          "headline": "Merge pull request #167 from linkdata/docs/ui-element-multiplicity",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T09:19:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a69aaa5151da3b9f089264c9764a662fbd26593f",
          "body": null,
          "is_bot": false,
          "headline": "docs: address UI multiplicity review",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T09:16:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c5f0965c9bacddc52c74245abfa6dfa14ef1d540",
          "body": null,
          "is_bot": false,
          "headline": "docs: define UI element multiplicity",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T09:01:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bbc1657c36e8de488410b28a6066da1368d4d9ad",
          "body": "ui: add transactional JsVar client validation",
          "is_bot": false,
          "headline": "Merge pull request #166 from linkdata/feat/jsvar-client-check",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T08:21:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30e3f59bc9d9632d3c80fd0bb7ac3188a6ef2ff1",
          "body": "Replace binding-local size accounting with an optional validation callback that observes the complete tentative state and changed jq path. Add JSONSizeCheck, atomic rollback, shared-state coverage, documentation, and retained benchmarks.",
          "is_bot": false,
          "headline": "ui: add transactional JsVar client checks",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-20T08:08:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "89f0e5ea8487b54cd52f6ea39199b9cd7a8ed233",
          "body": "Signed-off-by: Johan Lindh <johan@linkdata.se>",
          "is_bot": false,
          "headline": "jq v0.2.0",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T23:09:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70886189bb437e2a647a60e7c19768ca1f9e7856",
          "body": "… test\n\nTestJawsJS_ConnectsAfterDeferredAssets simulated deferred assets with\nwindow.jawstreeInit and window.Treeview globals, but jaws.js connects on the\nDOMContentLoaded/load events and never inspects any adapter global, so the\nconnectedAfterAssets check only re-verified the snippet's own setup ordering.\nDrop the globals and that assertion, keeping the real checks: jaws connects\nexactly once, only after the ready event, idempotent across duplicate events.",
          "is_bot": false,
          "headline": "test(assets): drop tautological jawstree fixture from deferred-assets…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T21:14:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "717e5cd2fefe2749408c2b4ab574919f140ab21d",
          "body": "Move the jawstree treeview widget to the standalone\ngithub.com/linkdata/jawstree module and repository.\n\n- Remove the jawstree package and its embedded Quercus.js assets.\n- Drop the jsdom install step from CI: only jawstree loaded pages under\n  jsdom; the remaining node-driven JS tests (lib/assets) need only node.\n- Narrow the 386 test leg to lib/bind.\n- Repoint the jawstree cross-references in errors.go, lib/ui/jsvar.go,\n  and SECURITY.md to the external module path.",
          "is_bot": false,
          "headline": "Extract jawstree into its own module",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T21:00:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "68a46a06f7ebdd69a50151ccf05104714ecfa5f2",
          "body": "Bring jawstree to 100% statement coverage under -race by exercising the\nremaining untested branches:\n\n- applyClientAbsolute: invalid-index and disabled-node rejections.\n- applyClientDelta single-select: disabled-add reject, remove-clears-\n  selection, remove-unselected no-op, and invalid-remove-inde\n[…]\nx reject.\n- JawsInput: bitmap (\"b\") input, empty-payload, and malformed-JSON\n  reject/resync cases.\n- sparsePayloadLocked: multi-index wire form.\n- Node.HasNames: root vs non-root empty-path matching.",
          "is_bot": false,
          "headline": "test(jawstree): cover selection error and edge branches",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T20:28:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1eeac3165d904e8f73a44c0af0e89824e0f0862b",
          "body": "click: build Click.Name in linear time when parsing",
          "is_bot": false,
          "headline": "Merge pull request #157 from linkdata/fix/click-name-linear",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:38:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c858c1a4fccf4236ccd623941c54f1c2139986bf",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/click-name-linear",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:35:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64885208295c05de2324d33efa7b4bf94455f386",
          "body": "…ftover\n\nui: skip out-of-band-deleted leftovers in container reconcile",
          "is_bot": false,
          "headline": "Merge pull request #158 from linkdata/fix/container-remove-deleted-le…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:32:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "29866a87c2f9d90a5a330fdde8052d837aaa9fb8",
          "body": "parseClickData accumulated the click name with clk.Name += \" \" + field\nonce per whitespace-separated token past the fourth. Go strings are\nimmutable, so each += reallocated and copied the whole accumulated name,\nmaking the parse O(n^2) in the token count. The click frame is untrusted\nbrowser input b\n[…]\nhmarks (b.Loop, Apple M5 Max):\n  OneToken               0 allocs/op (unchanged fast path)\n  TwoTokens              1 alloc/op  (unchanged)\n  LongName, 8000 tokens  5380us/8003 allocs -> 43us/17 allocs",
          "is_bot": false,
          "headline": "click: build Click.Name in linear time when parsing",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:27:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "39c18f8dc0e0bc42e69da00fbb9c7448cb146f55",
          "body": "…deleted-leftover",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into fix/container-remove-…",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:20:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9a8c6bd527d4ef221bdacf21e7e581660d460e4",
          "body": null,
          "is_bot": false,
          "headline": "test(ui): strengthen deleted-leftover regression",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:18:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "22c7a4c36c3c6f48ba9440b91e1e376c44298433",
          "body": "request: tolerate a nil *Element in DeleteElement",
          "is_bot": false,
          "headline": "Merge pull request #156 from linkdata/fix/deleteelement-nil-guard",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:13:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2b0c5558896975f18bde33677dfd3efa39a95777",
          "body": "ContainerHelper.reconcile's reuse loop already discards Elements deleted\nout-of-band (a what.Delete broadcast or browser what.Remove) so the\ncontainer self-heals a still-wanted child. But the leftover sweep that\nbuilds toRemove appended every remaining pooled Element unconditionally,\nso a child that\n[…]\nc-API use;\nreconcile's own doc anticipates the out-of-band deletion.\n\nMirror the reuse loop's !Deleted() filter into the leftover sweep so a\ndeleted, already-unregistered Element never reaches Remove.",
          "is_bot": false,
          "headline": "ui: skip out-of-band-deleted leftovers in container reconcile",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:05:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "317f8beb443f142c5b97a2d1297f816ab1827648",
          "body": "deleteElementLocked read elem.Request before any nil check, so\nRequest.DeleteElement(nil) dereferenced a nil *Element and panicked.\nElement embeds *Request as its first field, so the field read faults on a\nnil receiver.\n\nEvery sibling *Element-accepting method already tolerates nil (Tag,\nTagExpanded\n[…]\nor\nan unknown Jid, so the natural rq.DeleteElement(rq.GetElementByJid(id))\ncomposed two documented behaviors into a panic. Guard elem != nil to match\nthe rest of the family and document the nil no-op.",
          "is_bot": false,
          "headline": "request: tolerate a nil *Element in DeleteElement",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T19:00:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dbc26c41a40bd33dc9611980579181136b287666",
          "body": "jawstree: cover fresh-client cascade selection regression",
          "is_bot": false,
          "headline": "Merge pull request #155 from linkdata/fix/134-jawstree-cascade-init",
          "author_name": "Johan Lindh",
          "author_login": "linkdata",
          "committed_at": "2026-07-19T18:06:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1209,
      "latest_release_at": "2026-06-23T07:37:08Z",
      "latest_release_tag": "v0.600.0",
      "releases_from_tags": false,
      "days_since_last_push": 3,
      "active_weeks_last_year": 28,
      "days_since_latest_release": 34,
      "mean_days_between_releases": 14.5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/linkdata/jaws",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/linkdata/jaws",
          "is_deprecated": false,
          "latest_version": "v0.601.0",
          "repository_url": "https://github.com/linkdata/jaws",
          "versions_count": 292,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-19T21:00:38Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 7
        }
      ]
    },
    "popularity": {
      "forks": 2,
      "stars": 6,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2022-08-22",
            "count": 1
          },
          {
            "date": "2026-07-18",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 2,
        "total_forks": 2
      },
      "star_history": null,
      "open_issues_and_prs": 4
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 110794,
      "source_files_sampled": 193,
      "oversized_source_files": 3,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 6,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/coder/websocket",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.8.15"
        },
        {
          "name": "github.com/linkdata/deadlock",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.5.5"
        },
        {
          "name": "github.com/linkdata/jq",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.2.0"
        },
        {
          "name": "github.com/linkdata/secureheaders",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.1"
        },
        {
          "name": "github.com/linkdata/staticserve",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.8"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/coder/websocket",
            "direct": true,
            "version": "v1.8.15",
            "ecosystem": "go"
          },
          {
            "name": "github.com/linkdata/deadlock",
            "direct": true,
            "version": "v0.5.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/linkdata/jq",
            "direct": true,
            "version": "v0.2.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/linkdata/secureheaders",
            "direct": true,
            "version": "v1.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/linkdata/staticserve",
            "direct": true,
            "version": "v1.1.8",
            "ecosystem": "go"
          },
          {
            "name": "github.com/petermattis/goid",
            "direct": false,
            "version": "v0.0.0-20260330135022-df67b199bc81",
            "ecosystem": "go"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 6,
        "direct_count": 5,
        "indirect_count": 1
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 150,
        "open_issues": 4,
        "closed_ratio": 0.932,
        "closed_issues": 55,
        "closed_unmerged_prs": 11
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "linkdata",
          "commits": 2021,
          "avatar_url": "https://avatars.githubusercontent.com/u/2185977?v=4"
        },
        {
          "type": "User",
          "login": "elri",
          "commits": 20,
          "avatar_url": "https://avatars.githubusercontent.com/u/14096948?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.99
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build.yml",
        "codeql.yml",
        "scorecard.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [
        ".golangci.yml"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "10 out of 10 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/12 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 10,
            "reason": "project is fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 10,
            "reason": "all dependencies are pinned",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 10,
            "reason": "SAST tool is run on all commits",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 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": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "a71480a083e0efa28f6bcb5db716d93699dca694",
        "ran_at": "2026-07-27T14:07:23Z",
        "aggregate_score": 8.5,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": true,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-27T04:24:08Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-23T17:58:39Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 216,
          "created_at": "2026-07-22T20:40:15Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 217,
          "created_at": "2026-07-22T20:40:16Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 218,
          "created_at": "2026-07-22T20:40:16Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 219,
          "created_at": "2026-07-22T20:40:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/linkdata/jaws",
    "host": "github.com",
    "name": "jaws",
    "owner": "linkdata"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 67,
      "inputs": {
        "security": 88,
        "vitality": 90,
        "community": 29,
        "governance": 56,
        "engineering": 74
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 90,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 1209,
              "human_commit_share": 1,
              "days_since_last_push": 3,
              "active_weeks_last_year": 28
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "28/52 weeks with commits",
                "points": 19.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 28
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1209 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1209
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v0.600.0",
              "releases_from_tags": false,
              "days_since_latest_release": 34,
              "mean_days_between_releases": 14.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 34 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 34
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~14.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 14.5
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 3,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 3 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 29,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 11,
            "inputs": {
              "forks": 2,
              "stars": 6,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "6 stars",
                "points": 11.3,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "2 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 56,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 12,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.99
            },
            "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 99% of commits",
                "points": 0.2,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "merged_prs": 150,
              "open_issues": 4,
              "closed_issues": 55,
              "issue_closed_ratio": 0.932,
              "closed_unmerged_prs": 11
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "93% of issues closed",
                "points": 43.6,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 93
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "150/161 decided PRs merged",
                "points": 35.6,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 150,
                      "decided": 161
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/12 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 52,
            "inputs": {
              "followers": 10,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "linkdata",
              "public_repos": 44,
              "account_age_days": 5088
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "10 followers of linkdata",
                "points": 7.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 10,
                      "login": "linkdata"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "44 public repos, account ~13 yr old",
                "points": 24,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 44
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/linkdata/jaws"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 7
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 7 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 7
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "292 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 292
                    }
                  }
                ],
                "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": "good",
        "name": "Engineering Quality",
        "value": 74,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": ".golangci.yml",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "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": "10 out of 10 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "topics": [
                "dynamic-web",
                "dynamic-webpages",
                "go",
                "golang",
                "websocket",
                "websockets",
                "echo-framework",
                "react",
                "ui",
                "frontend",
                "web"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "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": "11 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "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": "excellent",
        "name": "Security",
        "value": 88,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "excellent",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 85,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 8.5
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "10 out of 10 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/12 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is fuzzed",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is run on all commits",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 6 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 6
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 6,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 6,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "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": 3
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 66,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.96,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "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": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "go.mod (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "go.mod"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".golangci.yml",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "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": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 110794,
              "source_files_sampled": 193,
              "oversized_source_files": 3
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "3/193 source files over 60KB",
                "points": 54.1,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 193,
                      "oversized": 3
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? 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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T14:07:38.529562Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/l/linkdata/jaws.svg",
  "full_name": "linkdata/jaws",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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 agregadasGo.