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

ang-ee / angee-operator

GoSin licencia detectada★ 3 estrellas⑂ 1 forkdesde feb 2026Ver en GitHub ↗

ang-ee/angee-operator tiene un índice de salud de 55 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es AI Readiness (81/100) y la más baja, Community & Adoption (14/100). Se actualizó por última vez hace 5 días. Una sola persona concentra la mayor parte del trabajo reciente.

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

55
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

ANGEE (angee.ai)Organización
2 seguidores9 repositorios públicosdesde may 2026

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
Gogithub.com/ang-ee/angee-operatorv0.8.4-62hace 9 días

Métricas por categoría

Vitalidad

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

79Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 5 días
7.6/36Cadencia de commits — 11/52 semanas con commits
18/18Volumen de commits — 221 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year221
human_commit_share1
days_since_last_push5
active_weeks_last_year11
Cómo se puntúa
27/27Publica versiones — 58 versiones publicadas
36/36Recencia de las versiones — última versión hace 9 días
27/27Cadencia de publicación — una versión cada ~2,2 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count58
latest_release_tagv0.8.4
releases_from_tagsno
days_since_latest_release9
mean_days_between_releases2,2

Comunidad y Adopción

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

14Crítico · 18% del índice global
Cómo se puntúa
4.9/60Estrellas — 3 estrellas
0/25Forks — 1 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks1
stars3
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
0/22.5Licencia — no se detectó ningún archivo de licencia
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_licenseno
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

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

41En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/46.8Resolución de issues — 0% de issues cerradas
27.3/38.3Aceptación de PR — 25/35 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/13 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs25
open_issues4
closed_issues0
issue_closed_ratio0
closed_unmerged_prs10
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
3.4/25Alcance del propietario — 2 seguidores de ang-ee
7.6/25Trayectoria — 9 repos públicos, cuenta de ~0 años
Datos de entrada utilizados
followers2
owner_typeOrganization
is_verified
owner_loginang-ee
public_repos9
account_age_days55
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en go
35/35Recencia de publicación — última publicación hace 9 días
20/20Historial de versiones — 62 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/ang-ee/angee-operator
ecosystemsgo
any_deprecatedno
min_days_since_publish9

Calidad de Ingeniería

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

78Bueno · 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 — 3 out of 3 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
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://docs.angee.ai/
0/10Descripción del repositorio
0/10Topics
0/10Wiki
Datos de entrada utilizados
topics
has_wikino
homepagehttps://docs.angee.ai/
has_readme
has_docs_dir
has_descriptionno

Seguridad

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

60Moderado · 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 — 3 out of 3 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/13 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
5/5Fuzzing — project is fuzzed
0/2.5Licencia — license file not detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
5/5SAST — SAST tool is run on all commits
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
6.8/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0.8/7.5Vulnerabilities — 9 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate6
Excluidos de la puntuación (sin datos o no aplicable): branch_protection. Los pesos restantes se han renormalizado.

Preparación para IA

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

81Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md, GEMINI.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 90 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,9
agent_instruction_filesAGENTS.md, CLAUDE.md, GEMINI.md
agent_instruction_max_bytes7530
Cómo se puntúa
18/18Arranque con un solo comando — Makefile
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 — Dockerfile, lockfile
10/10Práctica demostrada con agentes — 17 de los últimos 100 commits con autoría o crédito de agente
5/8Mantenimiento automatizado — automatización de dependencias configurada, no observada en los commits muestreados
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0,17
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
54/55Tamaños de archivo manejables — 3/170 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes1.005.743
source_files_sampled170
oversized_source_files3
Cómo se puntúa
40/40Esquema de API (OpenAPI/GraphQL/proto) — docs/public/angee.graphql, internal/operator/schema.graphql
0/20Servidor MCP
0/40Ejemplos ejecutables
Datos de entrada utilizados
example_dirs
has_mcp_signalno
api_schema_filesdocs/public/angee.graphql, internal/operator/schema.graphql

Datos clave

3estrellas de GitHub
1contribuidores
221commits en los últimos 12 meses
5días desde el último push
58versiones 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
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Más detalle

