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

pascalorg / editor

Create and share 3D architectural projects.

TypeScriptMIT★ 17.533 estrellas⑂ 2392 forksdesde oct 2025Ver en GitHub ↗

pascalorg/editor tiene un índice de salud de 74 sobre 100, lo que lo sitúa en la banda Bueno. Su puntuación más alta es Vitality (90/100) y la más baja, Security (43/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

74
global / 100
Bueno

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

74
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

PascalOrganización
273 seguidores4 repositorios públicosdesde may 2025

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
npm@pascal-app/mcp0.3.23144hace 5 díasmcpmodel-context-protocolpascal3dbuildingeditorai
npm@pascal-app/core0.9.216.29124hace 5 días3dbuildingeditorarchitecturewebgputhree.js
npm@pascal-app/nodes0.1.11171hace 5 díaspascal3deditornode-registry
npm@pascal-app/editor0.9.215337hace 5 días
npm@pascal-app/viewer0.9.2510726hace 5 días3dbuildingeditorviewerarchitecturewebgputhree.jsreact-three-fiber
npm@pascal-app/ifc-converter0.1.23033hace 5 días

Métricas por categoría

Vitalidad

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

90Excelente · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
19.4/36Cadencia de commits — 28/52 semanas con commits
18/18Volumen de commits — 1216 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1216
human_commit_share0,99
days_since_last_push0
active_weeks_last_year28
Cómo se puntúa
27/27Publica versiones — 13 versiones publicadas
36/36Recencia de las versiones — última versión hace 42 días
27/27Cadencia de publicación — una versión cada ~7,9 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count13
latest_release_tagv0.9.1
releases_from_tagsno
days_since_latest_release42
mean_days_between_releases7,9
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

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

84Bueno · 18% del índice global
Cómo se puntúa
60/60Estrellas — 17.533 estrellas
25/25Forks — 2392 forks
11.2/15Observadores — 103 observadores
Datos de entrada utilizados
forks2392
stars17.533
watchers103
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
18/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributing
has_issue_templateno
has_code_of_conductno
has_pull_request_template
Cómo se puntúa
58.3/80Descargas mensuales — 23.665 descargas/mes en npm
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packages@pascal-app/mcp, @pascal-app/core, @pascal-app/nodes, @pascal-app/editor, @pascal-app/viewer, @pascal-app/ifc-converter
dependents
ecosystemsnpm
total_downloads
monthly_downloads23.665
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

65Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
9.1/22.5Distribución de commits — el principal contribuyente firma el 60% de los commits
13.5/13.5Amplitud de contribuyentes — 25 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 4 contributing companies or organizations
Datos de entrada utilizados
bus_factor1
contributors_sampled25
top_contributor_share0,597
Cómo se puntúa
37.7/46.8Resolución de issues — 81% de issues cerradas
31.9/38.3Aceptación de PR — 364/436 PR decididos fusionados
3/15OpenSSF Scorecard: Code-Review — Found 6/27 approved changesets -- score normalized to 2
Datos de entrada utilizados
merged_prs364
open_issues13
closed_issues54
issue_closed_ratio0,806
closed_unmerged_prs72
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
17.5/25Alcance del propietario — 273 seguidores de pascalorg
7.4/25Trayectoria — 4 repos públicos, cuenta de ~1 años
Datos de entrada utilizados
followers273
owner_typeOrganization
is_verified
owner_loginpascalorg
public_repos4
account_age_days418
Cómo se puntúa
25/25Publicado y resoluble — 6 paquete(s) en npm
35/35Recencia de publicación — última publicación hace 5 días
20/20Historial de versiones — 26 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packages@pascal-app/mcp, @pascal-app/core, @pascal-app/nodes, @pascal-app/editor, @pascal-app/viewer, @pascal-app/ifc-converter
ecosystemsnpm
any_deprecatedno
min_days_since_publish5

Calidad de Ingeniería

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

81Bueno · 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 — eslint.config.mjs
0/9.6Hooks de pre-commit
0/6.4.editorconfig
18/20OpenSSF Scorecard: CI-Tests — 25 out of 26 merged PRs checked by a CI test -- score normalized to 9
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://editor.pascal.app
10/10Descripción del repositorio
0/10Topics
0/10Wiki
Datos de entrada utilizados
topics
has_wikino
homepagehttps://editor.pascal.app
has_readme
has_docs_dir
has_description

Seguridad

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

43En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.2/2.5CI-Tests — 25 out of 26 merged PRs checked by a CI test -- score normalized to 9
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
1.5/7.5Code-Review — Found 6/27 approved changesets -- score normalized to 2
2.5/2.5Contributors — project has 4 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 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
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — sin datos
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4,3
Excluidos de la puntuación (sin datos o no aplicable): signed_releases, vulnerabilities. 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.

75Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — .github/copilot-instructions.md, AGENTS.md, CLAUDE.md, GEMINI.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 98 de 99 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,99
agent_instruction_files.github/copilot-instructions.md, AGENTS.md, CLAUDE.md, GEMINI.md
agent_instruction_max_bytes3613
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — eslint.config.mjs
11/11Verificación estática de tipos — apps/editor/tsconfig.json, apps/ifc-converter/tsconfig.json, packages/core/tsconfig.json, packages/editor/tsconfig.json, packages/ifc-converter/tsconfig.json, packages/mcp/tsconfig.json, packages/nodes/tsconfig.json, packages/ui/tsconfig.json, packages/viewer/tsconfig.json
10/10Entorno reproducible — devcontainer
10/10Práctica demostrada con agentes — 64 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfileno
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsapps/editor/tsconfig.json, apps/ifc-converter/tsconfig.json, packages/core/tsconfig.json, packages/editor/tsconfig.json, packages/ifc-converter/tsconfig.json, packages/mcp/tsconfig.json, packages/nodes/tsconfig.json, packages/ui/tsconfig.json, packages/viewer/tsconfig.json
agent_commit_share0,64
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — TypeScript (tipado estático)
54.2/55Tamaños de archivo manejables — 22/1595 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageTypeScript
largest_source_bytes391.002
source_files_sampled1595
oversized_source_files22
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
20/20Servidor MCP
40/40Ejemplos ejecutables — demos, examples
Datos de entrada utilizados
example_dirsdemos, examples
has_mcp_signal
api_schema_files

Datos clave

17.533estrellas de GitHub
25contribuidores
1216commits en los últimos 12 meses
0días desde el último push
13versiones publicadas
1factor bus
13issues abiertas
npmecosistemas 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
  • deps.dev does not index npm:@pascal-app/editor@0.9.2; advisories assessed against the repository dependency graph instead

Más detalle

Historial de estrellas y forks 0 ★ / 2392 ⇿
0Estrellas
2392Forks
6Versiones

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

Solo se muestra el historial más reciente: este repositorio supera la ventana de recopilación, por lo que no se captura el historial más antiguo.

12001600200024002392752026-042026-062026-07
Mayor 0Menor 4Parche 2
OpenSSF Scorecard 4.3 / 10
4.3agregado

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-23 00:42 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
9CI-Tests25 out of 26 merged PRs checked by a CI test -- score normalized to 9
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
2Code-ReviewFound 6/27 approved changesets -- score normalized to 2
10Contributorsproject has 4 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 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
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
n/dVulnerabilitiesinternal error: vulnerabilitiesClient.ListUnfixedVulnerabilities: osvscanner.DoScan: client error: status="400 Bad Request" body={"code":3,"message":"error in query at index 192: rpc error: code = InvalidArgument desc = invalid hash"}
Dependencias directas 92
RegistroPaqueteRestricción de versiónManifiesto
npm@iconify/react^6.0.2apps/editor/package.json
npm@number-flow/react^0.6.0apps/editor/package.json
npm@pascal-app/core*apps/editor/package.json
npm@pascal-app/editor*apps/editor/package.json
npm@pascal-app/mcp*apps/editor/package.json
npm@pascal-app/nodes*apps/editor/package.json
npm@pascal-app/plugin-treesgithub:pascalorg/plugin-trees#56d978cd9b409b716207b3f3d269455d3cd6f067apps/editor/package.json
npm@pascal-app/viewer*apps/editor/package.json
npm@radix-ui/react-tooltip^1.2.8apps/editor/package.json
npm@react-three/drei^10.7.7apps/editor/package.json
npm@react-three/fiber^9.5.0apps/editor/package.json
npm@tailwindcss/postcss^4.2.1apps/editor/package.json
npmclsx^2.1.1apps/editor/package.json
npmgeist^1.7.0apps/editor/package.json
npmlucide-react^1.7.0apps/editor/package.json
npmnext16.2.9apps/editor/package.json
npmpostcss^8.5.6apps/editor/package.json
npmreact^19.2.4apps/editor/package.json
npmreact-dom^19.2.4apps/editor/package.json
npmtailwind-merge^3.5.0apps/editor/package.json
npmtailwindcss^4.2.1apps/editor/package.json
npmthree^0.185.0apps/editor/package.json
npmzod^4.3.5apps/editor/package.json
npm@pascal-app/core*apps/ifc-converter/package.json
npm@pascal-app/ifc-converter*apps/ifc-converter/package.json
npm@pascal-app/nodes*apps/ifc-converter/package.json
npm@pascal-app/viewer*apps/ifc-converter/package.json
npmlucide-react^1.7.0apps/ifc-converter/package.json
npm@react-three/drei^10.7.7apps/ifc-converter/package.json
npm@react-three/fiber^9.5.0apps/ifc-converter/package.json
npm@tailwindcss/postcss^4.2.1apps/ifc-converter/package.json
npmclsx^2.1.1apps/ifc-converter/package.json
npmnext16.2.9apps/ifc-converter/package.json
npmpostcss^8.5.6apps/ifc-converter/package.json
npmreact^19.2.4apps/ifc-converter/package.json
npmreact-dom^19.2.4apps/ifc-converter/package.json
npmtailwind-merge^3.5.0apps/ifc-converter/package.json
npmtailwindcss^4.2.1apps/ifc-converter/package.json
npmthree^0.185.0apps/ifc-converter/package.json
npmweb-ifc^0.0.77apps/ifc-converter/package.json
npmzod^4.3.5apps/ifc-converter/package.json
npmdedent^1.7.1packages/core/package.json
npmidb-keyval^6.2.2packages/core/package.json
npmmitt^3.0.1packages/core/package.json
npmnanoid^5.1.6packages/core/package.json
npmzod^4.3.5packages/core/package.json
npmzundo^2.3.0packages/core/package.json
npmzustand^5packages/core/package.json
npm@dnd-kit/core^6.3.1packages/editor/package.json
npm@dnd-kit/sortable^10.0.0packages/editor/package.json
npm@dnd-kit/utilities^3.2.2packages/editor/package.json
npm@iconify/react^6.0.2packages/editor/package.json
npm@number-flow/react^0.6.0packages/editor/package.json
npm@pascal-app/lingo^0.2.0packages/editor/package.json
npm@radix-ui/react-alert-dialog^1.1.15packages/editor/package.json
npm@radix-ui/react-context-menu^2.2.16packages/editor/package.json
npm@radix-ui/react-dialog^1.1.15packages/editor/package.json
npm@radix-ui/react-dropdown-menu^2.1.16packages/editor/package.json
npm@radix-ui/react-popover^1.1.15packages/editor/package.json
npm@radix-ui/react-select^2.2.6packages/editor/package.json
npm@radix-ui/react-separator^1.1.8packages/editor/package.json
npm@radix-ui/react-slider^1.3.6packages/editor/package.json
npm@radix-ui/react-slot^1.2.4packages/editor/package.json
npm@radix-ui/react-switch^1.2.6packages/editor/package.json
npm@radix-ui/react-tabs^1.1.13packages/editor/package.json
npm@radix-ui/react-tooltip^1.2.8packages/editor/package.json
npm@visual-json/react^0.4.0packages/editor/package.json
npmblob-stream^0.1.3packages/editor/package.json
npmclass-variance-authority^0.7.1packages/editor/package.json
npmclsx^2.1.1packages/editor/package.json
npmcmdk^1.1.1packages/editor/package.json
npmhowler^2.2.4packages/editor/package.json
npmlucide-react^1.7.0packages/editor/package.json
npmmitt^3.0.1packages/editor/package.json
npmmotion^12.34.3packages/editor/package.json
npmnanoid^5.1.6packages/editor/package.json
npmpdfkit^0.19.1packages/editor/package.json
npmtailwind-merge^3.5.0packages/editor/package.json
npmthree-mesh-bvh~0.9.8packages/editor/package.json
npmzod^4.3.6packages/editor/package.json
npmzustand^5.0.11packages/editor/package.json
npm@pascal-app/core*packages/ifc-converter/package.json
npmnanoid^5.1.6packages/ifc-converter/package.json
npmweb-ifc^0.0.77packages/ifc-converter/package.json
npm@modelcontextprotocol/sdk^1.29.0packages/mcp/package.json
npm@pascal-app/lingo^0.2.0packages/mcp/package.json
npmzod^4.3.5packages/mcp/package.json
npmreact^19.2.0packages/ui/package.json
npmreact-dom^19.2.0packages/ui/package.json
npmthree-bvh-csg^0.0.18packages/viewer/package.json
npmthree-mesh-bvh^0.9.8packages/viewer/package.json
npmzustand^5packages/viewer/package.json
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": 124285,
      "has_wiki": false,
      "homepage": "https://editor.pascal.app",
      "languages": {
        "CSS": 14861,
        "Shell": 13882,
        "JavaScript": 5330,
        "TypeScript": 12754169
      },
      "pushed_at": "2026-07-22T18:51:34Z",
      "created_at": "2025-10-16T19:35:06Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-22T19:29:00Z",
      "description": "Create and share 3D architectural projects.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "https://editor.pascal.app",
      "name": "Pascal",
      "type": "Organization",
      "login": "pascalorg",
      "company": null,
      "location": "United States of America",
      "followers": 273,
      "avatar_url": "https://avatars.githubusercontent.com/u/214160140?v=4",
      "created_at": "2025-05-30T17:13:27Z",
      "is_verified": null,
      "public_repos": 4,
      "account_age_days": 418
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.9.1",
          "kind": "patch",
          "published_at": "2026-06-10T03:17:29Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-05-27T18:48:43Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-05-10T00:47:25Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-05-09T14:38:28Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-04-22T06:05:55Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-04-14T05:02:27Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-04-13T12:45:32Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-04-07T23:23:24Z"
        },
        {
          "tag": "v0.3.3",
          "kind": "patch",
          "published_at": "2026-03-31T20:52:29Z"
        },
        {
          "tag": "v0.3.2",
          "kind": "patch",
          "published_at": "2026-03-30T21:46:43Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-03-26T21:09:30Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-03-24T19:48:36Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-03-21T03:22:04Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "26c9e17fed2b2c8416c90036f1f5d8636792a523",
          "body": "Wall/fence drafting already drew an X/Z axis cross at the segment start.\nNow the moving endpoint gets a single long guide line perpendicular to the\ndraft segment (a second cross would collide with the start cross on\naxis-aligned segments), fences gain the same guides they lacked entirely,\nand the 2D\n[…]\new store.\n\nThe guide components are extracted from wall/tool.tsx into\nnodes/shared/draft-axis-guides.tsx so both tools (and the fence's formerly\nduplicated arc/label helpers) share one implementation.",
          "is_bot": false,
          "headline": "feat(nodes): draft axis guides at the moving endpoint + 2d parity (#534)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-22T18:51:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "77442861d9a7e44de64bb1e5fa4c690d8a3865b5",
          "body": "* Add roof surface placement support for items\n\nItems (e.g. solar panels) can now be placed on sloped roof surfaces.\nThe placement system computes euler rotation from the roof surface\nnormal so items sit flush on the slope instead of going inside.\n\n- Add roofStrategy to placement-strategies with ent\n[…]\nundaries\n\n* feat(floorplan): refine construction dimension references\n\n* fix(floorplan): align documentation tools with architecture\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "editor: complete floorplan construction documentation (#531)",
          "author_name": "Sudhir Yadav",
          "author_login": "sudhir9297",
          "committed_at": "2026-07-22T18:02:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2adb50a340d32aa47a63e94590bef3c545f6beab",
          "body": "…orner (#533)\n\n* fix(wall): stop endpoint drag snapping back to the stale junction corner\n\nWalls attached to the moving corner cascade with the drag, but the snap\npipeline reads the scene store, which keeps their pre-drag coordinates\nuntil commit. Their stale corners recreated the old junction as a \n[…]\npply() with the raw\nplanPoint on modifier changes. Flagged by Bugbot on #533.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "editor: stop wall endpoint drag snapping back to the stale junction c…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-22T13:46:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0fba611a05015550a2a537021cb5d39251f711b8",
          "body": "…ode in GLB export (#532)\n\nBake v2 exporter side: library/preset, legacy scene-material, and item-GLB\ntextures get a validated pascalTextureRef stamped at load (origin-checked,\nenv-derived). Material-ish sources resolve to 'library-material' (storage\nbucket) or 'app-material' (static catalog on the \n[…]\nrites the ref to both texture and image extras via a\nGLTFExporter writeTexture plugin. Download GLB stays embed; the bake page\npasses reference.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(export): texture references — stamp sources at load, reference m…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-22T12:33:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cb6fadbc288f9daa627e866f31eb86a39b2d93e5",
          "body": "* feat(walkthrough): unify first-person and baked walkthrough UI into a shared HUD\n\nThe builder first-person overlay (crosshair, Exit Street View button, hints\ncard) and the baked-GLB walkthrough HUD were two divergent UIs. Extract the\nGLB-style HUD (reticle, floor/room labels, Esc pill, interact pr\n[…]\nnt error predates this branch (#526); fixed here to unblock\nthe quality gate.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "editor: unify walkthrough + viewer UI, crouch, screenshot pause (#529)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-21T21:04:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "de13119f86f857e23d4c1c2b76c73bf620089b9a",
          "body": "…ows (#528)\n\nDocuments the shipped vertical building model (#526): stored truth table,\nresolution helpers, clamp rules, pointer-decided placement, the load\nmigration that lives in migrateNodes indefinitely, and the gotchas. The\nsystems tables stop listing the deleted SlabSystem and point at the\nregistry geometry path instead.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(wiki): vertical-model architecture page; drop stale SlabSystem r…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-21T18:44:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "adc1ec89f439d5464d114eddd62f5912e6a40892",
          "body": "* fix(viewer): guard TextureNode updates against null textures\n\nthree's override-material passes (shadow, prepasses) copy per-object texture\nslots onto shared materials whose cached per-mesh node graphs can disagree\nabout a slot's presence; when a graph with a TextureNode pulls a null slot,\nthe exce\n[…]\nhored-By: Claude Fable 5 <noreply@anthropic.com>\n\n* style: sort guard imports\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(viewer): guard TextureNode updates against null textures (#527)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-21T15:34:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "603f5d2242e11521692b4299fc724d2a389c9f6e",
          "body": "…category (#525)\n\n* feat(materials): dynamic library registry, picker source tabs, create-material entry point\n\nCore gains a runtime material registry (registerLibraryMaterials/\nunregisterLibraryMaterials/subscribeLibraryMaterials) so embedders can\nfeed user/community materials; library: refs to reg\n[…]\nhas no real height map, so the copied slot is never null in either\ndirection.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(materials): dynamic library registry, picker source tabs, Other …",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-21T14:00:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bf89b5bcf2e98d06ce4a731a5e97c6abb883c189",
          "body": "… decks (#526)\n\n* feat(core): stored storey heights groundwork — pure slab-support module + level height schema\n\nExtract pointInPolygon/computeWallSlabSupport and friends into a cycle-free\npackages/core/src/systems/slab/slab-support.ts (severs level-height ->\nspatial-grid-manager -> use-scene), add \n[…]\nr slot lets the host app dock\nactions below it, exactly like inspectorFooter.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: vertical building model — stored level heights, wall inversion,…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-21T13:57:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "34b601bb7970b727afa18a0bd4cc3821aaa5ddac",
          "body": "Improve realtime collaboration feedback and previews",
          "is_bot": false,
          "headline": "Merge pull request #523 from pascalorg/feat/realtime-collaboration-sfx",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-20T23:44:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1a4dba74002083634d7fa1b54d479bbf8eee52d",
          "body": null,
          "is_bot": false,
          "headline": "feat: improve collaboration feedback and previews",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-20T18:25:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "10c9c6ad27273b05f44eb55980b3e4e4259cd2c8",
          "body": null,
          "is_bot": false,
          "headline": "fix: harden item and baked scene rendering (#522)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-20T16:15:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d43a39f9a7b3036da0daa114c1018493dff0a60",
          "body": null,
          "is_bot": false,
          "headline": "docs(viewer): document npm registry bootstrap (#521)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T16:43:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59a67e68ca54e1b55385a9f5d6aefaac77a619b4",
          "body": "* add devcontainer setup and change default port to 3002\n\n* fix(devcontainer): enforce frozen install\n\n---------\n\nCo-authored-by: victor <victor@elalemanyo.de>",
          "is_bot": false,
          "headline": "chore: add a verified Bun devcontainer (#520)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T16:39:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "494150dc1feb4f2a19f8a01d9d7544d5eb0c5c1f",
          "body": "* fix(viewer): stack levels per building\n\n* fix(viewer): recover legacy level ownership",
          "is_bot": false,
          "headline": "fix(viewer): stack levels per building (#519)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T16:29:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87f3952e4d07140f1b389c099e7c0d177be9fa37",
          "body": "Co-authored-by: Connor Soohoo <connorsoohoo@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(viewer): harden WebGPU slab recovery (#518)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:58:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7734b8ffeac651d5e556300b296854131d84a9a",
          "body": null,
          "is_bot": false,
          "headline": "test(nodes): isolate cabinet regression suites (#517)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:54:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "263b4ab6d0567bc1282555270dbf81d0e950b9f6",
          "body": "* fix(mcp): keep store receiver bound in scene event operations\n\nappendSceneEvent and listSceneEvents detached the store methods before\ninvoking them (const append = this.requireStore().appendSceneEvent;\nappend(options)), so `this` was undefined inside store implementations\nthat rely on it — SqliteS\n[…]\n 5 <noreply@anthropic.com>\n\n* test(mcp): close scene store after facade tests\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: Aymeric Rabot <aymeric.rabot@gmail.com>",
          "is_bot": false,
          "headline": "fix(mcp): keep store receiver bound in scene event operations (#489)",
          "author_name": "Kone Venkatesh",
          "author_login": "konevenkatesh",
          "committed_at": "2026-07-19T15:49:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e484e17f82dd97532df23e8a5a5c92a836153d71",
          "body": "Co-authored-by: mvanhorn <mvanhorn@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(viewer): kick render on resume (#516)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:46:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f67787077e22d0a4608c4795d31cb3e15e0d6ac8",
          "body": "…ry MONOREPO-EDITOR-EM) (#486)\n\n* fix(core): guard material-ref parsers against non-string values (Sentry MONOREPO-EDITOR-EM)\n\ngetLibraryMaterialIdFromRef and getSceneMaterialIdFromRef only guarded\nagainst null/undefined, then called .startsWith(). When a non-string\nmaterial ref reaches them (legacy\n[…]\nuring wall material\nresolution (packages/viewer wall-materials.ts -> parseMaterialRef).\n\n* test(core): cover malformed material refs\n\n---------\n\nCo-authored-by: Aymeric Rabot <aymeric.rabot@gmail.com>",
          "is_bot": false,
          "headline": "fix(core): guard material-ref parsers against non-string values (Sent…",
          "author_name": "Anton",
          "author_login": "anton-pascal",
          "committed_at": "2026-07-19T15:41:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5c7f58f2955a320a32857bb7490c764afcc50e92",
          "body": "Preload the selected tool inspector",
          "is_bot": false,
          "headline": "Merge pull request #515 from pascalorg/fix/preload-tool-inspector",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:40:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16ea186f772e8b15c903752bba1d1bb9d6b180b2",
          "body": "…NOREPO-EDITOR-EK) (#504)\n\n* fix(viewer): guard texture.repeat against non-array values (Sentry MONOREPO-EDITOR-EK)\n\n* fix(viewer): normalize legacy texture repeats\n\n---------\n\nCo-authored-by: openclaw-agent <agent@pascal.app>\nCo-authored-by: Aymeric Rabot <aymeric.rabot@gmail.com>",
          "is_bot": false,
          "headline": "fix(viewer): guard texture.repeat against non-array values (Sentry MO…",
          "author_name": "Anton",
          "author_login": "anton-pascal",
          "committed_at": "2026-07-19T15:40:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0ac9fb739769b0453aa9aca089f7aa447ccae9b",
          "body": "…(Sentry MONOREPO-EDITOR-79) (#459)\n\nCo-authored-by: Anton Pascal <anton-pascal@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(editor): guard GLB export against undefined array-material slots …",
          "author_name": "Anton",
          "author_login": "anton-pascal",
          "committed_at": "2026-07-19T15:40:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2129eed0c28e2d67e1bf8f419fa3b2eb783e3a08",
          "body": null,
          "is_bot": false,
          "headline": "fix(editor): preload selected tool inspector",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:35:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6cc10c929e6fded1dbef45ff0f46b194210b983b",
          "body": "* Add roof surface placement support for items\n\nItems (e.g. solar panels) can now be placed on sloped roof surfaces.\nThe placement system computes euler rotation from the roof surface\nnormal so items sit flush on the slope instead of going inside.\n\n- Add roofStrategy to placement-strategies with ent\n[…]\n modes for resize handles\n\n* fix(editor): harden cabinet resize interactions\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>\nCo-authored-by: Aymeric Rabot <aymeric.rabot@gmail.com>",
          "is_bot": false,
          "headline": "editor: improve cabinet resizing and wall alignment (#503)",
          "author_name": "Sudhir Yadav",
          "author_login": "sudhir9297",
          "committed_at": "2026-07-19T15:33:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c0a5db935e1cd34bfcaa18059568c5d34d29d465",
          "body": "Expose generic host integration primitives",
          "is_bot": false,
          "headline": "Merge pull request #514 from pascalorg/feat/host-integration-primitives",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:19:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8f1c834e56749038cc563ee8167fdba08372a95d",
          "body": null,
          "is_bot": false,
          "headline": "feat(core): expose generic host integration primitives",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-19T15:11:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2084892383ababb4cb0d2941d46e87982647a95c",
          "body": null,
          "is_bot": false,
          "headline": "fix: derive zone quantities from room topology (#512)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-18T12:35:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cddb73b23277eda8ea179242a1c381e1425d31a1",
          "body": null,
          "is_bot": false,
          "headline": "fix: harden measurement geometry (#507)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-18T07:44:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99cc537e2538419536be86678a6139047a13af9d",
          "body": "…editor@0.9.2 @pascal-app/nodes@0.1.1 @pascal-app/mcp@0.3.2 @pascal-app/ifc-converter@0.1.2",
          "is_bot": true,
          "headline": "release: @pascal-app/core@0.9.2 @pascal-app/viewer@0.9.2 @pascal-app/…",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-17T17:11:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cdf026bb92426cb7bd2807ce447e029dadbdaa86",
          "body": null,
          "is_bot": false,
          "headline": "fix: publish built-in nodes package (#506)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-17T17:07:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae87ca5475cb18809eb3b43a00422a2b08001860",
          "body": "* feat: add persistent measurement tools\n\n* feat: make measurements associative\n\n* fix: finish measurements with Escape\n\n* feat: improve measurement snapping guides\n\n* feat: clarify measurement axis feedback\n\n* feat: smart measure lens, zone reports, and direct measurement editing\n\n- Smart measureme\n[…]\nhe magnetic override seam.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n* fix(measurement): stabilize area surface intent\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add production measurement tools (#505)",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-17T17:01:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "22c9472066398dae668b45e65c4785a56b3d0fb8",
          "body": "…d fix (#502)\n\n* fix(viewer): tune shadow biases to stop acne without detaching shadows\n\nnormalBias 0.02 was too small a texel offset for the building-fit 1024\nshadow map and brought back self-shadowing acne. Settle on normalBias 0.08\n(0.07 and below acnes, 0.1 reads detached) plus depth bias -0.000\n[…]\nsks whether the ROOM is substantially covered by the union of manual\n  slabs.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Adjustments pass: shadow bias, polygon editor UX, space-detection loa…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-16T14:55:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9ca3eaa7fe8e8b96e5056af758d8bc96c3835d41",
          "body": null,
          "is_bot": false,
          "headline": "feat: add project plugin management (#501)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-16T14:26:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f0aa7f7b64850a833809f65bc4c042c899a1a75",
          "body": "* fix(core): bound slab corner miters\n\n* style(core): format slab miter fix",
          "is_bot": false,
          "headline": "fix(core): prevent unbounded slab corner miters (#500)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-16T00:10:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78223d61cf382bf46688de2771f99528e10df794",
          "body": null,
          "is_bot": false,
          "headline": "fix(core): exclude dangling walls from room polygons (#499)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-15T21:53:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a524da1574fc0a517568e121e973fc6cf6c694c1",
          "body": "* chore(core): point material catalog at KTX2 tiers for wood/flooring/roofing finishes\n\nAll 48 remaining webp/jpg/png finish entries now reference _512.ktx2 maps\nand 256px _thumb.webp previews, matching the fabric/leather/concrete/metal\nconvention. flipY set to false on the converted entries — compr\n[…]\nClaude Fable 5 <noreply@anthropic.com>\n\n* fix: stabilize room surfaces and wall openings\n\n* style(core): format KTX2 material catalog\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix room surfaces, wall openings, and paint scope (#498)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-15T20:35:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4fca38a3ef7517e0a635794058beceff952aea4c",
          "body": "* fix(editor): wall endpoint move — detach/attach modifier sync and zero-move drop\n\n- restore linked walls to original positions the moment alt-detach engages\n- re-run the endpoint preview on alt keydown/keyup so re-attach doesn't wait for a mousemove; preview, HUD badge, and commit share one alt so\n[…]\nle 5 <noreply@anthropic.com>\n\n* fix(core): resolve slab joins across floor elevations\n\n* fix(editor): keep slab resize arrows visible\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: make room walls and slabs join cleanly (#497)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-15T17:28:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a59074774898116c0e7116b424b371e5e3420ea4",
          "body": "…ixes (#496)\n\n* fix(editor): only start handle drags on primary button\n\nRight-click over a rotation/move/resize handle started the gesture and\nstopPropagation()'d, fighting the camera orbit. Guard every gesture\nstarter (shared useHandleDrag, group rotate gizmo, wall endpoint/height/\nmove, fence move\n[…]\ng positionLocal (instance transform included)\nrestores r184 behavior exactly.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Adjustments pass: three 0.185, undo/cancel semantics, guide & panel f…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-14T17:26:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3625d17bfc5bc6c5517d22bbd94dcf50c44d351b",
          "body": "…ose (#495)\n\nThe AI/chat tab was the default panel when opening a project; build is\nthe expected starting point. Also, collapsing the sidebar (rail click or\ndrag-collapse on desktop, sheet close on mobile) left the last build\ntool armed — it now resets to select mode.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): default sidebar to build tab, drop to select on panel cl…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-14T12:48:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "47313263fbf628235bce2aaa795ed61b125263f0",
          "body": "…drop, grounded horizon (#493)\n\n* feat(editor): dev-only window hook for deterministic camera poses\n\nExposes a getter for the CameraControls impl in development so\nscreenshot/automation tooling can set exact camera poses.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n* feat(viewer): rende\n[…]\nish, sunish, and half the height, so blue starts right\nabove the ground line.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(viewer): rendering & lighting pass — sun-dominant look, sky back…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-13T15:24:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c45808840c5694f4cff92def4f18fccb64590412",
          "body": "* Add roof surface placement support for items\n\nItems (e.g. solar panels) can now be placed on sloped roof surfaces.\nThe placement system computes euler rotation from the roof surface\nnormal so items sit flush on the slope instead of going inside.\n\n- Add roofStrategy to placement-strategies with ent\n[…]\n) and is clickable to toggle\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>\nCo-authored-by: Wassim SAMAD <wass08@gmail.com>",
          "is_bot": false,
          "headline": "nodes: add modular cabinets and wall trim controls (#461)",
          "author_name": "Sudhir Yadav",
          "author_login": "sudhir9297",
          "committed_at": "2026-07-12T22:33:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7d6879c416fbffe41e55c8fcf482607d009c06a8",
          "body": "…n-north\n\nfix(editor): compass needle follows align-north in 3D-only view",
          "is_bot": false,
          "headline": "Merge pull request #487 from pascalorg/fix/compass-follow-hidden-alig…",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-10T08:22:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cbcc7051739ecdac3c1a47df1a9069bab45a7e12",
          "body": "When the 2D panel is hidden, align-north publishes a single '2d' pose that\nthe camera applies through the echo-suppressed pending-pose path, so no\n'3d' poses ever reach the compass subscription and the needle stayed\nfrozen. Drive the needle with a local rAF exponential decay (same 90ms\ntime constant as the 2D view animation and the camera's effective\nsmoothTime); a live '3d' pose cancels it and takes back ownership.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): animate compass needle on align-north in 3D-only view",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-10T08:15:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5e5b62b09e730e4f25eab481dceef6c58ed34b1e",
          "body": "…s (#484)\n\nTwo readiness fixes surfaced by the first successful headless bake of a\nheavy scene (which exported with 33 items missing):\n\n- The 180-FRAME give-up cap silently assumed display-rate frames. The\n  bake page's timer-driven loop (?disable=draw) runs those frames in\n  ~3.6s — shorter than a \n[…]\nttles\norganically in ~2s and exports the complete artifact; a one-shot 504'd\nitem is now WAITED for through its retry instead of racing the cap.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(viewer): wall-clock scene-ready cap + skip unreachable dirty node…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-10T01:01:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aa30899090103c6966c9d721b086d0bfd302cd1c",
          "body": "With no real frames submitted, Chromium's no-damage scheduler throttles\nrequestAnimationFrame to 1Hz on Linux — measured in the headless bake\nworker: every useFrame system ticked once per second, so a heavy scene\nneeded 300+ seconds of wall time just to run ~300 frames of build work\n(and exceeded th\n[…]\nled on a visible page, so the loop\npacing is deterministic (fps prop) regardless of compositor heuristics.\nNormal rendering paths are untouched.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(viewer): drive the frame loop with a timer when ?disable=draw (#483)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-10T00:25:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bbe0e2b0b52fb3d6d820b96377e4d667b9388e35",
          "body": "…sumers (#482)\n\nThe headless bake worker renders on SwiftShader (CPU), where per-frame\nvertex/draw cost dominates the whole capture — but a bake only reads the\nbuilt scene graph; the pixels are thrown away. `?disable=draw` (same\ndiagnostic-param family as postFx) renders an EMPTY scene each frame\nin\n[…]\nean; the ±13-accessor variance exists\nbetween normal runs too). CPU-only (worker) numbers via the prod-image\ncontainer against a preview deploy.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(viewer): ?disable=draw — skip scene rendering for graph-only con…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-09T23:30:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "352954aafc66180338258bd1765eb0ecc7b0ee13",
          "body": "…tate, duplicate (#481)\n\n* feat(editor): group R/T — keyboard rotate for multi-selections\n\nExtract the rigid rotate/translate math from the group gizmos into\ngroup-transform-shared (rotateGroupPatches / translateGroupPatches) and\nadd a keyboard group-rotate path: R/T on a multi-selection steps the\nw\n[…]\n component that actually draws the line) and\ndrop the dead registry plumbing.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "editor: group manipulation — Photoshop-style multi-selection move, ro…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-09T19:10:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "feeabf4bd3a7a9bfb39b9d8bff5ae241ef996964",
          "body": "…rts clean (#480)\n\n* fix(items): retry failed model loads, settle skipped items, keep exports clean\n\nA transient storage failure (observed: Supabase 504s under the bake page's\n~200-concurrent-request burst) permanently broke an item for the whole\nsession: drei's useGLTF caches the rejected load by U\n[…]\nem on mount so the replacement load\nis awaited by ItemSystem/scene-ready too.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(items): retry failed model loads, settle skipped items, keep expo…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-09T18:50:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5831b7b2346b73b54289e9d40124d8df8c9166d8",
          "body": "editor: smart unit suffix — dim on focus, yield to explicit units",
          "is_bot": false,
          "headline": "Merge pull request #479 from pascalorg/feat/smart-unit-suffix",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-09T14:20:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d4e7be709235f17e1990a0413f3f416ca7436e6",
          "body": "editor: compass sync + fast align-to-north",
          "is_bot": false,
          "headline": "Merge pull request #478 from pascalorg/fix/compass-sync",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-09T14:20:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b4b267a40b453dc1b2903ee4e35bcaa7d150e11",
          "body": "While editing a numeric field, the unit suffix now visually responds to\nthe draft content:\n- Plain number / empty: suffix dims to 40% opacity (signals \"default unit\n  if you commit a bare number\")\n- Explicit unit typed (hint showing): suffix fades to opacity-0 over\n  150ms (the conversion hint provi\n[…]\nso the flex layout doesn't jump.\nThe predicate is simply `hint !== null` — it aligns exactly with\nmeasurementHint's internal PLAIN_NUMBER guard.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): smart unit suffix — dim on focus, yield to explicit units",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-09T14:07:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "58339c64f5bd7cbe4a4a60363f9ef27c52661e54",
          "body": "… scenes (#476)\n\nInstanced plant kinds (trees/grass/flowers) never cleared their dirty\nmarks: FloorElevationSystem deliberately leaves the mark for kinds with\na def.system, expecting that system to clear it after its own work, but\nInstancedKindSystem never participated in the dirty protocol. The mar\n[…]\nbaking Wawa House\nlocally: settle 22.5s -> 11.6s (the remainder is genuine asset\nloading), exported GLB byte-identical with and without the fix.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(plugin-trees): consume dirty marks so scene-ready fires for plant…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-09T11:39:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d4f1053528247468d10f46ba27a845edd2bbf61a",
          "body": "Route all pending-pose cancellations through clearPendingFloorplanNavigationPose()\nso savedSmoothTime is always restored. Add a controlstart listener to catch\nright-click orbit and other pointer drags that weren't handled. Guard the\nrotation-degree ref mirror to prevent React re-renders from clobber\n[…]\nue when the panel is hidden, and add a useLayoutEffect\nto keep the needle DOM in sync. Make the catch-up effect re-run directly on\npanel reopen.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): compass sync review fixes",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-09T11:23:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cb5cfc7e40acbb9cda024041a3cf766d92f2e7af",
          "body": "- Remove CSS transition on compass needle SVG so rotation tracks\n  exactly without rubber-band lag (was transition-transform 150ms)\n- Drive compass needle imperatively via ref when floorplan panel is\n  hidden (3D-only mode), avoiding per-frame React re-renders of the\n  full SVG while keeping the nee\n[…]\nom 0.25s to 0.18s\n  during 2D-origin transitions (SmoothDamp τ≈90ms matches the 2D\n  exponential decay), restoring on completion or cancellation\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): compass sync + fast align-to-north",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-09T11:09:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a477c4ade3b050e69976b0c60614626d2611c736",
          "body": "fix(editor): area readouts + generated names follow the unit toggle; bump lingo to 0.2.0",
          "is_bot": false,
          "headline": "Merge pull request #477 from pascalorg/fix/unit-labels-lingo-0.2",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T20:51:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8476a991f48fc9b24445131f27929c9b19e68f4c",
          "body": "0.2.0 is API-compatible with our usage (parseQuantity, quantity, Kind);\nit adds i18n/locale entrypoints and does not change the symbols we import.\nVerified: @pascal-app/editor and @pascal-app/mcp typecheck, and all 31\nmeasurement tests pass, including the AMBIGUOUS_NUMBER escalate guard.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps): bump @pascal-app/lingo to 0.2.0",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T20:34:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "682c023be19d802dc80ad67e4b4c6dfe52f1e3c1",
          "body": "The metric/imperial preference was already honored by every length input,\nbut two area surfaces were still hardcoded to m²:\n\n- the \"Load build\" import dialog's Floor area stat\n- the auto-generated default names for zones, slabs, and ceilings\n  (e.g. \"Zone (12.3m²)\"), which are live display fallbacks\n[…]\n to\nlib/measurements (with tests) and routes the site-panel Area readout\nthrough them, replacing an inline 10.7639 magic constant.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): area readouts and generated names follow the unit toggle",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T20:34:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fb0b78c091b8e7576fa4238217fcffcc84413562",
          "body": "…T, Set Scale UX (#475)\n\nFix pass over 2D reference-image (guide) handling plus two adjacent repairs:\n\n- North is now world −Z (FLOORPLAN_VIEW_ROTATION_DEG 90 → 0, mirrored in\n  world-grid-snap + mcp README; floorplan-panel de-dupes its local copy).\n  A rotation-0 north-up scan reads upright when th\n[…]\name-array dupes.\n- Editor accepts onLoaderChange so hosts can measure open-to-interactive\n  time (community wires it to a PostHog timing event).\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): floorplan reference pass — north convention, cursors, R/…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-08T18:12:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2cfce3f6b5ca9b9557671ea3912c549d9ef71237",
          "body": "feat: natural-language measurement inputs (UI + MCP tools) via @pascal-app/lingo",
          "is_bot": false,
          "headline": "Merge pull request #472 from pascalorg/feat/lingo-natural-inputs",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T15:08:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ffde5f66ae5ab18a99d08d2a8d141653b2141b4",
          "body": "…the unit toggle\n\nThe property-line vertex X/Z inputs and the Area/Perimeter readout were\nhardcoded to meters. Convert them to feet / ft² when the viewer preference is\nimperial, matching every other length input.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): site-panel property-line coords + area/perimeter follow …",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T15:00:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "69813a6e62c4f5d83e449510d3e194a6ef71b719",
          "body": "SliderControl (which drives the auto-inspector's ~144 fields and most custom\npanels) previously ignored the viewer unit preference and always rendered raw\nmeters with a static \"m\" label, while MetricControl converted to feet — so\ntoggling imperial changed some length inputs and not others. Extract t\n[…]\nto the display unit. For metric and non-length units\n(°, %, in, …) the conversions are the identity, so those paths are unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): honor the metric/imperial toggle in every length input",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T15:00:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "717c2c5c0af0f61543373471ac05292315e78d2a",
          "body": "…ibility, HDR (#473)\n\n* fix(core): apply window schema defaults on scene load\n\nWindows saved before a schema field existed (columnRatios/rowRatios/\nframeThickness/…) loaded with those fields missing; the window mesh\nbuilder reads them unconditionally and threw every frame, crashing the\nviewer on leg\n[…]\not group flag to\nper-frame on the meshes, which now remount on layer toggles.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: bug pass — legacy window crash, plant exports, zone snapping/vis…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-08T14:19:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "af1fe6a34c7a954d4bb455db63d2a58d33141064",
          "body": "…elper\n\nRecords @pascal-app/lingo@^0.1.0 in bun.lock (added to @pascal-app/editor and\n@pascal-app/mcp), so `bun install --frozen-lockfile` in CI resolves it. Also\ndocuments that measurement.ts is intentionally duplicated with the AI-chat copy\nacross the submodule boundary and must be kept in sync.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps): add @pascal-app/lingo to the lockfile; note duplicated h…",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T11:32:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3273aac551b8d3e0a2243c19dbe67720bd199ae2",
          "body": "…rement()\n\nAdversarial-review follow-ups to the lingo measurement() field:\n- Add a `positive` option (strict > 0) and use it for the non-zero dimension\n  params. Swapping z.number().positive() → measurement(..,{min:0}) had started\n  admitting 0 (the core node schemas have no positivity backstop), so\n[…]\nelElevation reverted to z.number() (it's a level ordinal, not meters);\n  radians fields now advertise radian-appropriate examples.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mcp): restore >0 validation and reject ambiguous numbers in measu…",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T11:09:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f66dcd438bef91c4d2c4630bedcd0f08d44ddc35",
          "body": "…app/lingo\n\nMeasurement/angle parameters on the scene tools now accept a bare number OR a\nnatural-language string (\"6 in\", \"180cm\", \"45°\", \"1.57rad\"), canonicalized to\nthe unit the handler already expects (meters for length, radians/degrees for\nangles) with min/max bounds and model-readable errors. \n[…]\nem, create_level, create_story_shell, create_roof,\ncreate_stair_between_levels, create_room, add_door, add_window, photo_to_scene.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mcp): natural-language measurements for tool inputs via @pascal-…",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T10:51:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a5963560b168806ed74a9f8406c5b796e3863eb9",
          "body": "Type any unit into SliderControl / MetricControl fields — \"6ft\", \"180cm\",\n\"1m80\", \"5'11\\\"\", \"72in\", \"45°\", \"1.57rad\" — and it canonicalizes to the\nunit the field already stores (meters / degrees / radians / inches),\nindependent of the metric/imperial display toggle. A live \"= 1.83 m\" hint\npreviews t\n[…]\nser.ts maps each field's `unit` prop to a lingo kind +\ncanonical unit, covering the auto-inspector and every custom panel at once.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): natural-language measurement inputs via @pascal-app/lingo",
          "author_name": "Aymeric Rabot",
          "author_login": "Aymericr",
          "committed_at": "2026-07-08T10:04:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51fddc2d9c520ba2b14e224dd7ae17ce8563792c",
          "body": "…(#469)\n\n* fix(editor): keep snapshot pitch out of preset thumbnail capture\n\nThe capture overlay's snapshot hint and 'Take snapshot' shutter label\nrendered in every capture variant, clashing with the save-as-preset\nflow's own 'Frame your item — click Capture' banner. Gate them on the\nexisting isPres\n[…]\nmpose panel and gallery, where there is no scene selection or tool to\nact on.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: capture-mode polish for studio & presets + pausable render loop …",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-07T21:10:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6a58489b83d489f155da34044b73621c4463a49",
          "body": "WebGPU rejects block-compressed textures whose base dimensions aren't\nmultiples of 4; three's KTX2Loader only warns and transcodes anyway, so a\nbaked GLB carrying one odd-sized user-item texture (e.g. 299x399) poisoned\nevery render pass — endless 'Invalid BindGroup … Invalid CommandBuffer'\nspam. Rou\n[…]\nompressed\nRGBA32 and repackage the pixels as a plain DataTexture (three's WebGPU\nupload path crashes on a CompressedTexture holding rgba8 data).\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(viewer): survive block-misaligned KTX2 textures on WebGPU (#467)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-06T23:39:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6ffb93a39b62539bab32deb7ea2f83ea3115fb2",
          "body": "…er meshes (#466)\n\n- roof-system: replace BoxGeometry placeholders (initial swap + empty-roof\n  merged shell) with a group-less degenerate geometry — a Box's 6 groups\n  against the roof's 4-material array crashed GLTFExporter on every scene\n  with a segment-less roof node (prod: 'reading isShaderMat\n[…]\nips building the SSGI/denoise pipeline entirely; the ?disable=postFx URL\n  flag previously only bypassed it per-frame while still allocating it.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(export): unbreak bakes and STL/OBJ exports on malformed/placehold…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-06T20:07:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9b5e229770a2de785f1e5a9d21ba25320a4c117c",
          "body": "* feat(editor): stage overlay slot, preselectable snapshot crop, pro capture overlay\n\n- Editor/EditorLayoutV2 gain a stageOverlay slot rendered over the canvas\n  but under the viewer toolbar (z-10 < z-20), so hosts can swap in a\n  full-stage surface (e.g. studio gallery) without unmounting the WebGL\n[…]\nerlay initializes its aspect picker from it.\nSnapshotStandardAspect exported.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): stage overlay slot + pro capture overlay for studio (#465)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-06T17:09:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "22af31dea80f5c5fc1648f7d78daca8161092b0e",
          "body": "…vation, cursor-true transfers (#458)\n\n* fix(snapping): show alignment lines in all modes, snap only in lines; north export; R/T hint; grid default\n\n- Alignment guides display in every snapping mode (grid/lines/angles/off);\n  magnetic pull applies only in 'lines'. New isAlignmentGuideActive() predic\n[…]\n latch in the\ncoordinator and the window/door move tools alike.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "editor: snapping overhaul — shared-wall rooms, deterministic slab ele…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-02T20:18:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c071ecad58e20063b2f073045ca2461a0431926",
          "body": "…rs/grass) (#457)\n\n* feat(plugins): trees tracer-bullet plugin + minimal host panel surface\n\nShip one real first-party plugin and only the host surface it forces\ninto existence, proving the plugin contribution paths every future\nplugin (mint.gg generator, Home Assistant, environments, room volume)\nw\n[…]\nTree re-export from the package barrel (no external consumers).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(plugins): plugin contract + first-party Nature pack (trees/flowe…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-07-02T17:45:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bf25af6addc95ad19c27bc418ff7d5f4280bf2fb",
          "body": "* Add roof surface placement support for items\n\nItems (e.g. solar panels) can now be placed on sloped roof surfaces.\nThe placement system computes euler rotation from the roof surface\nnormal so items sit flush on the slope instead of going inside.\n\n- Add roofStrategy to placement-strategies with ent\n[…]\nChain pattern.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>\nCo-authored-by: Wassim SAMAD <wass08@gmail.com>",
          "is_bot": false,
          "headline": "viewer: Fix Dutch roof trim artifacts (#452)",
          "author_name": "Sudhir Yadav",
          "author_login": "sudhir9297",
          "committed_at": "2026-06-30T20:41:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c51e67342115732cc51cfb06f687cd33dcd04b3f",
          "body": "viewer: slow first-person walk/run/jump speeds",
          "is_bot": false,
          "headline": "Merge pull request #451 from pascalorg/feat/slower-viewer-walk-speed",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T16:33:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36132bbcea9a1c2815e6af34fa8a59ed29d0cf70",
          "body": "Walk 4→2 m/s, run 5.5→5 m/s, jump 6→5 (~1.27 m peak). Applied to both\nthe GLB walkthrough controller (viewer) and the editor first-person\ncontrols so the two surfaces stay consistent.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "viewer: slow first-person walk/run/jump speeds",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T16:30:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "08731b5bde869e9ca2753a27ee038cb86e45e44e",
          "body": "fix(editor): wall-item placement & floorplan polish",
          "is_bot": false,
          "headline": "Merge pull request #450 from pascalorg/feat/placement-interaction-polish",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T14:30:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba464ef47e663d665c5d1cbac08e992329413041",
          "body": "Polish pass on the placement/interaction overhaul. Five fixes:\n\n- Item-on-item rotation box: the cursor box held the host-local yaw instead of\n  world yaw, so it diverged from the item by the host's rotation when stacked on\n  another item (fine on the floor). The box now derives world yaw from the\n \n[…]\ne global selected-node handler and the 2D move overlay.\n\nVerified: core/editor/nodes tsc, biome, editor 162/0 + nodes 292/0 tests.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): wall-item placement & floorplan polish",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T14:27:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9084396a82421db4d7dda3f68ab74fcd72c894b9",
          "body": "feat(editor): floorplan export (multi-page PDF, per level)",
          "is_bot": false,
          "headline": "Merge pull request #449 from pascalorg/feat/floorplan-export",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T12:53:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b87b1f999d9dfa65f1c89af727edf9196726b29f",
          "body": "Add a Floorplan group to the settings Export panel alongside the 3D\nmodel exports, with \"Full floorplan\" and \"Structure only\" buttons.\n\nExport re-runs the live registry-driven floorplan pipeline\n(def.floorplan -> FloorplanGeometryRenderer) headlessly with a neutral\nviewState, fits each level to its \n[…]\n real units before\n  svg2pdf (which ignores the hint and would otherwise draw door/window/\n  stair linework as metre-wide strokes)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): floorplan export (multi-page PDF, per level)",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-29T12:49:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a6023356b91d66783ea0824457f5b0aa034ee3d3",
          "body": "fix(doors): bake open-animation clips for every operation door + un-flipped rest pose",
          "is_bot": false,
          "headline": "Merge pull request #444 from pascalorg/fix/bake-door-window-anims",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T20:41:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0313a13dcfafc1818e1e190696bd65a803a1ddd",
          "body": "Fixes the lone biome organizeImports error so the quality gate passes on the\npost-#448 base. Type-check (9/9), biome, and all suites green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(editor): sort imports in glb-export.test.ts after main merge",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T20:36:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "db35af9a0554f46b43e04649e488f94344dfafa4",
          "body": "…anims",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into fix/bake-door-window-…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T20:32:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2dbe4677f47cbc5e538157c82cc3fc42533cd017",
          "body": "…rhaul\n\nPlacement & interaction overhaul: FSM scope spine, per-context snapping, 2D/floorplan perf",
          "is_bot": false,
          "headline": "Merge pull request #448 from pascalorg/feat/placement-interaction-ove…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T20:24:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "43fa2b12532b5ac8cc1f9be394c4fcd6f206d80f",
          "body": "Resolve 7 conflicts keeping our snapping migration + floorplan perf work as\nsource of truth, combined with main's MEP run-continuation / Alt-detach /\nlatch handles. Rebuilt two import blocks the auto-merge silently truncated\n(node-arrow-handles.tsx, duct-fitting/move-tool.tsx).\n\nVerified: tsc clean \n[…]\n/mcp, 451 tests pass,\nbiome clean. Floorplan view-transform re-render storm confirmed pre-existing\n(not introduced by this merge).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge origin/main into feat/placement-interaction-overhaul",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T20:22:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "15d36c12b12e8dcbda791dc0558a7f3aeb6bb663",
          "body": "… chip\n\nTwo zone fixes.\n\nhelper-manager: the contextual HUD only rendered for tools with `def.toolHints`,\nso zone (none) showed no HUD and no snapping chip even though it resolves a snap\ncontext. Render the generic RegisteredToolHelper whenever the tool has hints OR a\nsnap/continuation context; hois\n[…]\nt-bypass and\nits key listeners — Shift now cycles the mode globally. Recorded as migrated in\nthe review skill's known-legacy list.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): zone drafting respects the snapping mode + shows its HUD…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T01:29:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a2f1ef1683ece0b482178259ce5bad8697edec0c",
          "body": "…er-node perf\n\nCapture the durable patterns from the placement-interaction overhaul so reviews\nand new devs don't regress them:\n\n- tools.md: new \"Data-driven live drag\" section — kinds whose geometry is\n  recomputed from fields (wall/opening/endpoint) preview via useLiveNodeOverrides\n  (merged by ge\n[…]\ns.\n- review SKILL.md: matching blockers in §C (data-driven drag / no per-tick store\n  write) and §D (per-node list subscriptions).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(architecture): codify live-overrides drag protocol + floorplan p…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T01:19:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dc468a084b2ec6718543e00387356303d0ba61c7",
          "body": "The grid only appeared while a ghost was in flight (moving node / placing scope /\narmed GLB item), so a merely-armed draft tool (wall / slab / fence / ceiling /\nzone / column / MEP) showed no lattice. Gate visibility on isGridSnapActive()\nalone — it already derives the snap context from the interact\n[…]\nno surface; the grid's horizontal branch already falls back\nto the active level floor, with the reveal patch following the cursor.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): show placement grid for any armed grid-mode tool",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T01:05:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "81c5b2d22e1eac45e23e967d8fb25a3e2e71cec9",
          "body": "The footprint polygon uses `rotateVec` (R(-angle)) but the sprite was drawn via\nSVG `rotate(+angle)`, so image and box counter-rotated and diverged by 2x the\nitem's rotation in the 2D floorplan. Negate the image rotation so the sprite\ntracks its box (and the 3D orientation). Scoped to items — the only emitter of\nthe `image` floorplan geometry kind.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(nodes): match item floorplan sprite rotation to its footprint box",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T00:49:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "03284553aad7f00de74d8d1bdcf4d11a6157126d",
          "body": "…egistry\n\nIn split view, dragging any node re-rendered ALL ~150 per-node\nInteractiveGeometry instances every tick (profiler: InteractiveGeometry ×3192),\nbecause FloorplanRegistryLayer subscribed to the whole useLiveTransforms /\nuseLiveNodeOverrides maps and the per-node component wasn't memoized.\n\nE\n[…]\nerved verbatim.\n\nAn item move now re-renders only its own entry; a wall drag only the moving wall\nplus its linked-corner siblings.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(editor): per-node memo + own-slice subscriptions for floorplan r…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T00:47:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5f603e83c412a71e2b83106929f75cda3ad65ca0",
          "body": "… co-firing\n\nTwo fixes to the wall-endpoint reshape interaction.\n\nselection-manager: a node:click is synthesized on R3F pointer-up, so an endpoint\nhandle that sits on the wall body lets the wall mesh (raycast-hit behind it from\na 3D angle) emit its own click on the same release — selecting the wall \n[…]\nursor; the\nnext click after a move commits) exactly like a press-drag — both engage\nidentically. Drops the now-dead hasDraggedRef.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): unify wall-endpoint move activation; stop wall-move from…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-28T00:08:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "eeadec11a7cf84a2f548193b4769c94ec9f36f96",
          "body": "…ve overrides\n\nTwo changes from the split-view / wall-endpoint perf + UX pass.\n\nfloorplan-panel: render the heavy 2D <svg> scene only when the panel is visible\n(`isFloorplanOpen`, i.e. viewMode !== '3d'). The panel stays mounted in 3D\n(display:none) to keep the portalled compass + viewport state war\n[…]\nows\nevery endpoint-tool release so it can't fall through to the wall body and arm\nthe wall move tool (no-drag tap or post-commit).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf+fix(editor): gate 2D scene in 3D mode; wall-endpoint move via li…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T23:39:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b384bc817867eba4a31fc5a447ba2f04b83d3240",
          "body": "Camera-zoom hitch: the FloorplanPanel stays mounted (display:none in 3D mode),\nso its navigation-pose subscriber fired every camera onUpdate. During zoom the\nview-width changes continuously, so the epsilon guard never short-circuited and\n`syncFloorplanViewportToNavigationPose` ran each frame → setVi\n[…]\nortaled\nto the always-visible viewer area and still receives the pose; only the panel's\nown viewport sync is skipped while hidden.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(editor): skip floorplan viewport sync while the 2D panel is hidden",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T21:34:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bbe5b9a8eb06263aff1ee723284b8180bc52c522",
          "body": "…onger cancels camera orbit\n\nBUG 1 — wall-attached furniture facing. The coordinator drew its own inline\nfacing triangle and published the wall grid normal from the cursor ghost's own\nyaw, which is the symmetric-wireframe yaw — π off the item's true facing for a\nwall (and a different frame for a roo\n[…]\n0ms (a quick stationary click); a longer/further press is an orbit and\nis left alone. contextmenu now only suppresses the OS menu.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(placement): wall-item facing via useFacingPose + right-click no l…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T20:59:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8cc6c41b5168864d888b29ba9554dbb81f17dad3",
          "body": "Validated live by Wassim. The click-to-move branch set `clickHandledRef = true`\nthen returned early, skipping the 50ms reset the normal select path runs at the\nend. The flag stayed true, so `onGridClick`'s guard silently blocked every\nempty-click deselect until the next normal select cleared it. Schedule the reset\nright after the flag is set so EVERY branch (incl. the early return) clears it.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): unstick empty-click deselect after click-to-move",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T20:09:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5933a00247ca3e4ca6a8f8c729be17db69f568e8",
          "body": "Validated live by Wassim.\n\n- Wall grid is anchored to the wall PLANE (its foot), not the moving ghost, so\n  sliding a door/window only moves the reveal patch — the lattice stays a fixed\n  snap reference instead of \"following\" the opening.\n- DoubleSide so the lattice renders when an opening is handle\n[…]\n editor-side \"Show Grid\" setting: the 3D grid is now purely a\n  placement aid (shown only while placing/moving in grid-snap mode).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(editor): placement grid — wall-anchored, perf, first-frame wall seed",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T20:08:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "67a558a883c6de34e00f32d1fe3db3bef9465348",
          "body": "…verlay\n\nDoor and window are placed via preset and moved with a bespoke wall-bound\n`move-tool` (affordanceTools.move), not the draw tool — so the previous inline\ntriangle never showed for the paths actually used. Migrate both:\n\n- move-tool (move + preset, the community path): publish the on-wall gho\n[…]\nits only consumer, via relative import). The unified overlay now covers every\nplacement/move path: items, column/shelf, stair, and door/window.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): route door/window facing triangle through the unified o…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T02:12:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "68e5c6ca67d9e2b77bd002f28cb9ff892cacee04",
          "body": "…de renderer\n\nEvery placement and move path now publishes its ghost pose to a single\n`useFacingPose` store, drawn by one editor-side `<FacingPoseIndicator>` overlay,\ninstead of each path drawing its own triangle (which left the nodes-package and\nPlacementBox paths invisible):\n\n- column/shelf presets\n[…]\nnuation), grid surface (item #8), and\nHUD work. Door/window still render their own legacy inline triangle and are\nmigrated to the overlay next.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(editor): unify placement/move facing triangle into one editor-si…",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-27T01:48:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "61f3921a8325bbb55a49dd3f2a02e9a28ef623ba",
          "body": "feat(viewer): walkthrough FOV 60° + refresh ceiling-fan model",
          "is_bot": false,
          "headline": "Merge pull request #445 from pascalorg/polish/viewer-baking",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-26T19:58:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70acf894d167dd8ea543fb2831de96abfeca39cd",
          "body": "The walkthrough rode the default 50° orbit camera, which feels cramped on\nfoot. Both walkthrough controllers (baked GlbWalkthroughController and the\nparametric WalkthroughControls fallback) now set a shared WALKTHROUGH_FOV = 60\non enter and restore the prior FOV on exit, leaving orbit framing untouched.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(viewer): widen first-person walkthrough FOV to 60°",
          "author_name": "Wassim SAMAD",
          "author_login": "wass08",
          "committed_at": "2026-06-26T19:51:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 13,
      "commits_last_year": 1216,
      "latest_release_at": "2026-06-10T03:17:29Z",
      "latest_release_tag": "v0.9.1",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 28,
      "days_since_latest_release": 42,
      "mean_days_between_releases": 7.9
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 62,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@pascal-app/mcp",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "mcp",
            "model-context-protocol",
            "pascal",
            "3d",
            "building",
            "editor",
            "ai"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/mcp",
          "is_deprecated": false,
          "latest_version": "0.3.2",
          "repository_url": "https://github.com/pascalorg/editor",
          "versions_count": 4,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 314,
          "first_published_at": "2026-05-10T00:41:37.661000Z",
          "latest_published_at": "2026-07-17T17:11:22.823000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@pascal-app/core",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "3d",
            "building",
            "editor",
            "architecture",
            "webgpu",
            "three.js"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/core",
          "is_deprecated": false,
          "latest_version": "0.9.2",
          "repository_url": "https://github.com/pascalorg/editor",
          "versions_count": 24,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 16291,
          "first_published_at": "2026-02-03T23:33:37.578000Z",
          "latest_published_at": "2026-07-17T17:10:15.302000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@pascal-app/nodes",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "pascal",
            "3d",
            "editor",
            "node-registry"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/nodes",
          "is_deprecated": false,
          "latest_version": "0.1.1",
          "repository_url": "https://github.com/pascalorg/editor",
          "versions_count": 1,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 117,
          "first_published_at": "2026-07-17T17:11:12.329000Z",
          "latest_published_at": "2026-07-17T17:11:13.755000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@pascal-app/editor",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": null,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/editor",
          "is_deprecated": false,
          "latest_version": "0.9.2",
          "repository_url": null,
          "versions_count": 7,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 1533,
          "first_published_at": "2026-04-07T23:24:20.251000Z",
          "latest_published_at": "2026-07-17T17:10:30.148000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@pascal-app/viewer",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "3d",
            "building",
            "editor",
            "viewer",
            "architecture",
            "webgpu",
            "three.js",
            "react-three-fiber"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/viewer",
          "is_deprecated": false,
          "latest_version": "0.9.2",
          "repository_url": "https://github.com/pascalorg/editor",
          "versions_count": 26,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 5107,
          "first_published_at": "2025-12-31T00:44:13.366000Z",
          "latest_published_at": "2026-07-17T17:10:26.351000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@pascal-app/ifc-converter",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@pascal-app/ifc-converter",
          "is_deprecated": false,
          "latest_version": "0.1.2",
          "repository_url": "https://github.com/pascalorg/editor",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 2,
          "monthly_downloads": 303,
          "first_published_at": "2026-05-27T18:48:15.277000Z",
          "latest_published_at": "2026-07-17T17:11:29.529000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 2392,
      "stars": 17533,
      "watchers": 103,
      "fork_history": {
        "days": [
          {
            "date": "2026-04-14",
            "count": 50
          },
          {
            "date": "2026-04-15",
            "count": 75
          },
          {
            "date": "2026-04-16",
            "count": 44
          },
          {
            "date": "2026-04-17",
            "count": 16
          },
          {
            "date": "2026-04-18",
            "count": 19
          },
          {
            "date": "2026-04-19",
            "count": 36
          },
          {
            "date": "2026-04-20",
            "count": 48
          },
          {
            "date": "2026-04-21",
            "count": 29
          },
          {
            "date": "2026-04-22",
            "count": 20
          },
          {
            "date": "2026-04-23",
            "count": 21
          },
          {
            "date": "2026-04-24",
            "count": 9
          },
          {
            "date": "2026-04-25",
            "count": 12
          },
          {
            "date": "2026-04-26",
            "count": 21
          },
          {
            "date": "2026-04-27",
            "count": 35
          },
          {
            "date": "2026-04-28",
            "count": 15
          },
          {
            "date": "2026-04-29",
            "count": 22
          },
          {
            "date": "2026-04-30",
            "count": 11
          },
          {
            "date": "2026-05-01",
            "count": 11
          },
          {
            "date": "2026-05-02",
            "count": 6
          },
          {
            "date": "2026-05-03",
            "count": 12
          },
          {
            "date": "2026-05-04",
            "count": 23
          },
          {
            "date": "2026-05-05",
            "count": 9
          },
          {
            "date": "2026-05-06",
            "count": 6
          },
          {
            "date": "2026-05-07",
            "count": 11
          },
          {
            "date": "2026-05-08",
            "count": 7
          },
          {
            "date": "2026-05-09",
            "count": 1
          },
          {
            "date": "2026-05-10",
            "count": 3
          },
          {
            "date": "2026-05-11",
            "count": 5
          },
          {
            "date": "2026-05-12",
            "count": 5
          },
          {
            "date": "2026-05-13",
            "count": 6
          },
          {
            "date": "2026-05-14",
            "count": 9
          },
          {
            "date": "2026-05-15",
            "count": 6
          },
          {
            "date": "2026-05-16",
            "count": 6
          },
          {
            "date": "2026-05-17",
            "count": 6
          },
          {
            "date": "2026-05-18",
            "count": 22
          },
          {
            "date": "2026-05-19",
            "count": 13
          },
          {
            "date": "2026-05-20",
            "count": 14
          },
          {
            "date": "2026-05-21",
            "count": 12
          },
          {
            "date": "2026-05-22",
            "count": 5
          },
          {
            "date": "2026-05-23",
            "count": 3
          },
          {
            "date": "2026-05-24",
            "count": 4
          },
          {
            "date": "2026-05-25",
            "count": 13
          },
          {
            "date": "2026-05-26",
            "count": 8
          },
          {
            "date": "2026-05-27",
            "count": 2
          },
          {
            "date": "2026-05-28",
            "count": 8
          },
          {
            "date": "2026-05-29",
            "count": 6
          },
          {
            "date": "2026-05-30",
            "count": 6
          },
          {
            "date": "2026-05-31",
            "count": 5
          },
          {
            "date": "2026-06-01",
            "count": 6
          },
          {
            "date": "2026-06-02",
            "count": 5
          },
          {
            "date": "2026-06-03",
            "count": 2
          },
          {
            "date": "2026-06-04",
            "count": 9
          },
          {
            "date": "2026-06-05",
            "count": 6
          },
          {
            "date": "2026-06-06",
            "count": 1
          },
          {
            "date": "2026-06-07",
            "count": 2
          },
          {
            "date": "2026-06-08",
            "count": 3
          },
          {
            "date": "2026-06-09",
            "count": 12
          },
          {
            "date": "2026-06-10",
            "count": 17
          },
          {
            "date": "2026-06-11",
            "count": 13
          },
          {
            "date": "2026-06-12",
            "count": 11
          },
          {
            "date": "2026-06-13",
            "count": 3
          },
          {
            "date": "2026-06-14",
            "count": 15
          },
          {
            "date": "2026-06-15",
            "count": 5
          },
          {
            "date": "2026-06-16",
            "count": 3
          },
          {
            "date": "2026-06-17",
            "count": 1
          },
          {
            "date": "2026-06-18",
            "count": 2
          },
          {
            "date": "2026-06-19",
            "count": 5
          },
          {
            "date": "2026-06-20",
            "count": 1
          },
          {
            "date": "2026-06-21",
            "count": 7
          },
          {
            "date": "2026-06-22",
            "count": 2
          },
          {
            "date": "2026-06-23",
            "count": 9
          },
          {
            "date": "2026-06-24",
            "count": 8
          },
          {
            "date": "2026-06-25",
            "count": 3
          },
          {
            "date": "2026-06-26",
            "count": 7
          },
          {
            "date": "2026-06-27",
            "count": 1
          },
          {
            "date": "2026-06-28",
            "count": 2
          },
          {
            "date": "2026-06-29",
            "count": 2
          },
          {
            "date": "2026-06-30",
            "count": 2
          },
          {
            "date": "2026-07-01",
            "count": 3
          },
          {
            "date": "2026-07-02",
            "count": 7
          },
          {
            "date": "2026-07-03",
            "count": 3
          },
          {
            "date": "2026-07-04",
            "count": 1
          },
          {
            "date": "2026-07-05",
            "count": 3
          },
          {
            "date": "2026-07-06",
            "count": 15
          },
          {
            "date": "2026-07-07",
            "count": 1
          },
          {
            "date": "2026-07-08",
            "count": 8
          },
          {
            "date": "2026-07-09",
            "count": 8
          },
          {
            "date": "2026-07-10",
            "count": 8
          },
          {
            "date": "2026-07-11",
            "count": 5
          },
          {
            "date": "2026-07-12",
            "count": 7
          },
          {
            "date": "2026-07-13",
            "count": 2
          },
          {
            "date": "2026-07-14",
            "count": 5
          },
          {
            "date": "2026-07-15",
            "count": 4
          },
          {
            "date": "2026-07-16",
            "count": 2
          },
          {
            "date": "2026-07-17",
            "count": 2
          },
          {
            "date": "2026-07-18",
            "count": 6
          },
          {
            "date": "2026-07-19",
            "count": 4
          },
          {
            "date": "2026-07-20",
            "count": 3
          },
          {
            "date": "2026-07-22",
            "count": 2
          }
        ],
        "complete": false,
        "collected": 1000,
        "total_forks": 2392
      },
      "star_history": null,
      "open_issues_and_prs": 21
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "demos",
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": true,
      "typecheck_configs": [
        "apps/editor/tsconfig.json",
        "apps/ifc-converter/tsconfig.json",
        "packages/core/tsconfig.json",
        "packages/editor/tsconfig.json",
        "packages/ifc-converter/tsconfig.json",
        "packages/mcp/tsconfig.json",
        "packages/nodes/tsconfig.json",
        "packages/ui/tsconfig.json",
        "packages/viewer/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 391002,
      "source_files_sampled": 1595,
      "oversized_source_files": 22,
      "agent_instruction_files": [
        ".github/copilot-instructions.md",
        "AGENTS.md",
        "CLAUDE.md",
        "GEMINI.md"
      ],
      "agent_instruction_max_bytes": 3613
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@iconify/react",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.0.2"
        },
        {
          "name": "@number-flow/react",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.6.0"
        },
        {
          "name": "@pascal-app/core",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/editor",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/mcp",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/nodes",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/plugin-trees",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "github:pascalorg/plugin-trees#56d978cd9b409b716207b3f3d269455d3cd6f067"
        },
        {
          "name": "@pascal-app/viewer",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@radix-ui/react-tooltip",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.8"
        },
        {
          "name": "@react-three/drei",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.7.7"
        },
        {
          "name": "@react-three/fiber",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.5.0"
        },
        {
          "name": "@tailwindcss/postcss",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.2.1"
        },
        {
          "name": "clsx",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "geist",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.0"
        },
        {
          "name": "lucide-react",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.0"
        },
        {
          "name": "next",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "16.2.9"
        },
        {
          "name": "postcss",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.5.6"
        },
        {
          "name": "react",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.4"
        },
        {
          "name": "react-dom",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.4"
        },
        {
          "name": "tailwind-merge",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "tailwindcss",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.2.1"
        },
        {
          "name": "three",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.185.0"
        },
        {
          "name": "zod",
          "manifest": "apps/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.5"
        },
        {
          "name": "@pascal-app/core",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/ifc-converter",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/nodes",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "@pascal-app/viewer",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "lucide-react",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.0"
        },
        {
          "name": "@react-three/drei",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.7.7"
        },
        {
          "name": "@react-three/fiber",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.5.0"
        },
        {
          "name": "@tailwindcss/postcss",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.2.1"
        },
        {
          "name": "clsx",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "next",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "16.2.9"
        },
        {
          "name": "postcss",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.5.6"
        },
        {
          "name": "react",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.4"
        },
        {
          "name": "react-dom",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.4"
        },
        {
          "name": "tailwind-merge",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "tailwindcss",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.2.1"
        },
        {
          "name": "three",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.185.0"
        },
        {
          "name": "web-ifc",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.0.77"
        },
        {
          "name": "zod",
          "manifest": "apps/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.5"
        },
        {
          "name": "dedent",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.1"
        },
        {
          "name": "idb-keyval",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.2.2"
        },
        {
          "name": "mitt",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.1"
        },
        {
          "name": "nanoid",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.1.6"
        },
        {
          "name": "zod",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.5"
        },
        {
          "name": "zundo",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.3.0"
        },
        {
          "name": "zustand",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5"
        },
        {
          "name": "@dnd-kit/core",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.3.1"
        },
        {
          "name": "@dnd-kit/sortable",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.0.0"
        },
        {
          "name": "@dnd-kit/utilities",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.2.2"
        },
        {
          "name": "@iconify/react",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.0.2"
        },
        {
          "name": "@number-flow/react",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.6.0"
        },
        {
          "name": "@pascal-app/lingo",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.2.0"
        },
        {
          "name": "@radix-ui/react-alert-dialog",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.15"
        },
        {
          "name": "@radix-ui/react-context-menu",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.2.16"
        },
        {
          "name": "@radix-ui/react-dialog",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.15"
        },
        {
          "name": "@radix-ui/react-dropdown-menu",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.16"
        },
        {
          "name": "@radix-ui/react-popover",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.15"
        },
        {
          "name": "@radix-ui/react-select",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.2.6"
        },
        {
          "name": "@radix-ui/react-separator",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.8"
        },
        {
          "name": "@radix-ui/react-slider",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.3.6"
        },
        {
          "name": "@radix-ui/react-slot",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.4"
        },
        {
          "name": "@radix-ui/react-switch",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.6"
        },
        {
          "name": "@radix-ui/react-tabs",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.13"
        },
        {
          "name": "@radix-ui/react-tooltip",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.8"
        },
        {
          "name": "@visual-json/react",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.4.0"
        },
        {
          "name": "blob-stream",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.3"
        },
        {
          "name": "class-variance-authority",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.7.1"
        },
        {
          "name": "clsx",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "cmdk",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.1"
        },
        {
          "name": "howler",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.2.4"
        },
        {
          "name": "lucide-react",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.0"
        },
        {
          "name": "mitt",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.1"
        },
        {
          "name": "motion",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.34.3"
        },
        {
          "name": "nanoid",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.1.6"
        },
        {
          "name": "pdfkit",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.19.1"
        },
        {
          "name": "tailwind-merge",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "three-mesh-bvh",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "~0.9.8"
        },
        {
          "name": "zod",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.6"
        },
        {
          "name": "zustand",
          "manifest": "packages/editor/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.0.11"
        },
        {
          "name": "@pascal-app/core",
          "manifest": "packages/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "*"
        },
        {
          "name": "nanoid",
          "manifest": "packages/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.1.6"
        },
        {
          "name": "web-ifc",
          "manifest": "packages/ifc-converter/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.0.77"
        },
        {
          "name": "@modelcontextprotocol/sdk",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.29.0"
        },
        {
          "name": "@pascal-app/lingo",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.2.0"
        },
        {
          "name": "zod",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.5"
        },
        {
          "name": "react",
          "manifest": "packages/ui/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.0"
        },
        {
          "name": "react-dom",
          "manifest": "packages/ui/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.2.0"
        },
        {
          "name": "three-bvh-csg",
          "manifest": "packages/viewer/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.0.18"
        },
        {
          "name": "three-mesh-bvh",
          "manifest": "packages/viewer/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.9.8"
        },
        {
          "name": "zustand",
          "manifest": "packages/viewer/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5"
        }
      ],
      "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": 8,
        "merged_prs": 364,
        "open_issues": 13,
        "closed_ratio": 0.806,
        "closed_issues": 54,
        "closed_unmerged_prs": 72
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "wass08",
          "commits": 722,
          "avatar_url": "https://avatars.githubusercontent.com/u/6551176?v=4"
        },
        {
          "type": "User",
          "login": "sudhir9297",
          "commits": 173,
          "avatar_url": "https://avatars.githubusercontent.com/u/19578447?v=4"
        },
        {
          "type": "User",
          "login": "Aymericr",
          "commits": 161,
          "avatar_url": "https://avatars.githubusercontent.com/u/4444492?v=4"
        },
        {
          "type": "User",
          "login": "open-pascal",
          "commits": 51,
          "avatar_url": "https://avatars.githubusercontent.com/u/271033448?v=4"
        },
        {
          "type": "User",
          "login": "anton-pascal",
          "commits": 38,
          "avatar_url": "https://avatars.githubusercontent.com/u/257628774?v=4"
        },
        {
          "type": "User",
          "login": "AdrianPerez3",
          "commits": 23,
          "avatar_url": "https://avatars.githubusercontent.com/u/70107702?v=4"
        },
        {
          "type": "User",
          "login": "ruok-dev",
          "commits": 8,
          "avatar_url": "https://avatars.githubusercontent.com/u/251900461?v=4"
        },
        {
          "type": "User",
          "login": "WawaSenseiDev",
          "commits": 6,
          "avatar_url": "https://avatars.githubusercontent.com/u/232127047?v=4"
        },
        {
          "type": "User",
          "login": "kleenkanteen",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/67878058?v=4"
        },
        {
          "type": "User",
          "login": "developeratexample",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/14004359?v=4"
        }
      ],
      "contributors_sampled": 25,
      "top_contributor_share": 0.597
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "mcp-ci.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "eslint.config.mjs"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 9,
            "reason": "25 out of 26 merged PRs checked by a CI test -- score normalized to 9",
            "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": 2,
            "reason": "Found 6/27 approved changesets -- score normalized to 2",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 4 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 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": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": null,
            "reason": "internal error: vulnerabilitiesClient.ListUnfixedVulnerabilities: osvscanner.DoScan: client error: status=\"400 Bad Request\" body={\"code\":3,\"message\":\"error in query at index 192: rpc error: code = InvalidArgument desc = invalid hash\"}",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "26c9e17fed2b2c8416c90036f1f5d8636792a523",
        "ran_at": "2026-07-23T00:42:29Z",
        "aggregate_score": 4.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T18:53:33Z",
      "oldest_open_prs": [
        {
          "number": 268,
          "created_at": "2026-04-21T10:39:43Z",
          "last_comment_at": "2026-07-19T15:58:43Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 312,
          "created_at": "2026-05-15T23:47:17Z",
          "last_comment_at": "2026-07-20T14:47:15Z",
          "last_comment_author": "mvanhorn"
        },
        {
          "number": 455,
          "created_at": "2026-07-01T04:07:37Z",
          "last_comment_at": "2026-07-21T04:05:27Z",
          "last_comment_author": "anton-pascal"
        },
        {
          "number": 468,
          "created_at": "2026-07-07T04:11:28Z",
          "last_comment_at": "2026-07-19T15:56:27Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 488,
          "created_at": "2026-07-11T00:23:06Z",
          "last_comment_at": "2026-07-19T15:56:28Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 490,
          "created_at": "2026-07-11T15:09:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 524,
          "created_at": "2026-07-21T04:08:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 530,
          "created_at": "2026-07-22T04:07:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-22T18:51:35Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 154,
          "created_at": "2026-03-23T19:38:44Z",
          "last_comment_at": "2026-03-28T22:45:04Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 158,
          "created_at": "2026-03-24T07:23:39Z",
          "last_comment_at": "2026-05-16T08:13:13Z",
          "last_comment_author": "KongNan"
        },
        {
          "number": 174,
          "created_at": "2026-03-25T15:53:15Z",
          "last_comment_at": "2026-04-13T17:26:06Z",
          "last_comment_author": "gr2m"
        },
        {
          "number": 209,
          "created_at": "2026-04-04T12:05:24Z",
          "last_comment_at": "2026-05-15T23:47:33Z",
          "last_comment_author": "mvanhorn"
        },
        {
          "number": 227,
          "created_at": "2026-04-14T02:55:38Z",
          "last_comment_at": "2026-07-19T16:24:23Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 260,
          "created_at": "2026-04-18T16:44:30Z",
          "last_comment_at": "2026-04-21T05:41:50Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 288,
          "created_at": "2026-05-02T17:24:08Z",
          "last_comment_at": "2026-07-19T16:28:39Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 308,
          "created_at": "2026-05-14T14:20:50Z",
          "last_comment_at": "2026-07-19T16:24:23Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 362,
          "created_at": "2026-06-02T19:14:22Z",
          "last_comment_at": "2026-07-19T15:41:40Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 374,
          "created_at": "2026-06-04T19:20:59Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 474,
          "created_at": "2026-07-08T15:35:16Z",
          "last_comment_at": "2026-07-19T16:28:39Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 492,
          "created_at": "2026-07-13T10:01:57Z",
          "last_comment_at": "2026-07-19T16:28:39Z",
          "last_comment_author": "Aymericr"
        },
        {
          "number": 509,
          "created_at": "2026-07-18T07:44:51Z",
          "last_comment_at": "2026-07-19T16:41:40Z",
          "last_comment_author": "Aymericr"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/pascalorg/editor",
    "host": "github.com",
    "name": "editor",
    "owner": "pascalorg"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 74,
      "inputs": {
        "security": 43,
        "vitality": 90,
        "community": 84,
        "governance": 65,
        "engineering": 81
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 90,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 1216,
              "human_commit_share": 0.99,
              "days_since_last_push": 0,
              "active_weeks_last_year": 28
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "28/52 weeks with commits",
                "points": 19.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 28
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1216 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1216
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 13,
              "latest_release_tag": "v0.9.1",
              "releases_from_tags": false,
              "days_since_latest_release": 42,
              "mean_days_between_releases": 7.9
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "13 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 42 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 42
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~7.9 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 7.9
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "good",
        "name": "Community & Adoption",
        "value": 84,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "excellent",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 96,
            "inputs": {
              "forks": 2392,
              "stars": 17533,
              "watchers": 103,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "17,533 stars",
                "points": 60,
                "status": "met",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 17533
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "2,392 forks",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 2392
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "103 watchers",
                "points": 11.2,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 103
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "good",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 73,
            "inputs": {
              "packages": [
                "@pascal-app/mcp",
                "@pascal-app/core",
                "@pascal-app/nodes",
                "@pascal-app/editor",
                "@pascal-app/viewer",
                "@pascal-app/ifc-converter"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 23665
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "23,665 downloads/month across npm",
                "points": 58.3,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 23665,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 65,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 42,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 25,
              "top_contributor_share": 0.597
            },
            "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 60% of commits",
                "points": 9.1,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 60
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "25 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 25
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 73,
            "inputs": {
              "merged_prs": 364,
              "open_issues": 13,
              "closed_issues": 54,
              "issue_closed_ratio": 0.806,
              "closed_unmerged_prs": 72
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "81% of issues closed",
                "points": 37.7,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 81
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "364/436 decided PRs merged",
                "points": 31.9,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 364,
                      "decided": 436
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 6/27 approved changesets -- score normalized to 2",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "followers": 273,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "pascalorg",
              "public_repos": 4,
              "account_age_days": 418
            },
            "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": "273 followers of pascalorg",
                "points": 17.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 273,
                      "login": "pascalorg"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "4 public repos, account ~1 yr old",
                "points": 7.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 4
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 1
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@pascal-app/mcp",
                "@pascal-app/core",
                "@pascal-app/nodes",
                "@pascal-app/editor",
                "@pascal-app/viewer",
                "@pascal-app/ifc-converter"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "6 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 6,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "26 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 26
                    }
                  }
                ],
                "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": 81,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 82,
            "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": "eslint.config.mjs",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "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": "25 out of 26 merged PRs checked by a CI test -- score normalized to 9",
                "points": 18,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": "https://editor.pascal.app",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://editor.pascal.app",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 43,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases, Vulnerabilities. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases",
                    "vulnerabilities"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 43,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 4.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "25 out of 26 merged PRs checked by a CI test -- score normalized to 9",
                "points": 2.2,
                "status": "partial",
                "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 6/27 approved changesets -- score normalized to 2",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 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 not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "internal error: vulnerabilitiesClient.ListUnfixedVulnerabilities: osvscanner.DoScan: client error: status=\"400 Bad Request\" body={\"code\":3,\"message\":\"error in query at index 192: rpc error: code = InvalidArgument desc = invalid hash\"}",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": 6
            },
            "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": 75,
        "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.99,
              "agent_instruction_files": [
                ".github/copilot-instructions.md",
                "AGENTS.md",
                "CLAUDE.md",
                "GEMINI.md"
              ],
              "agent_instruction_max_bytes": 3613
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": ".github/copilot-instructions.md, AGENTS.md, CLAUDE.md, GEMINI.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".github/copilot-instructions.md, 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": "98 of 99 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 99
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": true,
              "has_linter_config": true,
              "typecheck_configs": [
                "apps/editor/tsconfig.json",
                "apps/ifc-converter/tsconfig.json",
                "packages/core/tsconfig.json",
                "packages/editor/tsconfig.json",
                "packages/ifc-converter/tsconfig.json",
                "packages/mcp/tsconfig.json",
                "packages/nodes/tsconfig.json",
                "packages/ui/tsconfig.json",
                "packages/viewer/tsconfig.json"
              ],
              "agent_commit_share": 0.64,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": "eslint.config.mjs",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "apps/editor/tsconfig.json, apps/ifc-converter/tsconfig.json, packages/core/tsconfig.json, packages/editor/tsconfig.json, packages/ifc-converter/tsconfig.json, packages/mcp/tsconfig.json, packages/nodes/tsconfig.json, packages/ui/tsconfig.json, packages/viewer/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "apps/editor/tsconfig.json, apps/ifc-converter/tsconfig.json, packages/core/tsconfig.json, packages/editor/tsconfig.json, packages/ifc-converter/tsconfig.json, packages/mcp/tsconfig.json, packages/nodes/tsconfig.json, packages/ui/tsconfig.json, packages/viewer/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "devcontainer",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "devcontainer"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "64 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 64,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 391002,
              "source_files_sampled": 1595,
              "oversized_source_files": 22
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "22/1595 source files over 60KB",
                "points": 54.2,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 1595,
                      "oversized": 22
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "demos",
                "examples"
              ],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "demos, examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "demos, examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index npm:@pascal-app/editor@0.9.2; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T00:43:00.332590Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/p/pascalorg/editor.svg",
  "full_name": "pascalorg/editor",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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