Звіт у форматі JSON машиночитний
{
"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"
}