OpenSSF Scorecard 6.0 / 10
6.0agregado

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-25 19:15 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-Tests3 out of 3 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/13 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
10Fuzzingproject is fuzzed
0Licenselicense file not detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
10SASTSAST tool is run on all commits
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
9Token-Permissionsdetected GitHub workflow tokens with excessive permissions
1Vulnerabilities9 existing vulnerabilities detected
Dependencias directas 14
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/fyltr/copier-gov0.0.0-20260615213950-5a55ba2e7116go.mod
Gogithub.com/gosimple/slugv1.15.0go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogolang.org/x/sysv0.45.0go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
Gogithub.com/99designs/gqlgenv0.17.90go.mod
Gogithub.com/bluekeyes/go-gitdiffv0.8.1go.mod
Gogithub.com/go-git/go-git/v5v5.19.1go.mod
Gogithub.com/go-playground/validator/v10v10.30.2go.mod
Gogithub.com/golang-jwt/jwt/v5v5.3.1go.mod
Gogithub.com/gorilla/websocketv1.5.0go.mod
Gogithub.com/invopop/jsonschemav0.14.0go.mod
Gogithub.com/vektah/gqlparser/v2v2.5.33go.mod
Gogolang.org/x/syncv0.20.0go.mod
Todas las dependencias no recopilado

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 10466,
      "has_wiki": false,
      "homepage": "https://docs.angee.ai/",
      "languages": {
        "Go": 1301085,
        "Jinja": 725,
        "Shell": 5971,
        "Makefile": 1315
      },
      "pushed_at": "2026-07-20T14:16:07Z",
      "created_at": "2026-02-27T20:29:22Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-16T11:30:42Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://angee.ai",
      "name": "ANGEE (angee.ai)",
      "type": "Organization",
      "login": "ang-ee",
      "company": null,
      "location": "United States of America",
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/289281192?v=4",
      "created_at": "2026-05-30T20:58:23Z",
      "is_verified": null,
      "public_repos": 9,
      "account_age_days": 55
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.8.4",
          "kind": "patch",
          "published_at": "2026-07-16T11:33:25Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2026-07-16T11:20:42Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2026-07-15T18:21:59Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-07-15T14:21:20Z"
        },
        {
          "tag": "v0.7.6",
          "kind": "patch",
          "published_at": "2026-07-01T19:39:22Z"
        },
        {
          "tag": "v0.7.5",
          "kind": "patch",
          "published_at": "2026-07-01T17:28:48Z"
        },
        {
          "tag": "v0.7.4",
          "kind": "patch",
          "published_at": "2026-07-01T12:18:17Z"
        },
        {
          "tag": "v0.7.3",
          "kind": "patch",
          "published_at": "2026-06-30T16:18:48Z"
        },
        {
          "tag": "v0.7.2",
          "kind": "patch",
          "published_at": "2026-06-26T18:34:22Z"
        },
        {
          "tag": "v0.7.1",
          "kind": "patch",
          "published_at": "2026-06-26T17:34:43Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-06-26T10:27:30Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-06-17T15:28:32Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-06-17T09:56:08Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-06-17T09:30:53Z"
        },
        {
          "tag": "v0.5.17",
          "kind": "patch",
          "published_at": "2026-06-17T07:50:08Z"
        },
        {
          "tag": "v0.5.16",
          "kind": "patch",
          "published_at": "2026-06-17T07:06:48Z"
        },
        {
          "tag": "v0.5.15",
          "kind": "patch",
          "published_at": "2026-06-15T21:56:48Z"
        },
        {
          "tag": "v0.5.14",
          "kind": "patch",
          "published_at": "2026-06-15T13:41:59Z"
        },
        {
          "tag": "v0.5.13",
          "kind": "patch",
          "published_at": "2026-06-14T22:24:13Z"
        },
        {
          "tag": "v0.5.12",
          "kind": "patch",
          "published_at": "2026-06-14T13:10:14Z"
        },
        {
          "tag": "v0.5.11",
          "kind": "patch",
          "published_at": "2026-06-14T09:33:14Z"
        },
        {
          "tag": "v0.5.10",
          "kind": "patch",
          "published_at": "2026-06-04T15:06:41Z"
        },
        {
          "tag": "v0.5.9",
          "kind": "patch",
          "published_at": "2026-06-03T02:45:03Z"
        },
        {
          "tag": "v0.5.8",
          "kind": "patch",
          "published_at": "2026-06-02T23:13:31Z"
        },
        {
          "tag": "v0.5.7",
          "kind": "patch",
          "published_at": "2026-06-02T20:33:06Z"
        },
        {
          "tag": "v0.5.6",
          "kind": "patch",
          "published_at": "2026-06-02T20:14:39Z"
        },
        {
          "tag": "v0.5.5",
          "kind": "patch",
          "published_at": "2026-05-22T01:28:03Z"
        },
        {
          "tag": "v0.5.4",
          "kind": "patch",
          "published_at": "2026-05-22T01:12:28Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-05-19T23:43:57Z"
        },
        {
          "tag": "v0.4.12",
          "kind": "patch",
          "published_at": "2026-05-15T13:12:03Z"
        },
        {
          "tag": "v0.4.11",
          "kind": "patch",
          "published_at": "2026-05-15T13:06:47Z"
        },
        {
          "tag": "v0.4.10",
          "kind": "patch",
          "published_at": "2026-05-11T02:20:03Z"
        },
        {
          "tag": "v0.4.9",
          "kind": "patch",
          "published_at": "2026-05-10T19:54:32Z"
        },
        {
          "tag": "v0.4.8",
          "kind": "patch",
          "published_at": "2026-05-10T19:05:42Z"
        },
        {
          "tag": "v0.4.7",
          "kind": "patch",
          "published_at": "2026-05-10T18:14:09Z"
        },
        {
          "tag": "v0.4.6",
          "kind": "patch",
          "published_at": "2026-05-10T11:31:48Z"
        },
        {
          "tag": "v0.4.5",
          "kind": "patch",
          "published_at": "2026-05-09T20:00:37Z"
        },
        {
          "tag": "v0.4.4",
          "kind": "patch",
          "published_at": "2026-05-09T16:47:31Z"
        },
        {
          "tag": "v0.4.3",
          "kind": "patch",
          "published_at": "2026-05-09T14:18:50Z"
        },
        {
          "tag": "v0.4.2",
          "kind": "patch",
          "published_at": "2026-05-08T18:24:23Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-05-08T18:16:27Z"
        },
        {
          "tag": "v0.3.3",
          "kind": "patch",
          "published_at": "2026-05-08T03:44:41Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-05-02T18:03:38Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-05-02T18:02:15Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-03-03T15:11:03Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-03-02T19:47:23Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-03-02T18:21:18Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-03-02T18:16:49Z"
        },
        {
          "tag": "v0.0.10",
          "kind": "patch",
          "published_at": "2026-02-28T02:24:28Z"
        },
        {
          "tag": "v0.0.9",
          "kind": "patch",
          "published_at": "2026-02-28T02:21:55Z"
        },
        {
          "tag": "v0.0.8",
          "kind": "patch",
          "published_at": "2026-02-28T02:02:29Z"
        },
        {
          "tag": "v0.0.7",
          "kind": "patch",
          "published_at": "2026-02-28T01:46:09Z"
        },
        {
          "tag": "v0.0.6",
          "kind": "patch",
          "published_at": "2026-02-28T01:35:38Z"
        },
        {
          "tag": "v0.0.5",
          "kind": "patch",
          "published_at": "2026-02-27T22:31:11Z"
        },
        {
          "tag": "v0.0.4",
          "kind": "patch",
          "published_at": "2026-02-27T22:26:13Z"
        },
        {
          "tag": "v0.0.3",
          "kind": "patch",
          "published_at": "2026-02-27T21:50:43Z"
        },
        {
          "tag": "v0.0.2",
          "kind": "patch",
          "published_at": "2026-02-27T21:32:13Z"
        },
        {
          "tag": "v0.0.1",
          "kind": "patch",
          "published_at": "2026-02-27T20:58:35Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "e74a6145416358d53e5bf491b7a127744a389e15",
          "body": "`angee init --dev` failed with `validate local source \"framework\": path \".\"\nescapes render target`. In the repo layout the dev stack's `framework` local\nsource resolves to the repo root — the render target itself, one level above\n`.angee`. preparedAbsolutePathOpener only diverted escaping paths (rel\n[…]\negression test for the opener covering the target-root and outside-target\ncases. Earlier renders never reached this staging step because the\n_preserve_symlinks refusal aborted first (fixed in v0.8.3).",
          "is_bot": false,
          "headline": "fix(service): open a local source located at the render target root",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-16T11:30:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d229156f6bc8a6902233c16953e30de7f15c52b3",
          "body": "…ation\n\n`angee init --dev` failed with `render layer \"stack\": _preserve_symlinks is\nnot supported by safe reconciliation`: PrepareReconcile rejected every template\ndeclaring `_preserve_symlinks: true`, which the dev/local stack templates need\nfor their `CLAUDE.md -> AGENTS.md` and `.angee/templates \n[…]\nl\nand the now-dead PreserveSymlinks config field, add an end-to-end test covering\nan in-tree and an escaping symlink plus an idempotent re-reconcile, and\nreconcile the two docs that claimed rejection.",
          "is_bot": false,
          "headline": "fix(copierx): preserve _preserve_symlinks templates in safe reconcili…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-16T11:17:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3f9610e0e04ed7c3852fa8038672eb2016a70ad5",
          "body": null,
          "is_bot": false,
          "headline": "temporary",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T18:51:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "221b9f2b508e397c12245e0ad639fbc3ecdb3736",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.8.2 (operator streams live job output)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T18:18:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a8157b4a1630b2f2ddde113e7da7b8229998bc88",
          "body": "feat(service): stream operator job output live to the terminal",
          "is_bot": false,
          "headline": "Merge pull request #41 from ang-ee/feat/job-output-streaming",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-07-15T18:15:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b0ac88128e676a9e470e5d574145327f249350c",
          "body": "The standalone operator now mirrors manual job (`angee job run`) output to\nits terminal as it runs, while still returning the captured output to the\ncaller. A mutex-serialised sink emits per-job status markers\n(`[job <name>] running|finished|failed`) and keeps them on their own lines so\nconcurrent j\n[…]\njobs now wrap their error with the captured\noutput, matching the local-runtime path. Streaming tests inject the sink\ndirectly via `Config.jobOutput` instead of swapping the process-global\n`os.Stdout`.",
          "is_bot": false,
          "headline": "feat(service): stream operator job output live to the terminal",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T18:09:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a83f00f2effa6f74e45551f99b27eb47f7406b5c",
          "body": "Template reconciliation for stacks, workspaces, chains, and services",
          "is_bot": false,
          "headline": "Merge pull request #40 from ang-ee/codex/template-render-reconciliation",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-07-15T14:16:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8d18475bc7b9697181eebb30647e041109ecdb6",
          "body": null,
          "is_bot": false,
          "headline": "fix: harden guarded template mutations",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T14:10:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c57ecd98f8b97bc19b56ca763b02c4c9662d39cd",
          "body": null,
          "is_bot": false,
          "headline": "fix(ci): update vulnerable Go dependencies",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T13:57:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "df93989208d59e8816ba561d74b5e90a0381ca64",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.8.1",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T13:49:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3ce313675e9e4df1007fe520ce238ac589d34d7",
          "body": null,
          "is_bot": false,
          "headline": "fix: make template reconciliation transactional",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T12:55:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "19f825d553c9e1d8de17b21571e0b0edc65f3779",
          "body": null,
          "is_bot": false,
          "headline": "fix(service): validate template update names",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T10:04:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d8e3ffd05c6b0bcc4925b60c6ed41032177bb785",
          "body": null,
          "is_bot": false,
          "headline": "fix: harden template reconciliation",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T10:01:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a89e6098d69c3bafb51aabe6e74a8b8a768ff4b1",
          "body": null,
          "is_bot": false,
          "headline": "docs: document template reconciliation workflows",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:52:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "19c2cf958f2a5bfed99199681b1c99d08d5bdcd5",
          "body": null,
          "is_bot": false,
          "headline": "feat(service): update services from templates",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:50:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d0c647ec1cbf5e28858d068b5d7ca774dcca74f",
          "body": null,
          "is_bot": false,
          "headline": "feat(workspace): reconcile templates on update",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:41:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "872d0ca7c612f6f367918e1f9c2da2d9fa2a5228",
          "body": null,
          "is_bot": false,
          "headline": "feat(stack): reconcile complete template output",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:34:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "840df1aa705f872097fe0dfbe98dc373bcdc3415",
          "body": null,
          "is_bot": false,
          "headline": "feat(copier): add stateful render reconciliation",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:29:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "193bd587751a4e34bc6d63a13d3174e25a6e3ab2",
          "body": null,
          "is_bot": false,
          "headline": "plan: implement template reconciliation",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:21:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "593f5c4c88e559a5b34bfe8513bf53026fc24c78",
          "body": null,
          "is_bot": false,
          "headline": "docs: include service template updates",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T09:17:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e47f0ee5ec95a5eccb96e99b54c690199346d654",
          "body": null,
          "is_bot": false,
          "headline": "docs: design reusable template reconciliation",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-15T08:26:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce3d822685ac03696c1a340370d4685a0e1fcddb",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.6 (stack init renders _angee.chain hosts)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T19:36:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af152ef70bd6b51728d80fdb75cf4d5811182439",
          "body": "feat(stack): resolve _angee.chain in StackInit",
          "is_bot": false,
          "headline": "Merge pull request #39 from ang-ee/feat/stack-chain-resolver",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-07-01T19:35:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb0e57b1f5e8a2367c083b6b1cfaa6c78173581f",
          "body": "Review of the initial chain-in-StackInit landing surfaced that it rendered the\nsame shared `_angee.chain` schema differently from the existing\nrenderWorkspaceChain, so a chain block that is correct on a workspace template\nwas silently wrong on a stack template. Converge the two:\n\n- Resolve chain-ent\n[…]\nputs / ResolvePathInputs errors with the\n  failing entry's identity.\n\nAdd stack_chain_test.go covering input forwarding, the unknown-ref error, the\n`stacks/<name>` ref form, and root-scoped rendering.",
          "is_bot": false,
          "headline": "fix(stack): align _angee.chain resolution with workspace chains",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T19:33:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "81d76627159c5f08ea4f0d18dfa92442f2527531",
          "body": "StackInit parsed a stack template's `_angee.chain` but never rendered it, so a\n`kind: stack` that chains a host (e.g. stacks/local → projects/web) produced only\nthe stack's own files. Render each chained template into the same target BEFORE\nthe stack overlay, so the stack overlays a real host:\n\n- re\n[…]\nnore (overlay), both answers files, overlay wins.\n\nFollow-up: chain-input rendering handles bare `{{ x }}`, not Jinja filters\n(`{{ x | replace(...) }}`); and a Go test with fixtures should cover this.",
          "is_bot": false,
          "headline": "feat(stack): resolve _angee.chain in StackInit",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T18:59:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1027e17e691f62dc5cbd997303f5ffe9cfcbd068",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.5 (stack init tolerates an unreachable operator)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T17:25:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f00c9d9c70d359d52f51ee863ecb8c6aace16b5",
          "body": "angee stack init (and the init --dev / init stack variants) now run\nin-process locally when ANGEE_OPERATOR_URL / --operator is set but the\noperator does not answer the probe, instead of failing with a raw\nconnection error. Init is a bootstrap command that only renders template\nfiles into a new root \n[…]\nck. Reachable operators and runtime commands\n(up, down, logs, ...) are unchanged.\n\nAdds RemoteClient.Ping and CLI initPlatform, with tests for both the\nunreachable-fallback and reachable-remote paths.",
          "is_bot": false,
          "headline": "fix(cli): fall back to local init when the operator is unreachable",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T17:25:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1c5f2167d91948ba71ce46d8662d48e637870bbc",
          "body": "…ctor)",
          "is_bot": false,
          "headline": "changelog: cut v0.7.4 (serviceEndpoint logStream + --log-backend sele…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T12:15:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d1f6a008786bed3b2018829e8f6117d1f407c96d",
          "body": "…s reconcile",
          "is_bot": false,
          "headline": "Merge chore/reconcile-proposals: logStream + --log-backend + proposal…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T12:15:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "63d7655433a66b07aba579f39d0dc5a5bd5b77ed",
          "body": "…le proposals\n\nExpose a `logStream` descriptor on the GraphQL `serviceEndpoint` query,\nreaching parity with the REST `GET /services/{name}/endpoint` `log_stream`\nfield: the resolver builds it from the request scheme/host (injected into\nthe resolver context) via a descriptor closure, so the field ret\n[…]\neir remaining scope with an Implementation status header, add\ndocs/proposals/ROADMAP.md indexing all open work, and refresh the concepts /\ntemplates guides (two stack layouts + project template kind).",
          "is_bot": false,
          "headline": "feat(operator): logStream on serviceEndpoint + --log-backend; reconci…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-07-01T12:14:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb8778573a07155305af8cfb4636fd16f35e03a6",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.3 (operator workspace file tools)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-30T16:15:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ade5ead0f88761c98abeae1a8a8a1ed143549de7",
          "body": "Add the proposal (read/edit files in a workspace source over the operator\nAPI, modeled on the secrets API) plus the finalized architecture decision:\nthe store-vs-object split, the capability + registry substrate, the\nno-secret-verbs discipline, and the prior-art rationale (Vault\nphysical.Backend, gocloud.dev, the Go stdlib optional-interface idiom).",
          "is_bot": false,
          "headline": "docs(proposals): operator file-tools proposal + finalized architecture",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-30T16:13:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c682f74ab34598c36e783675aea98280f7f6424c",
          "body": "…lient, CLI\n\ninternal/files: a raw-bytes object layer over a Versioned store (UTF-8 +\nsize caps, etag compare-and-set, containment mapping) that requires the\nVersioned capability at construction.\n\nservice.FileAPI (FileRead/FileWrite) on Platform resolves a stack source\nkey to its on-disk dir and ope\n[…]\nput ladder lives in a single place.\n\nTests: object layer, service, REST (bearer/roundtrip/traversal/etag-409),\ngql fake resolver, and a REST/GraphQL parity test. GraphQL SDL and\nresolvers regenerated.",
          "is_bot": false,
          "headline": "feat(operator): workspace file read/write API across REST, GraphQL, c…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-30T16:13:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "668699d18c82415380498f0625a72935e3056393",
          "body": "…gistry\n\nAdd internal/store: a minimal Store (Get/Set) carrying ZERO domain verbs,\nmodeled on Vault's physical.Backend, plus optional capability interfaces\n(Lister/Deleter/Versioned) discovered by type assertion, and a backend\nregistry (Register/Open).\n\nlocalfs backend: sha256 etag, compare-and-set \n[…]\ned, not built) a secrets-engine seam so secret-specific\nactions never leak onto Store. golangci: exclude gosec G703 for localfs\n(containment is enforced in resolve(); same class as the existing G304).",
          "is_bot": false,
          "headline": "feat(store): generic key/bytes store substrate with capabilities + re…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-30T16:13:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1983b18af7e5062a9b2cb5a81e5d216197be2bfb",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.2 (service build context no longer doubles .angee)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T18:31:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c52f201cfc55ce7c1dd557ae35ad5047aa5c7b94",
          "body": "The workspace-flow callout pointed at a stale absolute path\n(~/Work/fyltr/angee-django); replace both occurrences with a\n<your-angee-django-checkout> placeholder so no hardcoded pathname remains.",
          "is_bot": false,
          "headline": "docs(agents): drop hardcoded angee-django path from AGENTS.md",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T18:31:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bf406b0db6bbfafccf9161cd179b363ec8af1934",
          "body": "p.root is already the stack control root (ANGEE_ROOT, normally .angee, and\nalways .angee for a workspace inner-stack), so joining \".angee/services/<name>\"\ndouble-prepended .angee and landed the build context at\n.angee/.angee/services/<name>. Every other artifact (workspaces/, run/,\nsources/, volumes\n[…]\nngo) match.\n\nAdds TestServiceCreateControlRootNoDoubling (roots the stack at a real .angee\ndir to reproduce the production layout) plus a table-driven test for the\nbuild.context containment validator.",
          "is_bot": false,
          "headline": "fix(service): install dynamic service build contexts at <root>/services",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T18:31:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6984bb24d50565a49d8a37c1ad2c976ea6b519e2",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.1 (workspace create --sync + transactional create)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T17:31:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b009f6b5a3682516ba1ab2e7895ec585fe7d31f",
          "body": "… create\n\n`angee workspace create --sync` reconciles a git worktree left behind by an\nearlier create that failed after materializing it, instead of failing with\n`already exists and is not empty`:\n\n- A populated leftover worktree is removed (targeted `git worktree remove`,\n  refusing anything that is\n[…]\nL (workspaces_insert_input.sync /\nWorkspaceCreateInput.sync). Reviewed across three passes; tests pin the\nsibling-branch refusal, populated-vs-missing reclaim, non-worktree preservation,\nand rollback.",
          "is_bot": false,
          "headline": "feat(workspace): --sync reconciles a leftover worktree; transactional…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T17:31:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6f156dd13d5dcde7eacbbde2caeb3328ebed10f5",
          "body": "… broke release lint)",
          "is_bot": false,
          "headline": "test(graphql): use gqlparser.LoadQueryWithRules (deprecated LoadQuery…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T10:25:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1e8f1a27b6b27ab6808fe7e0a46db5210c40ba5e",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.7.0 (operator GraphQL reshaped to the Hasura dialect)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T10:20:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ef0828edf0008e6e53b39d77dc437b321ffcf074",
          "body": "… dialect",
          "is_bot": false,
          "headline": "Merge refactor/graphql-hasura: reshape operator GraphQL to the Hasura…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-26T10:20:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f11aec9cf97c884951ea12c8b23e86e6b5332f9",
          "body": "…d-key shape\n\nReshape the grouped-aggregation roots (services_groups / sources_groups) from\nthe interim { dimensions: [KeyValue!]!, aggregates } shape onto the frozen\nstrawberry-django-hasura \"Option A\" NDC contract, so one shared refine\nuseGroupBy/useFacets hook (useCustom) drives the operator and \n[…]\ngenerated gqlgen + SDL export; updated grouping contract/resolver tests\n(typed-key, having+order_by, granularity rejection, sources reducers, empty\ngroup_by); golangci-lint clean; go test -race green.",
          "is_bot": false,
          "headline": "feat(graphql)!: harmonize *_groups onto strawberry-django-hasura type…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-24T08:08:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b0bc392f089fbdedbfd20bf56340ffd46a219cb2",
          "body": "…es_groups)\n\nRe-align the operator's grouped aggregation to the NDC grouping shape (the\nemerging Hasura v3/DDN group-by standard, graphql-engine #10786) per the\nrefine-adoption plan, so the operator and the Django `<model>_groups` backend\nshare one forward-compatible grouped shape for a common useGr\n[…]\n in hasura_bind.go.\n- Tests: TestServicesGroupsByStatus + contract-test docs for services_groups\n  and the numeric sources_groups.\n\nDeferred toward full NDC: having predicates + order-by-on-aggregate.",
          "is_bot": false,
          "headline": "feat(graphql): NDC-shaped grouped aggregation (services_groups, sourc…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T12:27:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4622ed3fb734d8fe29d80920e2b681c2251a8249",
          "body": "Post-pivot cleanup and code-review fixes for the Hasura dialect.\n\nReview fixes:\n- getOne (`*_by_pk`) resolves null for a missing row instead of a hard error\n  (Hasura getOne contract): sources/workspaces/templates map NotFoundError -> nil;\n  secrets_by_pk treats the synthesized zero ref as not-found\n[…]\nk the superseded graphql-nestjs-query-shape proposal.\n\nNo `nestjs` strings remain in code/schema. Build/vet/gofmt/go test -race green;\nmake generate idempotent; @refinedev/hasura contract test passes.",
          "is_bot": false,
          "headline": "refactor(graphql): remove nestjs remnants + address Hasura review",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T12:17:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7505a1095e0d3b78440979b610087a96dc766292",
          "body": "Angee standardizes its consoles on Hasura, so the operator now emits the\nHasura GraphQL dialect, consumable by @refinedev/hasura with no custom\nmappers (namingConvention \"hasura-default\", idType \"String\"). Clean cut,\nno backward compatibility — supersedes the intermediate nestjs-query shape.\n\n- Tabl\n[…]\n_contract_test.go: validates the exact documents\n@refinedev/hasura generates against the executable schema (consumability\nguarantee). Deferred: bulk *Many mutations (createMany/updateMany/deleteMany).",
          "is_bot": false,
          "headline": "feat(graphql)!: reshape operator GraphQL to the Hasura dialect",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T11:59:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "450c2c5bc4b47caf6f489a6be479d104fe8d1e65",
          "body": "Address code-review feedback on the push-down/relations/aggregations work:\n\n- Move query.Validate to the top of the six Platform list methods so an\n  unknown filter/sort field returns 400 *before* the expensive slice build\n  (git stat/CurrentRef/AheadBehind per source, backend.Get per secret, the\n  \n[…]\n today; a future numeric remote pushdown needs a typed wire form).\n- Document that query.Aggregate expects callers to pre-validate groupBy field\n  names (the GraphQL groupBy enums do this implicitly).",
          "is_bot": false,
          "headline": "refactor(query): validate filter/sort before the list slice build",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T10:14:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ff8df331e940a7b3193ef54c6fe6ed06ab3e56cb",
          "body": "…Aggregate)\n\nAdd nestjs-query-style aggregate queries via the generic query.Aggregate:\ngroupBy + count, plus min/max/sum over numeric source fields. GitOpsSummary\nis retained as the curated fast-path.\n\n- internal/query.Aggregate: filter (reusing matchFilter) -> groupBy stringified\n  field values -> \n[…]\nfor source reducers.\n- Tests: query.Aggregate (groupBy/count/reducers/null-key) and a\n  serviceAggregate resolver test.\n\nAlso refresh the CHANGELOG for the push-down, relations, and aggregations work.",
          "is_bot": false,
          "headline": "feat(graphql): groupBy + count aggregations (serviceAggregate, source…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T10:04:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "430866b50ddeb3cd893f788be84ee32bf18258d3",
          "body": "…atus\n\nReshape nested list fields into nestjs-query relation connections\n(filter/sorting/paging), resolved by applying internal/query over the slice\nthe parent object already carries (no service.API change). Breaking for\nclients selecting these fields as bare lists.\n\n- GitOpsTopology.{sources,worksp\n[…]\n have no id.\n- StackStatus.* stays bare lists (map-backed + StackSnapshot-coupled).\n- Updated the gitOpsTopology/workspaceStatus test queries to the connection\n  shape; added a relation resolver test.",
          "is_bot": false,
          "headline": "feat(graphql): nestjs-query relations on GitOpsTopology + WorkspaceSt…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T10:00:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1d60e1c664b107fd60e4576beea06f210b25d197",
          "body": "Move the nestjs-query filter/sort/paging application from the GraphQL\nresolver layer into service.Platform so REST and GraphQL filter through one\npath. Breaking: REST list endpoints now return {nodes,totalCount} instead of\na bare array.\n\n- internal/query: add Validate (unknown filter/sort field -> e\n[…]\n: query.Validate + Aggregate, queryfields wire round-trip, a REST\nfilter round-trip (filtered {nodes,totalCount}; unknown field and malformed\nquery -> 400), and the updated REST list-shape assertions.",
          "is_bot": false,
          "headline": "feat(api): push filter/sort/paging into service.API + REST filter parity",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T09:52:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aa68431e93af7c0bf93ca6b684eebba499c4a81f",
          "body": "Reshape the operator GraphQL collection surface to the nestjs-query\nconvention so @refinedev/nestjs-query drives a console with no custom\nmappers. Breaking, clean cut — no backward compatibility.\n\n- All collections (services, jobs, sources, workspaces, templates,\n  secrets) take filter/sorting/pagin\n[…]\nql (cmd/gqlschema,\n  make graphql-schema, wired into generate + check-generated) for\n  frontend codegen; live introspection at /graphql is unchanged.\n\nSee docs/proposals/graphql-nestjs-query-shape.md.",
          "is_bot": false,
          "headline": "feat(graphql)!: reshape collections to nestjs-query shape + SDL export",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-23T09:08:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c480c95bd88c320d771d9fe2b1559814c9fc7b62",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.6.2 (compose project name derived from stack root)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T15:25:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0430082af1d33b8ec8569fcc5335da35ebb40d88",
          "body": "… from stack root",
          "is_bot": false,
          "headline": "Merge fix/compose-project-isolation: compose project identity derived…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T15:24:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc350c81fd3fbd2c7a0100dcb15434220a1b332e",
          "body": "The Docker Compose project name keys container, network, and volume names\nin the shared daemon — a global namespace — yet the operator emitted the\nmanifest `name:` verbatim. Two stacks sharing a `name:` (every dev workspace\ndefaults to the same example name) were merged into one Compose project even\n[…]\nsh suffix so a\npathological manifest name can't produce names Docker rejects; a fuzz target\nlocks the \"always a valid Compose project name\" invariant.\n\nSee docs/proposals/compose-project-isolation.md.",
          "is_bot": false,
          "headline": "fix(compose): derive project name from stack root, not manifest name:",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T15:24:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "794b11f4a3f84609de37f332a0152b0f09371b4a",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.6.1 (tail/-n on the per-service log socket)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:53:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "012ee9739cc627a6c17b8d551f1f6280aff8cb49",
          "body": null,
          "is_bot": false,
          "headline": "Merge feat/log-tail: tail/-n backlog on the per-service log socket",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:52:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6dd01031db4ddf344a7cb11693144426dbf49d88",
          "body": "GET /services/{name}/logs/stream now accepts ?tail=<n> (alias ?n=<n>) to replay\nthe last N available lines before the live follow begins, mapped to the compose\nand process-compose --tail flag. Threaded through LogsRequest.Tail and\nPlatform.StreamServiceLogs/LogStreamer; the handler parses and clamps the value\nto [0, 10000] (0/garbage = backend default). Documented and tested (argv on both\nbackends, param parsing, end-to-end passthrough).",
          "is_bot": false,
          "headline": "feat(logs): tail/-n backlog on the per-service log socket",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:52:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f4ee702552d77fe0dd77d6971c8a6cbe1985bd7",
          "body": "…(stack snapshot subscription)",
          "is_bot": false,
          "headline": "changelog: cut v0.6.0 (per-service log streaming) + backfill v0.5.16 …",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:27:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d7eff6d3f2cde7aa9c40c6bb6277afc2a6af0bc",
          "body": "…+ ingress.port fixes",
          "is_bot": false,
          "headline": "Merge feat/per-service-log-streaming: live per-service log streaming …",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:16:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0338c5d6d82d792d418b1a8ed999a126de4cf55",
          "body": "ingress.port only affects the plain-HTTP (tls: off) edge, but a port set under\ntls: auto or type: none was silently accepted as a dead no-op. ValidateExtended\nnow rejects it, matching how the mode-mismatched route.host/route.path\noverrides are handled. Also: document the field (and correct the stale\n[…]\nonly :80' claim) in the manifest guide, share a DefaultEdgePort\nconstant between HostPort and the route-URL builder, and cover the\nroute.host+custom-port URL plus the validation boundaries with tests.",
          "is_bot": false,
          "headline": "fix(ingress): reject ingress.port outside tls:off; docs + tests",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:16:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b38e208736f8f2038a8117092b63156a300eeb21",
          "body": "Add a line-by-line follow primitive (runtime.StreamCommand) so the compose\nand process-compose backends stream logs as produced instead of buffering via\nCombinedOutput — which also repairs the onServiceLogs/onWorkspaceLogs\nsubscriptions that previously emitted nothing until teardown. On top of it:\nP\n[…]\n/services/{name}/logs/stream (in-handler route-token/admin auth, origin\nchecked, stream opened pre-upgrade); and serviceEndpoint advertises the socket\n+ a minted credential in a log_stream descriptor.",
          "is_bot": false,
          "headline": "feat(logs): live per-service log streaming sockets",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T09:16:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "85a578f69d68abcea07d5a78f7ff0e575143081a",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.5.17 (ingress.port custom tls:off edge host port)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T07:47:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f34b92d42f908997247d2dbd6ef9aa36d83f9dd4",
          "body": null,
          "is_bot": false,
          "headline": "Merge feat/ingress-edge-port: ingress.port custom tls:off edge host port",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T07:47:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "031f0f26c4b957f3b83ca12a74b793b9a8747939",
          "body": "Lets the plain ws:// (tls: off) Caddy edge bind a host port other than 80\nvia ingress.port, so parallel dev stacks on one host no longer all contend\nfor :80. The chosen port maps to the edge container's :80 and is reflected\nin the consumer route URL (ws://host:PORT/...) when non-default; the prod\n(tls: auto) edge keeps 443/80 and ignores the field.\n\nSchema carries matching minimum/maximum bounds so JSON-schema and Go\nvalidation agree.",
          "is_bot": false,
          "headline": "feat(ingress): add ingress.port for a custom tls:off edge host port",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T07:47:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5f57a1237e1a33c80f45c15f481dc9c4eec84b48",
          "body": null,
          "is_bot": false,
          "headline": "stack snapshot",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-17T07:04:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "582df535a1035738ddf4e8ffbd6b7d490dea7532",
          "body": "…ase lookup)",
          "is_bot": false,
          "headline": "changelog: cut v0.5.15 (template autoescape fix + install latest-rele…",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-15T21:53:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "abc53d242faec2f7217c65ec45dd0f67881a6aaf",
          "body": "Pull in the copier-go build that calls pongo2.SetAutoescape(false) globally,\nmatching Jinja2 / Python Copier semantics. Without it, rendered template\nvalues containing \", <, >, or & were HTML-escaped (e.g. \" -> &quot;),\ncorrupting non-HTML output such as quoted angee.yaml values.",
          "is_bot": false,
          "headline": "fix(deps): bump copier-go to disable pongo2 HTML autoescaping",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-15T21:53:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dd12b18f73b5692932621bade2690d68bc0ea6f5",
          "body": "scripts/install.sh resolved the latest version via the unauthenticated GitHub\nREST API, which is rate limited to 60 req/hr/IP. On shared/CI networks (or after\na few retries) that returned an empty version and the installer silently fell\nback to building from source — which fails when Go isn't instal\n[…]\n`…/download/v${ANGEE_VERSION}/…`, yielding a broken `vv0.5.14`\n  URL. Strip the leading \"v\".\n\nVerified end-to-end while api.github.com was rate-limited: installs v0.5.14 CLI\nand operator successfully.",
          "is_bot": false,
          "headline": "fix(install): resolve latest release without the rate-limited GitHub API",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-15T15:08:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "99036be9ce3828c77ecf8d910f59c6ed179c215f",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.5.14 (ingress host/path routing modes and tls: off)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-15T13:38:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8910e0750866921d93a7af9b69682a17bf832b8",
          "body": "feat(ingress): host/path routing modes and tls: off",
          "is_bot": false,
          "headline": "Merge pull request #31 from ang-ee/feat/ingress-routing-modes",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-06-15T13:38:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6a5764a6384977661b8937202087835562de6810",
          "body": "Give the Caddy edge two routing modes selected by a new `ingress.routing`\nfield, plus an `ingress.tls` companion:\n\n- `routing: host` (default, unchanged) — one subdomain per service\n  (`wss://<service>.<domain>/`), one Caddy site block each.\n- `routing: path` — one shared host with a stripped prefix\n[…]\n; path mode requires a\ndomain. Shared `Route.HostName`/`Route.PathPrefix` helpers keep the URL\nresolver and the edge label generator from drifting.\n\nImplements docs/proposals/ingress-routing-modes.md.",
          "is_bot": false,
          "headline": "feat(ingress): add host/path routing modes and tls: off",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-15T13:37:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7e1f28355949c6ffe515eae1be9fcaeacfbf1ee0",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.5.13 (angee dev multi-runtime log streaming)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T22:20:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c19235ab7d59eaee222974760a838f25a8e5722",
          "body": "`angee dev` ran container services detached (docker compose up -d) and let\nprocess-compose own the foreground, so a mixed stack's container/agent logs\nnever appeared. It now brings both runtimes up attached and concurrently:\ndocker compose up (no -d) keeps its native per-service coloured output and\n\n[…]\nlouring; the operator's shared HTTP writer is\nmutex-guarded since exec runs a copier goroutine per child for non-file sinks.\n\nAdds `angee dev -d`/`--detach` to start the whole stack in the background.",
          "is_bot": false,
          "headline": "feat(dev): stream logs from every service runtime in `angee dev`",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T22:20:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fcf317a1a7eea302efaaaee1a852f71349f46735",
          "body": "Follow-ups from reviewing 99d745b:\n- Add TestServiceCreateDeclaresReferencedSecret: an end-to-end check that a\n  service referencing ${secret.NAME} persists the secret as a value-less\n  declaration and renders cleanly once the value is set via the backend.\n- Iterate env keys in sorted order in servi\n[…]\nr is deterministic (Go map iteration is randomized).\n- Drop the redundant []string(...) conversions on StringList ports/mounts.\n- Note the parallel jobs-reference-secrets gap in .agents/notes/todo.md.",
          "is_bot": false,
          "headline": "test(service): cover referenced-secret declaration end-to-end",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T22:20:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "99d745bb1bcaeacb643487e160fc0c1f1109692f",
          "body": "A service template is forbidden from declaring secrets (blast radius), but a\nservice legitimately references ${secret.NAME} in its env/command. The\npost-create compose re-render only resolves DECLARED secrets, so a\nreferenced-but-undeclared secret failed with `secret \"…\" is not resolved` —\nblocking \n[…]\nefs extractor over the service's substituted strings) as a\nplain external entry; the value still comes only from the backend, so\nreferencing grants no value. Rollback drops any newly-declared entries.",
          "is_bot": false,
          "headline": "fix(service): declare the secrets a service references at create",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T20:57:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2686d278b84c3759ae7f8cb426a5aa76e6318f5a",
          "body": null,
          "is_bot": false,
          "headline": "changelog: cut v0.5.12 (workspace stack update ports)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T13:09:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7aee38ada41906c5587482a41f5b17371d267e4b",
          "body": "When run on a workspace's inner stack, `stack update --template` re-rendered\nsolely from the inner stack's frozen .copier-answers.yml. If that file drifted\nto template defaults, the update silently baked default ports into the inner\nstack, colliding with the host stack and other workspaces.\n\nDetect \n[…]\nlved.allocations record. Only allocation-bearing\ninputs are reconciled; project/source inputs still come from the answers file,\nand already-resolved path inputs are reused verbatim (no re-resolution).",
          "is_bot": false,
          "headline": "fix(stack): honour workspace-allocated ports in stack update --template",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T13:09:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c8b96276f5bea35f2995f0bf109de5f223640796",
          "body": null,
          "is_bot": false,
          "headline": "persists in stack",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-14T09:19:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2237acba59ac2f88a443961cd2ce3d8de19636ec",
          "body": "chore: rename module to github.com/ang-ee/angee-operator",
          "is_bot": false,
          "headline": "Merge #27: rename module to github.com/ang-ee/angee-operator",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-06-04T15:03:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "71561055fcc53f2b01b981f22e941ca1be6985e3",
          "body": "The repository is now ang-ee/angee-operator (was ang-ee/angee, originally\nfyltr/angee). Rewrite the module path github.com/fyltr/angee ->\ngithub.com/ang-ee/angee-operator across go.mod and every importing file (Go\nsources, gqlgen.yml + regenerated generated.go, Makefile, Dockerfiles, CI +\nrelease wo\n[…]\nerator, ghcr.io/ang-ee/angee-cli) are unchanged.\nangee-django / angee-docs / angee-nextjs references are deliberately left intact.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: rename Go module to github.com/ang-ee/angee-operator",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-04T14:56:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "949c88d542dd210b927d55cc97223465f19ab8a6",
          "body": "refactor: one service.API contract for CLI, REST, and GraphQL",
          "is_bot": false,
          "headline": "Merge #26: service.API control-plane contract",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-06-04T14:51:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9d9d9e0fb990b388de06c4809110a0c2576a0e9d",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "changelog: cut v0.5.10 (service.API control-plane contract)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-04T14:40:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ee538fc24df6f3c65424692600b2cc221c17ec53",
          "body": "The CLI, REST operator, and GraphQL operator already delegated business\nlogic to service.Platform, but the only shared *interface* was a private,\nhand-maintained cli.platformClient that had drifted from the concrete type,\nthe operator coupled directly to *service.Platform, and the remote HTTP\nclient\n[…]\nompiledStack JSON wire-shape follow-up\nin .agents/notes/todo.md. Add a mock-based gql resolver test exercising a\nfake service.API.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract service.API as the single control-plane contract",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-04T14:30:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f718bb71b74979440e7c8da8842a9c8960bbfa5f",
          "body": "docs/public/angee.schema.json was stale relative to manifest.Stack after\nthe v0.5.8 Caddy edge ingress work added the Ingress/Route fields. Regenerate\nvia `make schema` so `make check-schema` passes. No code change.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: regenerate manifest schema (ingress/route drift)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-04T14:30:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8f94c33d94f53d069ede203184e9c1662ae5e99c",
          "body": "stack update --template: re-render angee.yaml from its stack template",
          "is_bot": false,
          "headline": "Merge #25: stack update --template (v0.5.9)",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-06-03T02:42:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "466e04479470656952e30d16d9473373aaaf8f3a",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "changelog: cut v0.5.9 (stack update --template)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-03T02:38:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8c5ec2175bfedca8b80400527ac16c819a68305d",
          "body": "Implements docs/proposals/stack-update-template-sync.md (Option B: structured\nmanifest merge), scoped to a local, opt-in path.\n\n- StackUpdateFromTemplate renders the stack's Copier template to a scratch dir,\n  structurally merges the template-origin sections over the current manifest\n  (template win\n[…]\nmerge keeping allocated value, fail on missing answers, dry-run\n  guard). Full 3-way conflict detection is a documented follow-up.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "stack: stack update --template re-renders manifest from its template",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-03T02:38:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bc0209473ae257fd98ea835909664a4a89135440",
          "body": null,
          "is_bot": false,
          "headline": "docs refactor",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-03T01:02:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "efbb5b3a97e09b8faf942040f5944f32148d3e12",
          "body": "A cohesive guide page (docs/guide/ingress.md) tying together the ingress\nedge, the connection/route token model, the /edge/verify forward_auth flow,\ngraphql-ws + routed WebSockets, dev setup, and operational caveats — the\nfeature was previously only documented piecemeal across the manifest and\noperator-API references. Cross-linked from both references.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add Edge Ingress & Scoped Tokens guide",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-03T00:42:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cf773b97f4550b6f89ea7f3b001dbed0328e43c9",
          "body": "Ingress: optional Caddy edge backend (ingress.type: caddy), default off",
          "is_bot": false,
          "headline": "Merge #24: ingress Caddy edge backend (v0.5.8)",
          "author_name": "Alexis Yushin",
          "author_login": "ayushin",
          "committed_at": "2026-06-02T23:10:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79421a33dfed8b243228c6b498b5cf485e1430b5",
          "body": "govulncheck flagged GO-2026-5039 (net/textproto) and GO-2026-5037\n(crypto/x509), both fixed in go1.25.11, against the pinned 1.25.10. Bump\nGO_VERSION in ci.yml/release.yml and the codeql.yml pin so CI, CodeQL, and the\npublished release binaries all build against the patched standard library.\nPre-existing infra issue surfaced on this branch; unrelated to the ingress code.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: bump Go toolchain 1.25.10 -> 1.25.11 (stdlib vuln fixes)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T23:05:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "683f5f8e11c58cc556e7cfee886a67dbf178c9ce",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "changelog: cut v0.5.8 (ingress Caddy edge)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:59:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac6fae01229791197b35dd43a01e046261d6944e",
          "body": "Two reviewers (correctness + security) on the ingress phase. Fixes:\n\nSecurity (Critical) — Caddyfile injection: manifest data (routed service\nnames, route.host, ingress fields) flowed unescaped into caddy-docker-proxy\nlabels. ValidateExtended now (under ingress.type: caddy) charset-checks routed\nnam\n[…]\nuide;\nCHANGELOG.\n\nApplied by Codex, verified by Claude (removed an ineffectual assignment;\nmake check green; go generate in sync).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ingress: address review findings (injection guard, orphan lease, ctx)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:54:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b647e589d4825178a054449bc92b8056b3f75c61",
          "body": "A live caddy-docker-proxy:2.9 spike (mock /edge/verify + WS echo backend)\nvalidated the design end-to-end (WS upgrade -> 101 with a valid route token,\n401 otherwise) and resolved the TODO(spike):\n\n- CaddyBackend stamps a direct per-service forward_auth (caddy.forward_auth +\n  caddy.forward_auth.uri \n[…]\ntoken= there; r.URL carries only ?service=). Added tests\n  for the forward_auth shape.\n- Proposal + plan record the spike results.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ingress: fold Caddy run-spike findings into edge labels + /edge/verify",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:31:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ef89c3752c24cae4b876d357caf70570d2bc220e",
          "body": "- manifest guide: ingress: backend + service route: with the WS-reload\n  operational note (short TTL + auto-reconnect + debounce).\n- operator-api.md: /edge/verify forward_auth target + serviceEndpoint /\n  ingressStatus queries.\n- CHANGELOG Unreleased: ingress (Caddy edge) entry.\n- plan: all chunks A-I complete.\n\nFinal chunk of the ingress build loop. Authored by Claude.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: document ingress/route, /edge/verify, endpoint queries (Chunk I)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:14:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "45751079510063e6b5edcaa1653ece60f8002e46",
          "body": "A routed service (ingress caddy + route:) is reached through the single edge\nand has its host ports stripped, so allocateServicePorts now early-returns an\nempty allocation for it — no lease taken. Non-routed services unchanged.\nBuilt by Codex, verified by Claude.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "service: skip port lease for routed services (Chunk H)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:12:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c31e1d58de66427372f159e7389947eda93606e1",
          "body": "Replaces host-side compose-port-scraping: serviceEndpoint(name) returns\n{routed, url (wss://), internalHost, internalPort}; ingressStatus returns\n{type, domain, routes}. New api DTOs mapped via gqlgen.yml, Platform methods\nread the manifest ingress/route, resolvers regenerated. surfaces.md updated\nfor the exported-method guard. Built by Codex, verified by Claude (full -race\nsuite + make check green; go generate in sync).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "operator: add serviceEndpoint + ingressStatus queries (Chunk G)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:08:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e0bc8c392300f06612623ba59207402c957e5f90",
          "body": "The edge's per-request auth check: resolves the service from ?service=,\nreads the token from ?token= / Authorization / Sec-WebSocket-Protocol, and\nverifies aud=svc:<service>. Returns 200/401, never 101 (the edge does the\nWS upgrade). Mounted outside s.auth (a route token isn't an operator token).\nBuilt by Codex, verified by Claude (full -race suite green).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "operator: add GET /edge/verify forward_auth target (Chunk F)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T22:00:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e4dcc2e0804cc8e1a5d69dbfdef9b6fd9235d1c9",
          "body": "Compile now calls edge.FromManifest(stack.Ingress).Contribute before\nreturning. Inert for ingress: none (existing compose output unchanged);\ninjects the edge for ingress: caddy. Built by Codex, verified by Claude\n(none-inert + caddy-injects tests through the real Compile path; make check green).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "service: wire edge backend into Compile() (Chunk E)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T21:55:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c906fc9d490008b037739f3266e1b22991e5a05e",
          "body": "Injects the caddy-docker-proxy edge service (only published port, docker\nsocket RO, joined to <name>_edge), adds the network, and for each routed\nservice clears host ports, joins the edge network, and stamps caddy labels\n(host, reverse_proxy upstreams, flush_interval -1, forward_auth import).\nNon-ro\n[…]\nocker-proxy global-snippet/forward_auth label syntax is marked\nTODO(spike) for run-validation. Built by Codex, verified by Claude.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "edge: implement CaddyBackend.Contribute (Chunk D)",
          "author_name": "Angee",
          "author_login": null,
          "committed_at": "2026-06-02T21:52:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 58,
      "commits_last_year": 221,
      "latest_release_at": "2026-07-16T11:33:25Z",
      "latest_release_tag": "v0.8.4",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 11,
      "days_since_latest_release": 9,
      "mean_days_between_releases": 2.2
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 12,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/ang-ee/angee-operator",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/ang-ee/angee-operator",
          "is_deprecated": false,
          "latest_version": "v0.8.4",
          "repository_url": "https://github.com/ang-ee/angee-operator",
          "versions_count": 62,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-16T11:30:21Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 9
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 3,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-16",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 8
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [
        "docs/public/angee.graphql",
        "internal/operator/schema.graphql"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 1005743,
      "source_files_sampled": 170,
      "oversized_source_files": 3,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md",
        "GEMINI.md"
      ],
      "agent_instruction_max_bytes": 7530
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/fyltr/copier-go",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20260615213950-5a55ba2e7116"
        },
        {
          "name": "github.com/gosimple/slug",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.15.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.45.0"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "github.com/99designs/gqlgen",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.17.90"
        },
        {
          "name": "github.com/bluekeyes/go-gitdiff",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.8.1"
        },
        {
          "name": "github.com/go-git/go-git/v5",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v5.19.1"
        },
        {
          "name": "github.com/go-playground/validator/v10",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v10.30.2"
        },
        {
          "name": "github.com/golang-jwt/jwt/v5",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v5.3.1"
        },
        {
          "name": "github.com/gorilla/websocket",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.5.0"
        },
        {
          "name": "github.com/invopop/jsonschema",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.14.0"
        },
        {
          "name": "github.com/vektah/gqlparser/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.5.33"
        },
        {
          "name": "golang.org/x/sync",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.20.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 4,
        "merged_prs": 25,
        "open_issues": 4,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 10
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "ayushin",
          "commits": 23,
          "avatar_url": "https://avatars.githubusercontent.com/u/6916509?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "codeql.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "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": "3 out of 3 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/13 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "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": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 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": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 9,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 1,
            "reason": "9 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "e74a6145416358d53e5bf491b7a127744a389e15",
        "ran_at": "2026-07-25T19:15:08Z",
        "aggregate_score": 6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": true,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-20T14:16:01Z",
      "oldest_open_prs": [
        {
          "number": 14,
          "created_at": "2026-05-11T22:17:29Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 32,
          "created_at": "2026-06-15T14:20:33Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 42,
          "created_at": "2026-07-20T14:15:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 43,
          "created_at": "2026-07-20T14:16:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-15T18:15:26Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 19,
          "created_at": "2026-06-01T13:41:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 33,
          "created_at": "2026-06-16T04:18:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 34,
          "created_at": "2026-06-16T04:31:28Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 35,
          "created_at": "2026-06-16T04:54:07Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/ang-ee/angee-operator",
    "host": "github.com",
    "name": "angee-operator",
    "owner": "ang-ee"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 55,
      "inputs": {
        "security": 60,
        "vitality": 79,
        "community": 14,
        "governance": 41,
        "engineering": 78
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 79,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "commits_last_year": 221,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 11
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "11/52 weeks with commits",
                "points": 7.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 11
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "221 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 221
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 58,
              "latest_release_tag": "v0.8.4",
              "releases_from_tags": false,
              "days_since_latest_release": 9,
              "mean_days_between_releases": 2.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "58 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 58
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 9 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 9
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 14,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 5,
            "inputs": {
              "forks": 1,
              "stars": 3,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "3 stars",
                "points": 4.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "critical",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 41,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 27,
            "inputs": {
              "merged_prs": 25,
              "open_issues": 4,
              "closed_issues": 0,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 10
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "25/35 decided PRs merged",
                "points": 27.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 25,
                      "decided": 35
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/13 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 41,
            "inputs": {
              "followers": 2,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "ang-ee",
              "public_repos": 9,
              "account_age_days": 55
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "2 followers of ang-ee",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "ang-ee"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "9 public repos, account ~0 yr old",
                "points": 7.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 9
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/ang-ee/angee-operator"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 9
            },
            "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 9 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 9
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "62 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 62
                    }
                  }
                ],
                "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": 78,
        "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": "3 out of 3 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": "https://docs.angee.ai/",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://docs.angee.ai/",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 60,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 6
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "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": "3 out of 3 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/13 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is run on all commits",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "9 existing vulnerabilities detected",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 81,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.9,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md",
                "GEMINI.md"
              ],
              "agent_instruction_max_bytes": 7530
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md, GEMINI.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md, GEMINI.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "90 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 90,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 87,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.17,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".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": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "17 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 17,
                      "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": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 1005743,
              "source_files_sampled": 170,
              "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/170 source files over 60KB",
                "points": 54,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 170,
                      "oversized": 3
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": false,
              "api_schema_files": [
                "docs/public/angee.graphql",
                "internal/operator/schema.graphql"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "docs/public/angee.graphql, internal/operator/schema.graphql",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "docs/public/angee.graphql, internal/operator/schema.graphql"
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-25T19:15:22.103687Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/ang-ee/angee-operator.svg",
  "full_name": "ang-ee/angee-operator",
  "license_state": "absent",
  "license_spdx": null
}

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

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

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