diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3923979..4a964c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,3 +33,6 @@ jobs: BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: npm run ci:validate-reports + + - name: Check October reports render without JavaScript and on phones + run: npm run ci:render-october diff --git a/package.json b/package.json index bd625e1..2bf786b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "description": "CI validation tooling for hyperide.github.io reports (no site build step — this is a static Pages site).", "type": "module", "scripts": { - "ci:validate-reports": "node scripts/ci/validate-reports.mjs" + "ci:validate-reports": "node scripts/ci/validate-reports.mjs", + "ci:render-october": "node scripts/ci/check-october-render.mjs" }, "devDependencies": { "playwright": "^1.61.0" diff --git a/reports/2026-10-own-results-evidence.json b/reports/2026-10-own-results-evidence.json index 1a2f902..b850bd6 100644 --- a/reports/2026-10-own-results-evidence.json +++ b/reports/2026-10-own-results-evidence.json @@ -1,520 +1,3182 @@ { - "verifiedAt": "2026-11-05", + "verifiedAt": "2026-11-06", "authors": [ { "account": "alex-mextner", "displayName": "Alex Ultra", - "reportByline": "Ultra / Mextner" + "reportByline": "Ultra / Mextner", + "aliasOpenedFrom": "smoothbricker", + "aliasRule": "credited only where every commit is authored by Alex Ultra" } ], "reports": { "hyper-2026-10": [ + { + "repo": "hyperide/hyper-saas", + "pr": 810, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 7 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-14T18:39:58Z", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "url": "https://github.com/hyperide/hyper-saas/pull/810", + "changedFiles": 68, + "additions": 16876, + "deletions": 215, + "group": "git-push" + }, { "repo": "hyperide/hyper-saas", "pr": 825, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-16T01:22:33Z", "mergeSha": "b0c3a5123add28644d0da367c0e808c7b7e6dd3d", - "url": "https://github.com/hyperide/hyper-saas/pull/825" + "url": "https://github.com/hyperide/hyper-saas/pull/825", + "changedFiles": 3, + "additions": 27, + "deletions": 3, + "group": "extension-release" }, { "repo": "hyperide/hyper-saas", "pr": 837, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-30T13:15:07Z", "mergeSha": "ecd0b8f1b0bf8921f740e76b20337d1a0bc9faac", - "url": "https://github.com/hyperide/hyper-saas/pull/837" - }, - { - "repo": "hyperide/hyper-saas", - "pr": 810, - "author": "alex-mextner", - "state": "MERGED", - "mergedAt": "2026-10-14T18:39:58Z", - "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", - "url": "https://github.com/hyperide/hyper-saas/pull/810" + "url": "https://github.com/hyperide/hyper-saas/pull/837", + "changedFiles": 10, + "additions": 252, + "deletions": 126, + "group": "dependencies" } ], "state-lib-2026-10": [ { "repo": "hyperide/hyper-saas", - "pr": 810, - "author": "alex-mextner", + "pr": 802, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 15 + }, + "attribution": "commit-author", "state": "MERGED", - "mergedAt": "2026-10-14T18:39:58Z", - "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", - "url": "https://github.com/hyperide/hyper-saas/pull/810" + "mergedAt": "2026-10-30T15:43:41Z", + "mergeSha": "659d9ef4932ca48de1f2d9e0810f2c1e72a320b7", + "url": "https://github.com/hyperide/hyper-saas/pull/802", + "changedFiles": 110, + "additions": 21928, + "deletions": 0, + "group": "compiled-entries", + "mergedBy": "alex-mextner" }, { "repo": "hyperide/hyper-saas", "pr": 803, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-30T17:49:58Z", "mergeSha": "f862a797d98126315b4d52ee931d5a7dd4d7faf0", - "url": "https://github.com/hyperide/hyper-saas/pull/803" + "url": "https://github.com/hyperide/hyper-saas/pull/803", + "changedFiles": 11, + "additions": 324, + "deletions": 3, + "group": "records" + }, + { + "repo": "hyperide/hyper-saas", + "pr": 807, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-30T15:27:35Z", + "mergeSha": "f32c4cf9aed3d1d5a62efbdd78877916bd63cfd9", + "url": "https://github.com/hyperide/hyper-saas/pull/807", + "changedFiles": 2, + "additions": 65, + "deletions": 17, + "group": "live-docs" + }, + { + "repo": "hyperide/hyper-saas", + "pr": 809, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 18 + }, + "attribution": "commit-author", + "state": "MERGED", + "mergedAt": "2026-10-31T20:15:56Z", + "mergeSha": "7669cfbdc6ed84e4ffa7b09b0829715be19d4f5a", + "url": "https://github.com/hyperide/hyper-saas/pull/809", + "changedFiles": 99, + "additions": 9124, + "deletions": 255, + "group": "live-docs", + "mergedBy": "alex-mextner" + }, + { + "repo": "hyperide/hyper-saas", + "pr": 810, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 7 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-14T18:39:58Z", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "url": "https://github.com/hyperide/hyper-saas/pull/810", + "changedFiles": 68, + "additions": 16876, + "deletions": 215, + "group": "async-toolkit" }, { "repo": "hyperide/hyper-saas", "pr": 826, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-30T16:30:35Z", "mergeSha": "5acccf194d17d4eaf746b3a1a72324853ac87eef", - "url": "https://github.com/hyperide/hyper-saas/pull/826" + "url": "https://github.com/hyperide/hyper-saas/pull/826", + "changedFiles": 13, + "additions": 1986, + "deletions": 12, + "group": "ownership" }, { "repo": "hyperide/hyper-saas", "pr": 832, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-30T22:02:48Z", "mergeSha": "b1723e89b082fc21eabc64434dccf4fc8b5bff09", - "url": "https://github.com/hyperide/hyper-saas/pull/832" + "url": "https://github.com/hyperide/hyper-saas/pull/832", + "changedFiles": 31, + "additions": 15045, + "deletions": 61, + "group": "compiled-entries" }, { "repo": "hyperide/hyper-saas", - "pr": 834, - "author": "alex-mextner", + "pr": 833, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "commit-author", "state": "MERGED", - "mergedAt": "2026-10-30T23:32:15Z", - "mergeSha": "4568a6b3af2980be700da51977b6facd1d687cf2", - "url": "https://github.com/hyperide/hyper-saas/pull/834" + "mergedAt": "2026-10-30T22:58:47Z", + "mergeSha": "6002c63954a90815275eb088f3813680b0f0d189", + "url": "https://github.com/hyperide/hyper-saas/pull/833", + "changedFiles": 4, + "additions": 272, + "deletions": 1, + "group": "live-docs", + "mergedBy": "alex-mextner" }, { "repo": "hyperide/hyper-saas", - "pr": 807, + "pr": 834, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-30T15:27:35Z", - "mergeSha": "f32c4cf9aed3d1d5a62efbdd78877916bd63cfd9", - "url": "https://github.com/hyperide/hyper-saas/pull/807" + "mergedAt": "2026-10-30T23:32:15Z", + "mergeSha": "4568a6b3af2980be700da51977b6facd1d687cf2", + "url": "https://github.com/hyperide/hyper-saas/pull/834", + "changedFiles": 7, + "additions": 347, + "deletions": 62, + "group": "cold-import" } ], "conloca-2026-10": [ { "repo": "conloca/private", - "pr": 299, + "pr": 129, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T15:08:41Z", + "mergeSha": "801b46dd5871a461b7cd250985bf12486b95f996", + "url": "https://github.com/conloca/private/pull/129", + "changedFiles": 1, + "additions": 1, + "deletions": 1, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 155, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T07:05:53Z", - "mergeSha": "2ac9cc7fbabd481334197b605bf72300e5d41ffb", - "url": "https://github.com/conloca/private/pull/299" + "mergedAt": "2026-10-16T16:41:01Z", + "mergeSha": "f663164416eb578972d7506fbb097e8e4883a13c", + "url": "https://github.com/conloca/private/pull/155", + "changedFiles": 6, + "additions": 2914, + "deletions": 0, + "group": "stage" }, { "repo": "conloca/private", - "pr": 306, + "pr": 158, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T14:37:34Z", - "mergeSha": "e781c6c705ec93471e168f14279f0d87a3cc7f2d", - "url": "https://github.com/conloca/private/pull/306" + "mergedAt": "2026-10-01T00:38:48Z", + "mergeSha": "ad7cc6005cb07ab4ae910652a884a8a95d7fe5ca", + "url": "https://github.com/conloca/private/pull/158", + "changedFiles": 2, + "additions": 12, + "deletions": 0, + "group": "gates" }, { "repo": "conloca/private", - "pr": 302, + "pr": 166, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 21 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T08:45:17Z", - "mergeSha": "5cdba99c7d858aa321e4bb64dddb62cd9cec7c14", - "url": "https://github.com/conloca/private/pull/302" + "mergedAt": "2026-10-17T05:39:26Z", + "mergeSha": "bac761bc467ed83ac527ca4389afd84e195e77ad", + "url": "https://github.com/conloca/private/pull/166", + "changedFiles": 64, + "additions": 5898, + "deletions": 397, + "group": "gates" }, { "repo": "conloca/private", - "pr": 296, + "pr": 167, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 8 + }, + "attribution": "commit-author", + "state": "MERGED", + "mergedAt": "2026-10-17T08:50:11Z", + "mergeSha": "d11cf4c9905ef558f6c50f8d1ce89fe4b9aeea0c", + "url": "https://github.com/conloca/private/pull/167", + "changedFiles": 7, + "additions": 1557, + "deletions": 0, + "group": "gates", + "mergedBy": "alex-mextner" + }, + { + "repo": "conloca/private", + "pr": 168, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "commit-author", + "state": "MERGED", + "mergedAt": "2026-10-16T12:49:13Z", + "mergeSha": "20eb0445f0433c18b9dba2dabde858ac053d9775", + "url": "https://github.com/conloca/private/pull/168", + "changedFiles": 4, + "additions": 9, + "deletions": 7, + "group": "stage", + "mergedBy": "alex-mextner" + }, + { + "repo": "conloca/private", + "pr": 169, + "author": "smoothbricker", + "commitAuthors": { + "alex-mextner": 7 + }, + "attribution": "commit-author", + "state": "MERGED", + "mergedAt": "2026-10-16T13:26:07Z", + "mergeSha": "412a9def65831de3bf9ad7bb12ba6ea746ce8d07", + "url": "https://github.com/conloca/private/pull/169", + "changedFiles": 32, + "additions": 1806, + "deletions": 217, + "group": "stage", + "mergedBy": "alex-mextner" + }, + { + "repo": "conloca/private", + "pr": 174, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T06:40:54Z", - "mergeSha": "f3d6aea36b8eff2dc25e6863ab4686a660a8013e", - "url": "https://github.com/conloca/private/pull/296" + "mergedAt": "2026-10-17T08:31:39Z", + "mergeSha": "6c5c10bf674a8d802eab56ad253b9e9201ccb33f", + "url": "https://github.com/conloca/private/pull/174", + "changedFiles": 2, + "additions": 45, + "deletions": 0, + "group": "gates" }, { "repo": "conloca/private", - "pr": 307, + "pr": 175, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T14:52:40Z", - "mergeSha": "70a75505b5722461852713aa22aa5d7b2842bab4", - "url": "https://github.com/conloca/private/pull/307" + "mergedAt": "2026-10-05T16:04:02Z", + "mergeSha": "da8e89782b227fd629d0af1ffb6c0e8671e159cc", + "url": "https://github.com/conloca/private/pull/175", + "changedFiles": 1, + "additions": 3, + "deletions": 0, + "group": "gates" }, { "repo": "conloca/private", - "pr": 288, + "pr": 176, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-22T15:59:57Z", - "mergeSha": "34fe714e90e054defc7b05c0e203dcea73e5d69a", - "url": "https://github.com/conloca/private/pull/288" + "mergedAt": "2026-10-05T16:50:22Z", + "mergeSha": "234af343a7f188202087a4e0fcf32f00970bba4f", + "url": "https://github.com/conloca/private/pull/176", + "changedFiles": 1, + "additions": 26, + "deletions": 0, + "group": "gates" }, { "repo": "conloca/private", - "pr": 289, + "pr": 177, "author": "alex-mextner", + "attribution": "commit-scope", "state": "MERGED", - "mergedAt": "2026-10-22T22:15:44Z", - "mergeSha": "4c784903d79fce725a752b99c42c4f5b3cb00dfe", - "url": "https://github.com/conloca/private/pull/289" + "mergedAt": "2026-10-16T18:32:05Z", + "mergeSha": "e75c29887f001f910ac5e6e9baa9e66552ad3cc0", + "url": "https://github.com/conloca/private/pull/177", + "group": "content", + "mixedAuthors": true, + "scopeCommits": [ + "4b42a4741a825554d63919646acc18e921a92ba0", + "7654828fbd61bce114fe48ae032ffab5f917f3aa", + "4155f8592bd48f293b40eb9bbcdef9e48d7c1ee5" + ], + "scopeSummary": "stale preview-session reconcile repair, its at-head regression test and the browser publication proof", + "ownCommits": 29, + "creditedCommitAuthors": { + "alex-mextner": 3 + } + }, + { + "repo": "conloca/private", + "pr": 178, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T03:51:35Z", + "mergeSha": "427ba73f4caecbd35edaf5e59c30c90ccfa6bead", + "url": "https://github.com/conloca/private/pull/178", + "changedFiles": 5, + "additions": 34, + "deletions": 19, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 188, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T13:08:37Z", + "mergeSha": "776f36056ce9b676fab47db4da68822a608cff31", + "url": "https://github.com/conloca/private/pull/188", + "changedFiles": 8, + "additions": 420, + "deletions": 11, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 191, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T16:48:56Z", + "mergeSha": "96dfd7b13bb2ee635e4efe1fe70a20854bb6b4a6", + "url": "https://github.com/conloca/private/pull/191", + "changedFiles": 6, + "additions": 91, + "deletions": 21, + "group": "workspace" }, { "repo": "conloca/private", "pr": 192, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 8 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-17T14:30:04Z", "mergeSha": "c02858bf15b57020fecc968bd70866d9f6ddb7a4", - "url": "https://github.com/conloca/private/pull/192" + "url": "https://github.com/conloca/private/pull/192", + "changedFiles": 14, + "additions": 863, + "deletions": 28, + "group": "workspace" }, { "repo": "conloca/private", - "pr": 224, + "pr": 193, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-17T15:11:05Z", - "mergeSha": "4fa3cd565e92d577f75a447e2b65c4c956a3ca5a", - "url": "https://github.com/conloca/private/pull/224" + "mergedAt": "2026-10-16T18:13:55Z", + "mergeSha": "a407565daa12518e4151d3e53259a27de0b57929", + "url": "https://github.com/conloca/private/pull/193", + "changedFiles": 7, + "additions": 307, + "deletions": 99, + "group": "stage" + }, + { + "repo": "conloca/private", + "pr": 194, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T14:16:31Z", + "mergeSha": "8ef420b13b13fa7aa2d9e677d0add2a583d9af73", + "url": "https://github.com/conloca/private/pull/194", + "changedFiles": 9, + "additions": 140, + "deletions": 21, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 195, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T13:49:19Z", + "mergeSha": "7f0ff49900f92bc6b4272920148fc55b45bbcd6d", + "url": "https://github.com/conloca/private/pull/195", + "changedFiles": 1, + "additions": 10, + "deletions": 0, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 196, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T13:45:01Z", + "mergeSha": "ccbcc74b071de7a0b795fdefa7aab9feec53fbc8", + "url": "https://github.com/conloca/private/pull/196", + "changedFiles": 5, + "additions": 224, + "deletions": 97, + "group": "editor" }, { "repo": "conloca/private", "pr": 197, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-17T15:48:14Z", "mergeSha": "c8940860effb75be5c2cae136108f12b2ebb6f83", - "url": "https://github.com/conloca/private/pull/197" + "url": "https://github.com/conloca/private/pull/197", + "changedFiles": 6, + "additions": 518, + "deletions": 69, + "group": "content" }, { "repo": "conloca/private", - "pr": 243, + "pr": 198, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 9 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-15T20:13:55Z", - "mergeSha": "a7f6ba6ad6b220cb1d7f0f7cf886bb2105dc00fd", - "url": "https://github.com/conloca/private/pull/243" + "mergedAt": "2026-10-15T14:49:44Z", + "mergeSha": "bc2fe3f829949d0e8f10d10b1f44e65259d49f2d", + "url": "https://github.com/conloca/private/pull/198", + "changedFiles": 6, + "additions": 897, + "deletions": 0, + "group": "coverage" }, { "repo": "conloca/private", - "pr": 235, + "pr": 200, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 9 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-15T16:32:44Z", - "mergeSha": "51fba3c31dc867639763432c7f3a85d291aee9ee", - "url": "https://github.com/conloca/private/pull/235" + "mergedAt": "2026-10-15T11:49:45Z", + "mergeSha": "5ea01fc5c09fe23d2fe9c933f51412480f7528fa", + "url": "https://github.com/conloca/private/pull/200", + "changedFiles": 8, + "additions": 845, + "deletions": 1, + "group": "stage" }, { "repo": "conloca/private", - "pr": 342, + "pr": 201, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-27T15:46:16Z", - "mergeSha": "ce20346cf302a70229c8378c583062414994be5d", - "url": "https://github.com/conloca/private/pull/342" + "mergedAt": "2026-10-15T14:33:48Z", + "mergeSha": "a60d17a7a4b8daa112c2c10643beb8f30ca5c350", + "url": "https://github.com/conloca/private/pull/201", + "changedFiles": 1, + "additions": 15, + "deletions": 16, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 204, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T14:01:40Z", + "mergeSha": "927baff1bd385526cae02e67225715e00a72dfc0", + "url": "https://github.com/conloca/private/pull/204", + "changedFiles": 2, + "additions": 81, + "deletions": 3, + "group": "gates" }, { "repo": "conloca/private", "pr": 217, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 12 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-16T22:53:42Z", "mergeSha": "13ce65e6d35309af48d0d639315482f58932521b", - "url": "https://github.com/conloca/private/pull/217" + "url": "https://github.com/conloca/private/pull/217", + "changedFiles": 18, + "additions": 580, + "deletions": 75, + "group": "coverage" }, { "repo": "conloca/private", - "pr": 244, + "pr": 220, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-15T17:27:07Z", - "mergeSha": "f08bb34d1792ee2200d4426a4afc0c50295ddd10", - "url": "https://github.com/conloca/private/pull/244" + "mergedAt": "2026-10-15T19:55:17Z", + "mergeSha": "a3494437fa6d0c56f60a6a213e34aaa4c2cf90f1", + "url": "https://github.com/conloca/private/pull/220", + "changedFiles": 4, + "additions": 96, + "deletions": 2, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 221, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T15:57:55Z", + "mergeSha": "ac0217af3dfce6b86cde41038e5a2c9c1a86b538", + "url": "https://github.com/conloca/private/pull/221", + "changedFiles": 1, + "additions": 113, + "deletions": 0, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 222, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T17:46:11Z", + "mergeSha": "ae5dc32b7e971066844c55841d5d0e12b0e38429", + "url": "https://github.com/conloca/private/pull/222", + "changedFiles": 4, + "additions": 58, + "deletions": 13, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 223, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T23:21:05Z", + "mergeSha": "97920b612e286b4d5fa6c829d1fdfffa5df9e24b", + "url": "https://github.com/conloca/private/pull/223", + "changedFiles": 13, + "additions": 1554, + "deletions": 651, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 224, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 6 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T15:11:05Z", + "mergeSha": "4fa3cd565e92d577f75a447e2b65c4c956a3ca5a", + "url": "https://github.com/conloca/private/pull/224", + "changedFiles": 15, + "additions": 319, + "deletions": 32, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 225, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T16:14:52Z", + "mergeSha": "6f0ab1bde62014378f61dc270df169726fc3ae2d", + "url": "https://github.com/conloca/private/pull/225", + "changedFiles": 11, + "additions": 231, + "deletions": 57, + "group": "workspace" }, { "repo": "conloca/private", "pr": 226, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", "mergedAt": "2026-10-15T17:08:27Z", "mergeSha": "92729b031f3afac0d840739718c318ef4401c812", - "url": "https://github.com/conloca/private/pull/226" + "url": "https://github.com/conloca/private/pull/226", + "changedFiles": 1, + "additions": 125, + "deletions": 19, + "group": "coverage" }, { "repo": "conloca/private", - "pr": 300, + "pr": 228, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T09:19:30Z", - "mergeSha": "1a9c773b28e1f39ff0b29dfe6488acfb6242eb60", - "url": "https://github.com/conloca/private/pull/300" + "mergedAt": "2026-10-15T20:53:19Z", + "mergeSha": "928630e27de2ffed4ae2c6d3716731d5fe5f4dac", + "url": "https://github.com/conloca/private/pull/228", + "changedFiles": 1, + "additions": 7, + "deletions": 0, + "group": "content" }, { "repo": "conloca/private", - "pr": 304, + "pr": 229, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 9 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T09:14:51Z", - "mergeSha": "456e5c4ee2740be398bd20ce0614bb8eaedfe3f0", - "url": "https://github.com/conloca/private/pull/304" + "mergedAt": "2026-10-17T17:47:01Z", + "mergeSha": "e8cf5c5256fccf1c2281951930fb9db337bd3328", + "url": "https://github.com/conloca/private/pull/229", + "changedFiles": 10, + "additions": 583, + "deletions": 3, + "group": "coverage" }, { "repo": "conloca/private", - "pr": 309, + "pr": 230, "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 7 + }, + "attribution": "pr-author", "state": "MERGED", - "mergedAt": "2026-10-23T14:54:24Z", - "mergeSha": "8540d9b8616fe12ba72689cb63b3d2ede62ab959", - "url": "https://github.com/conloca/private/pull/309" - } - ] - }, - "approvalPreview": { - "number": 489, - "url": "https://github.com/conloca/private/pull/489", - "headRefOid": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", - "state": "OPEN", - "isDraft": false, - "author": { - "id": "U_kgDOBqa7tg", - "is_bot": false, - "login": "alex-mextner", - "name": "Alex Ultra" - } - }, - "images": [ - { - "path": "reports/state-lib-2026-10/images/caption-before.png", - "sha256": "51a7726c59072f657e954bad98e57c2beb9a37be0acf0353e6c2cc85f18348f7", - "sourcePr": 810, - "repo": "hyperide/hyper-saas", - "capturedAt": "2026-10-14", - "captureTimePrecision": "date", - "width": 850, - "height": 450 - }, - { - "path": "reports/state-lib-2026-10/images/caption-after.png", - "sha256": "8ae9f19a967ee8d48db6f8446cd827a5425a44c5a2c48f65c704d7127b7e57c5", - "sourcePr": 810, - "repo": "hyperide/hyper-saas", - "capturedAt": "2026-10-14", - "captureTimePrecision": "date", + "mergedAt": "2026-10-16T19:18:43Z", + "mergeSha": "bee9ed4938177f75617b7b8150607d40362398ff", + "url": "https://github.com/conloca/private/pull/230", + "changedFiles": 15, + "additions": 679, + "deletions": 26, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 231, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T16:07:34Z", + "mergeSha": "22042f621dce3570211177e162c7f53f6f229929", + "url": "https://github.com/conloca/private/pull/231", + "changedFiles": 11, + "additions": 236, + "deletions": 18, + "group": "landing" + }, + { + "repo": "conloca/private", + "pr": 232, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T13:18:09Z", + "mergeSha": "861df4c80c0c20a35ff3bec27b98f8fd023ed270", + "url": "https://github.com/conloca/private/pull/232", + "changedFiles": 4, + "additions": 179, + "deletions": 1, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 233, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T12:03:56Z", + "mergeSha": "d29d1f73c04cff944452a23c4c657ec39e956f35", + "url": "https://github.com/conloca/private/pull/233", + "changedFiles": 3, + "additions": 4, + "deletions": 4, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 234, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T20:33:55Z", + "mergeSha": "54076b938177f892e120556833bc4549070bf4b3", + "url": "https://github.com/conloca/private/pull/234", + "changedFiles": 2, + "additions": 100, + "deletions": 1, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 235, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T16:32:44Z", + "mergeSha": "51fba3c31dc867639763432c7f3a85d291aee9ee", + "url": "https://github.com/conloca/private/pull/235", + "changedFiles": 7, + "additions": 321, + "deletions": 11, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 236, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T15:22:49Z", + "mergeSha": "4c7f3701fe8176c8129952d47814351fdf9c49a4", + "url": "https://github.com/conloca/private/pull/236", + "changedFiles": 2, + "additions": 68, + "deletions": 0, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 237, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T12:46:50Z", + "mergeSha": "700e5750db126dec8430a747f175a4473c0300a5", + "url": "https://github.com/conloca/private/pull/237", + "changedFiles": 2, + "additions": 86, + "deletions": 8, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 238, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T12:30:22Z", + "mergeSha": "ba70c9045ec62266058ec5cff9b0f51388bca3a4", + "url": "https://github.com/conloca/private/pull/238", + "changedFiles": 13, + "additions": 1587, + "deletions": 126, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 239, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T15:38:52Z", + "mergeSha": "d3a4924d7537b38b649a27350dc3e97fb8b39cf4", + "url": "https://github.com/conloca/private/pull/239", + "changedFiles": 2, + "additions": 108, + "deletions": 11, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 240, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T12:58:28Z", + "mergeSha": "29f2ed575c7188a8b5840b8cb3b5db4e72e2fdfe", + "url": "https://github.com/conloca/private/pull/240", + "changedFiles": 22, + "additions": 974, + "deletions": 141, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 241, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T13:32:54Z", + "mergeSha": "b82495b20009755725653f53a4c7cc87dde49fa4", + "url": "https://github.com/conloca/private/pull/241", + "changedFiles": 12, + "additions": 100, + "deletions": 101, + "group": "stage" + }, + { + "repo": "conloca/private", + "pr": 243, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T20:13:55Z", + "mergeSha": "a7f6ba6ad6b220cb1d7f0f7cf886bb2105dc00fd", + "url": "https://github.com/conloca/private/pull/243", + "changedFiles": 18, + "additions": 854, + "deletions": 28, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 244, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T17:27:07Z", + "mergeSha": "f08bb34d1792ee2200d4426a4afc0c50295ddd10", + "url": "https://github.com/conloca/private/pull/244", + "changedFiles": 19, + "additions": 1552, + "deletions": 10, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 247, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T18:02:01Z", + "mergeSha": "6cef88cdfa9c65b96582a54e9685d97d0fb950e3", + "url": "https://github.com/conloca/private/pull/247", + "changedFiles": 29, + "additions": 1226, + "deletions": 72, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 248, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 9 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T12:26:15Z", + "mergeSha": "2cf6e085c63bfafcd46d11559226e7da7d734ec6", + "url": "https://github.com/conloca/private/pull/248", + "changedFiles": 15, + "additions": 509, + "deletions": 41, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 251, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 14 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T20:11:17Z", + "mergeSha": "36d2fc7a54a7328c304bf694cd5ae42c061c2daf", + "url": "https://github.com/conloca/private/pull/251", + "changedFiles": 160, + "additions": 5770, + "deletions": 2119, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 253, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T23:46:23Z", + "mergeSha": "54d8def011e16fe32bf32f5d3a5f48f03d103ff7", + "url": "https://github.com/conloca/private/pull/253", + "changedFiles": 24, + "additions": 945, + "deletions": 387, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 254, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-15T18:21:12Z", + "mergeSha": "0e5c8e794dfa9a7c3f7d0fe6ecf2599de68611a7", + "url": "https://github.com/conloca/private/pull/254", + "changedFiles": 2, + "additions": 29, + "deletions": 2, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 255, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T17:15:14Z", + "mergeSha": "0a2e0f55d3b815c95feb56c22c86fd739b69b0ed", + "url": "https://github.com/conloca/private/pull/255", + "changedFiles": 1, + "additions": 15, + "deletions": 9, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 256, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T22:36:23Z", + "mergeSha": "78bb19000b7e3c23521e8d52c5e520b947779edb", + "url": "https://github.com/conloca/private/pull/256", + "changedFiles": 12, + "additions": 770, + "deletions": 117, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 257, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T21:15:46Z", + "mergeSha": "5f8afccaa9dbb7050cd975a96ea170c6f5940498", + "url": "https://github.com/conloca/private/pull/257", + "changedFiles": 3, + "additions": 23, + "deletions": 2, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 258, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-16T21:19:52Z", + "mergeSha": "9739e87d9fad726df9282b131fabb9c9ef0f7e70", + "url": "https://github.com/conloca/private/pull/258", + "changedFiles": 6, + "additions": 118, + "deletions": 25, + "group": "stage" + }, + { + "repo": "conloca/private", + "pr": 259, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T04:47:36Z", + "mergeSha": "29494248aaf828d6e4ed475bf57a947ad7ddf4d4", + "url": "https://github.com/conloca/private/pull/259", + "changedFiles": 13, + "additions": 1195, + "deletions": 93, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 260, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 13 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T08:00:32Z", + "mergeSha": "652a0f076983c375ec9c774b71f76fe6326b271d", + "url": "https://github.com/conloca/private/pull/260", + "changedFiles": 16, + "additions": 887, + "deletions": 415, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 261, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 11 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T11:31:02Z", + "mergeSha": "0e02589354f4b9de3b30749761ede691ec4587a8", + "url": "https://github.com/conloca/private/pull/261", + "changedFiles": 21, + "additions": 1109, + "deletions": 171, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 262, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T10:58:48Z", + "mergeSha": "b128562707f98b6f93700135441096dd3dd73b2c", + "url": "https://github.com/conloca/private/pull/262", + "changedFiles": 3, + "additions": 21, + "deletions": 9, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 263, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-17T13:52:26Z", + "mergeSha": "35a522795b9f059d2ea85f1ba68396ec7301c0b5", + "url": "https://github.com/conloca/private/pull/263", + "changedFiles": 3, + "additions": 417, + "deletions": 12, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 288, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-22T15:59:57Z", + "mergeSha": "34fe714e90e054defc7b05c0e203dcea73e5d69a", + "url": "https://github.com/conloca/private/pull/288", + "changedFiles": 8, + "additions": 447, + "deletions": 46, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 289, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-22T22:15:44Z", + "mergeSha": "4c784903d79fce725a752b99c42c4f5b3cb00dfe", + "url": "https://github.com/conloca/private/pull/289", + "changedFiles": 15, + "additions": 422, + "deletions": 91, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 290, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-22T21:52:18Z", + "mergeSha": "704a00460c41ab93650789bf2d78a117d3a5129e", + "url": "https://github.com/conloca/private/pull/290", + "changedFiles": 1, + "additions": 1, + "deletions": 1, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 292, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-22T22:57:57Z", + "mergeSha": "4f6cc8b299d3514dc42af9f7f827ba33f4800f68", + "url": "https://github.com/conloca/private/pull/292", + "changedFiles": 2, + "additions": 53, + "deletions": 6, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 293, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-22T23:34:30Z", + "mergeSha": "6f4b29be5cb20f25ef11ea573b122f1bb6d19ca1", + "url": "https://github.com/conloca/private/pull/293", + "changedFiles": 5, + "additions": 151, + "deletions": 2, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 294, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 8 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T03:15:49Z", + "mergeSha": "9ab7c3049deb7f1c00f4c578d71b8637379dceb1", + "url": "https://github.com/conloca/private/pull/294", + "changedFiles": 3, + "additions": 199, + "deletions": 1, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 295, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T00:50:17Z", + "mergeSha": "050d649b940d96e1c4f5d4f24cdc252963f6e69e", + "url": "https://github.com/conloca/private/pull/295", + "changedFiles": 4, + "additions": 165, + "deletions": 8, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 296, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 6 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T06:40:54Z", + "mergeSha": "f3d6aea36b8eff2dc25e6863ab4686a660a8013e", + "url": "https://github.com/conloca/private/pull/296", + "changedFiles": 20, + "additions": 1038, + "deletions": 61, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 297, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T06:46:50Z", + "mergeSha": "d49f861c624244eb9a804f5d06b3def75e309399", + "url": "https://github.com/conloca/private/pull/297", + "changedFiles": 6, + "additions": 490, + "deletions": 9, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 298, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T07:23:50Z", + "mergeSha": "53aafd0776152eff1c32b45acf55d387209dbb5b", + "url": "https://github.com/conloca/private/pull/298", + "changedFiles": 1, + "additions": 1, + "deletions": 1, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 299, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T07:05:53Z", + "mergeSha": "2ac9cc7fbabd481334197b605bf72300e5d41ffb", + "url": "https://github.com/conloca/private/pull/299", + "changedFiles": 4, + "additions": 406, + "deletions": 13, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 300, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T09:19:30Z", + "mergeSha": "1a9c773b28e1f39ff0b29dfe6488acfb6242eb60", + "url": "https://github.com/conloca/private/pull/300", + "changedFiles": 5, + "additions": 419, + "deletions": 72, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 301, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 5 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T07:47:43Z", + "mergeSha": "1154e7f80b94d01ed2bf41b6d9947d1f10af267e", + "url": "https://github.com/conloca/private/pull/301", + "changedFiles": 4, + "additions": 256, + "deletions": 4, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 302, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T08:45:17Z", + "mergeSha": "5cdba99c7d858aa321e4bb64dddb62cd9cec7c14", + "url": "https://github.com/conloca/private/pull/302", + "changedFiles": 7, + "additions": 392, + "deletions": 109, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 303, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T08:33:53Z", + "mergeSha": "ef00358114e5d835a76da78ab71a406ea3cc0888", + "url": "https://github.com/conloca/private/pull/303", + "changedFiles": 8, + "additions": 2237, + "deletions": 1, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 304, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T09:14:51Z", + "mergeSha": "456e5c4ee2740be398bd20ce0614bb8eaedfe3f0", + "url": "https://github.com/conloca/private/pull/304", + "changedFiles": 1, + "additions": 486, + "deletions": 0, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 305, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T09:54:20Z", + "mergeSha": "cab2bae62ef827f4dd430beeb54146249d10feb7", + "url": "https://github.com/conloca/private/pull/305", + "changedFiles": 2, + "additions": 140, + "deletions": 21, + "group": "workspace" + }, + { + "repo": "conloca/private", + "pr": 306, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 3 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T14:37:34Z", + "mergeSha": "e781c6c705ec93471e168f14279f0d87a3cc7f2d", + "url": "https://github.com/conloca/private/pull/306", + "changedFiles": 2, + "additions": 139, + "deletions": 31, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 307, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T14:52:40Z", + "mergeSha": "70a75505b5722461852713aa22aa5d7b2842bab4", + "url": "https://github.com/conloca/private/pull/307", + "changedFiles": 2, + "additions": 97, + "deletions": 2, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 308, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T14:53:57Z", + "mergeSha": "e0d431a83452f24e1574ffc920601b344cb45494", + "url": "https://github.com/conloca/private/pull/308", + "changedFiles": 3, + "additions": 122, + "deletions": 4, + "group": "content" + }, + { + "repo": "conloca/private", + "pr": 309, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T14:54:24Z", + "mergeSha": "8540d9b8616fe12ba72689cb63b3d2ede62ab959", + "url": "https://github.com/conloca/private/pull/309", + "changedFiles": 1, + "additions": 86, + "deletions": 0, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 311, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T13:50:17Z", + "mergeSha": "eeb42b9b6a01b44f3b6ed4821d7b6eb6f7cd8d1e", + "url": "https://github.com/conloca/private/pull/311", + "changedFiles": 5, + "additions": 133, + "deletions": 91, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 313, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 1 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T14:56:02Z", + "mergeSha": "b72ae7fb4335c7c607c26f637a85b4ec2e947541", + "url": "https://github.com/conloca/private/pull/313", + "changedFiles": 3, + "additions": 23, + "deletions": 38, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 314, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 4 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T15:09:57Z", + "mergeSha": "0c8c19e09fb4fe453c35d7aaaf4fedf9eb7cb388", + "url": "https://github.com/conloca/private/pull/314", + "changedFiles": 4, + "additions": 101, + "deletions": 367, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 315, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T15:49:47Z", + "mergeSha": "7bf3aa1361ca54c162ecd201b6d644436b56e0d7", + "url": "https://github.com/conloca/private/pull/315", + "changedFiles": 3, + "additions": 41, + "deletions": 2, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 316, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T16:15:51Z", + "mergeSha": "d49ad9680e730d48070a34a65a8587d3b320850b", + "url": "https://github.com/conloca/private/pull/316", + "changedFiles": 2, + "additions": 20, + "deletions": 1, + "group": "editor" + }, + { + "repo": "conloca/private", + "pr": 319, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T17:00:15Z", + "mergeSha": "104f3f6105ec5a2122a5b2367c7f03978290db93", + "url": "https://github.com/conloca/private/pull/319", + "changedFiles": 1, + "additions": 7, + "deletions": 2, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 320, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 7 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T17:44:35Z", + "mergeSha": "f294dfd11b0e7a97d9bd651b929564af74fb92a7", + "url": "https://github.com/conloca/private/pull/320", + "changedFiles": 16, + "additions": 328, + "deletions": 95, + "group": "coverage" + }, + { + "repo": "conloca/private", + "pr": 322, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 8 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-23T19:01:39Z", + "mergeSha": "8a894311d29ba51efdf651de9e59ac08ac1330b5", + "url": "https://github.com/conloca/private/pull/322", + "changedFiles": 20, + "additions": 162, + "deletions": 54, + "group": "gates" + }, + { + "repo": "conloca/private", + "pr": 342, + "author": "alex-mextner", + "commitAuthors": { + "alex-mextner": 2 + }, + "attribution": "pr-author", + "state": "MERGED", + "mergedAt": "2026-10-27T15:46:16Z", + "mergeSha": "ce20346cf302a70229c8378c583062414994be5d", + "url": "https://github.com/conloca/private/pull/342", + "changedFiles": 15, + "additions": 535, + "deletions": 407, + "group": "landing" + } + ] + }, + "approvalPreview": { + "number": 489, + "url": "https://github.com/conloca/private/pull/489", + "headRefOid": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", + "state": "OPEN", + "isDraft": false, + "author": { + "id": "U_kgDOBqa7tg", + "is_bot": false, + "login": "alex-mextner", + "name": "Alex Ultra" + } + }, + "images": [ + { + "path": "reports/state-lib-2026-10/images/caption-before.png", + "sha256": "51a7726c59072f657e954bad98e57c2beb9a37be0acf0353e6c2cc85f18348f7", + "sourcePr": 810, + "repo": "hyperide/hyper-saas", + "capturedAt": "2026-10-14", + "captureTimePrecision": "date", + "width": 850, + "height": 450 + }, + { + "path": "reports/state-lib-2026-10/images/caption-after.png", + "sha256": "8ae9f19a967ee8d48db6f8446cd827a5425a44c5a2c48f65c704d7127b7e57c5", + "sourcePr": 810, + "repo": "hyperide/hyper-saas", + "capturedAt": "2026-10-14", + "captureTimePrecision": "date", "width": 850, "height": 450 }, { - "path": "reports/conloca-2026-10/images/theme-before.png", - "sha256": "c1772cffc7113284902e9af1c9c77847e7307f955b935894b2071a84615e018d", - "sourceUrl": "https://conloca.com/getting-started/", - "capturedAt": "2026-11-05T20:03:10.819Z", - "sourcePr": 489, + "path": "reports/conloca-2026-10/images/theme-before.png", + "sha256": "c1772cffc7113284902e9af1c9c77847e7307f955b935894b2071a84615e018d", + "sourceUrl": "https://conloca.com/getting-started/", + "capturedAt": "2026-11-05T20:03:10.819Z", + "sourcePr": 489, + "repo": "conloca/private", + "captureKind": "viewport", + "width": 1440, + "height": 1000 + }, + { + "path": "reports/conloca-2026-10/images/theme-after.png", + "sha256": "b1a80d382d6b855bed76f13df4c90bd408c446749fdcc9bcd073acc9ea2125de", + "sourceUrl": "https://site.pr489.conloca.com/getting-started/", + "capturedAt": "2026-11-05T20:03:12.926Z", + "sourcePr": 489, + "repo": "conloca/private", + "captureKind": "viewport", + "width": 1440, + "height": 1000 + } + ], + "storybookPreviews": { + "verifiedAt": "2026-11-05T22:16:30.758703+00:00", + "workflowStatus": "implemented-awaiting-merge-approval", + "pullRequests": [ + { + "author": "alex-mextner", + "headRefOid": "018f52c31332dc3c1055eadfc6dde63be78b9e59", + "isDraft": false, + "number": 404, + "state": "OPEN", + "url": "https://github.com/conloca/private/pull/404" + }, + { + "author": "alex-mextner", + "headRefOid": "591024553d91fb0aeaad8081f9c39064cb024846", + "isDraft": false, + "number": 509, + "state": "OPEN", + "url": "https://github.com/conloca/private/pull/509" + } + ], + "status": "historical", + "historicalNote": "Receipts of an earlier catalogue publication on 5 November 2026. Superseded and not linked from the human reports.", + "segments": [ + { + "segment": "main", + "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/main/", + "sourceSha": "795967bd48a0f1d8f96d87a562b15922ef529775", + "publication": "operator-published", + "deployExit": 0, + "protectionProbeExit": 0 + }, + { + "segment": "pr-404", + "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/pr-404/", + "sourceSha": "018f52c31332dc3c1055eadfc6dde63be78b9e59", + "publication": "operator-published", + "deployExit": 0, + "protectionProbeExit": 0, + "commitStatus": "success" + }, + { + "segment": "pr-489", + "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/pr-489/", + "sourceSha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", + "publication": "operator-published", + "deployExit": 0, + "protectionProbeExit": 0, + "commitStatus": "success" + } + ], + "requiresForgeSignIn": true, + "authenticatedProductionBrowserVerified": false, + "verification": "Deployment receipts, exact-head GitHub statuses and anonymous access protection. The same archive was browser-tested on the real host binary locally; that is not production OAuth acceptance.", + "mainSandboxPathFix": "PR404 carries the prefixed sandbox-path fix; main contains the merged integration branch.", + "deployedE2E": "https://github.com/conloca/private/actions/runs/42052900149/job/127344610560" + }, + "sourceScopes": { + "hyperide/hyper-saas#810": { + "title": "feat(state-lib): headless async toolkit and fail-closed export (HYP-1507)", + "author": "alex-mextner", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "url": "https://github.com/hyperide/hyper-saas/pull/810", + "files": [ + "server/routes/git.ts", + "server/routes/__tests__/git-push.security.test.ts", + "server/services/git-push-error.ts", + "server/services/__tests__/git-push-tls.test.ts", + "server/utils/git-credentials.ts", + "packages/state-lib/toolkit/src/async-resource.ts", + "packages/state-lib/site/src/lib/highlight.ts", + "packages/state-lib/site/tools/heading-caption.check.mts" + ], + "includedWork": [ + "Headless async toolkit", + "Git push authority, transport policy and typed failure handling", + "Quoted attribute and comment parsing in diagram captions" + ] + } + }, + "checks": [ + { + "name": "CI", + "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-14T10:22:11Z", + "repo": "hyperide/hyper-saas", + "run": 38547360197, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360197", + "pr": 810, + "prHead": "d4cca87cee086eead00392f1a662de7065a8019c", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "event": "pull_request" + }, + { + "name": "Security Scan", + "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-14T10:09:02Z", + "repo": "hyperide/hyper-saas", + "run": 38547359971, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547359971", + "pr": 810, + "prHead": "d4cca87cee086eead00392f1a662de7065a8019c", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "event": "pull_request" + }, + { + "name": "State docs reading and interactions", + "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-14T10:19:19Z", + "repo": "hyperide/hyper-saas", + "run": 38547360009, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360009", + "pr": 810, + "prHead": "d4cca87cee086eead00392f1a662de7065a8019c", + "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", + "event": "pull_request" + }, + { + "name": "E2E Tests (Deployed Stage)", + "head_sha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", + "status": "completed", + "conclusion": "success", + "started_at": "2026-11-03T11:37:48Z", + "completed_at": "2026-11-03T11:48:51Z", + "repo": "conloca/private", + "run": 41626469902, + "url": "https://github.com/conloca/private/actions/runs/41626469902/job/125893569803", + "job": 125893569803 + }, + { + "name": "E2E Tests (Deployed Stage)", + "head_sha": "018f52c31332dc3c1055eadfc6dde63be78b9e59", + "status": "completed", + "conclusion": "success", + "started_at": "2026-11-05T15:33:02Z", + "completed_at": "2026-11-05T15:42:55Z", + "repo": "conloca/private", + "run": 42052900149, + "url": "https://github.com/conloca/private/actions/runs/42052900149/job/127344610560", + "job": 127344610560 + }, + { + "name": "CI", + "head_sha": "ce20346cf302a70229c8378c583062414994be5d", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-27T16:04:21Z", + "repo": "conloca/private", + "run": 40534284367, + "url": "https://github.com/conloca/private/actions/runs/40534284367", + "jobs": [ + { + "conclusion": "success", + "head_sha": "ce20346cf302a70229c8378c583062414994be5d", + "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122295162949", + "id": 122295162949, + "name": "Validate", + "status": "completed" + }, + { + "conclusion": "success", + "head_sha": "ce20346cf302a70229c8378c583062414994be5d", + "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122299074596", + "id": 122299074596, + "name": "E2E Tests (Deployed Stage)", + "status": "completed" + }, + { + "conclusion": "success", + "head_sha": "ce20346cf302a70229c8378c583062414994be5d", + "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122303701660", + "id": 122303701660, + "name": "Deploy Production", + "status": "completed" + } + ], + "pr": 342, + "prHead": "49f981635b1b59af680fe9f81e1c9c0d6ae4e986", + "mergeSha": "ce20346cf302a70229c8378c583062414994be5d", + "event": "push" + }, + { + "conclusion": "success", + "head_sha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", + "name": "CI", + "status": "completed", + "updated_at": "2026-11-03T11:48:52Z", + "url": "https://github.com/conloca/private/actions/runs/41626469902", + "repo": "conloca/private", + "run": 41626469902 + }, + { + "name": "CI", + "head_sha": "ff519a9864093f1c7b130425077fb99d4bb7951b", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-15T13:10:44Z", + "repo": "hyperide/hyper-saas", + "run": 38738722190, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38738722190", + "event": "pull_request", + "pr": 825, + "prHead": "ff519a9864093f1c7b130425077fb99d4bb7951b", + "mergeSha": "b0c3a5123add28644d0da367c0e808c7b7e6dd3d" + }, + { + "name": "Publish VS Code Extension", + "head_sha": "b0c3a5123add28644d0da367c0e808c7b7e6dd3d", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-16T01:27:05Z", + "repo": "hyperide/hyper-saas", + "run": 38834833575, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38834833575", + "event": "push", + "pr": 825, + "prHead": "ff519a9864093f1c7b130425077fb99d4bb7951b", + "mergeSha": "b0c3a5123add28644d0da367c0e808c7b7e6dd3d" + }, + { + "name": "CI", + "head_sha": "49f981635b1b59af680fe9f81e1c9c0d6ae4e986", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-27T12:57:39Z", "repo": "conloca/private", - "captureKind": "viewport", - "width": 1440, - "height": 1000 + "run": 40505784923, + "url": "https://github.com/conloca/private/actions/runs/40505784923", + "event": "pull_request", + "pr": 342, + "prHead": "49f981635b1b59af680fe9f81e1c9c0d6ae4e986", + "mergeSha": "ce20346cf302a70229c8378c583062414994be5d" }, { - "path": "reports/conloca-2026-10/images/theme-after.png", - "sha256": "b1a80d382d6b855bed76f13df4c90bd408c446749fdcc9bcd073acc9ea2125de", - "sourceUrl": "https://site.pr489.conloca.com/getting-started/", - "capturedAt": "2026-11-05T20:03:12.926Z", - "sourcePr": 489, + "name": "CI", + "head_sha": "3a014d4a2fca9e2919cacfbf60884336d3c79e80", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-23T07:04:14Z", "repo": "conloca/private", - "captureKind": "viewport", - "width": 1440, - "height": 1000 + "run": 39913205421, + "url": "https://github.com/conloca/private/actions/runs/39913205421", + "event": "pull_request", + "pr": 299, + "prHead": "3a014d4a2fca9e2919cacfbf60884336d3c79e80", + "mergeSha": "2ac9cc7fbabd481334197b605bf72300e5d41ffb" + }, + { + "name": "CI", + "head_sha": "55bd485f2ab3a49f28738a59923abf5780087a85", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-23T08:44:40Z", + "repo": "conloca/private", + "run": 39924273295, + "url": "https://github.com/conloca/private/actions/runs/39924273295", + "event": "pull_request", + "pr": 302, + "prHead": "55bd485f2ab3a49f28738a59923abf5780087a85", + "mergeSha": "5cdba99c7d858aa321e4bb64dddb62cd9cec7c14" + }, + { + "name": "CI", + "head_sha": "7a149328b47c01d06fed75621ab3191a591c6dc0", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-23T02:07:17Z", + "repo": "conloca/private", + "run": 39886342267, + "url": "https://github.com/conloca/private/actions/runs/39886342267", + "event": "pull_request", + "pr": 296, + "prHead": "7a149328b47c01d06fed75621ab3191a591c6dc0", + "mergeSha": "f3d6aea36b8eff2dc25e6863ab4686a660a8013e" + }, + { + "name": "CI", + "head_sha": "2ad5a099a531ff6af4509f771cd7c9428d9ad8d2", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-23T14:07:38Z", + "repo": "conloca/private", + "run": 39964824309, + "url": "https://github.com/conloca/private/actions/runs/39964824309", + "event": "pull_request", + "pr": 306, + "prHead": "2ad5a099a531ff6af4509f771cd7c9428d9ad8d2", + "mergeSha": "e781c6c705ec93471e168f14279f0d87a3cc7f2d" + }, + { + "name": "CI", + "head_sha": "6212c9c6f63f0e18ec074579dd32fa523debb835", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-22T15:47:24Z", + "repo": "conloca/private", + "run": 39804895916, + "url": "https://github.com/conloca/private/actions/runs/39804895916", + "event": "pull_request", + "pr": 288, + "prHead": "6212c9c6f63f0e18ec074579dd32fa523debb835", + "mergeSha": "34fe714e90e054defc7b05c0e203dcea73e5d69a" + }, + { + "name": "CI", + "head_sha": "522f2e9f7ca5c65619a1d9cba5c9183d83e0efc5", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-22T22:15:23Z", + "repo": "conloca/private", + "run": 39861084298, + "url": "https://github.com/conloca/private/actions/runs/39861084298", + "event": "pull_request", + "pr": 289, + "prHead": "522f2e9f7ca5c65619a1d9cba5c9183d83e0efc5", + "mergeSha": "4c784903d79fce725a752b99c42c4f5b3cb00dfe" + }, + { + "name": "CI", + "head_sha": "0bb823841fc194923c01427fcbdaced2c2923514", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-17T14:28:27Z", + "repo": "conloca/private", + "run": 39039673811, + "url": "https://github.com/conloca/private/actions/runs/39039673811", + "event": "pull_request", + "pr": 192, + "prHead": "0bb823841fc194923c01427fcbdaced2c2923514", + "mergeSha": "c02858bf15b57020fecc968bd70866d9f6ddb7a4" + }, + { + "name": "CI", + "head_sha": "15b8a5b8959bd8c85276a68777b2666e030e876a", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-15T10:59:37Z", + "repo": "conloca/private", + "run": 38721133962, + "url": "https://github.com/conloca/private/actions/runs/38721133962", + "event": "pull_request", + "pr": 240, + "prHead": "15b8a5b8959bd8c85276a68777b2666e030e876a", + "mergeSha": "29f2ed575c7188a8b5840b8cb3b5db4e72e2fdfe" + }, + { + "name": "CI", + "head_sha": "161ea5724f4e5a8ba88e0d8de1ae32a7226c895f", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-15T07:41:10Z", + "repo": "conloca/private", + "run": 38698806777, + "url": "https://github.com/conloca/private/actions/runs/38698806777", + "event": "pull_request", + "pr": 225, + "prHead": "161ea5724f4e5a8ba88e0d8de1ae32a7226c895f", + "mergeSha": "6f0ab1bde62014378f61dc270df169726fc3ae2d" + }, + { + "name": "CI", + "head_sha": "e5499354d775b827314cb18207a09c73d24244ce", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-17T15:46:49Z", + "repo": "conloca/private", + "run": 39045562323, + "url": "https://github.com/conloca/private/actions/runs/39045562323", + "event": "pull_request", + "pr": 197, + "prHead": "e5499354d775b827314cb18207a09c73d24244ce", + "mergeSha": "c8940860effb75be5c2cae136108f12b2ebb6f83" + }, + { + "name": "CI", + "head_sha": "d335bb38bbacaa194d627eca089b3043c088286f", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-15T16:17:09Z", + "repo": "conloca/private", + "run": 38765245205, + "url": "https://github.com/conloca/private/actions/runs/38765245205", + "event": "pull_request", + "pr": 247, + "prHead": "d335bb38bbacaa194d627eca089b3043c088286f", + "mergeSha": "6cef88cdfa9c65b96582a54e9685d97d0fb950e3" + }, + { + "name": "CI", + "head_sha": "19f29a1f51b7b6845c332cba408b4681bb764f7e", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-17T04:45:56Z", + "repo": "conloca/private", + "run": 39002501897, + "url": "https://github.com/conloca/private/actions/runs/39002501897", + "event": "pull_request", + "pr": 259, + "prHead": "19f29a1f51b7b6845c332cba408b4681bb764f7e", + "mergeSha": "29494248aaf828d6e4ed475bf57a947ad7ddf4d4" + }, + { + "name": "CI", + "head_sha": "984c48c805e1be9c4fda15473e64d1cf8cc9be73", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-15T10:36:18Z", + "repo": "conloca/private", + "run": 38719753633, + "url": "https://github.com/conloca/private/actions/runs/38719753633", + "event": "pull_request", + "pr": 235, + "prHead": "984c48c805e1be9c4fda15473e64d1cf8cc9be73", + "mergeSha": "51fba3c31dc867639763432c7f3a85d291aee9ee" + }, + { + "name": "CI", + "head_sha": "6cb79e630bc92dfad464efdceecaf15c4ca0efa6", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-17T17:43:18Z", + "repo": "conloca/private", + "run": 39053918519, + "url": "https://github.com/conloca/private/actions/runs/39053918519", + "event": "pull_request", + "pr": 229, + "prHead": "6cb79e630bc92dfad464efdceecaf15c4ca0efa6", + "mergeSha": "e8cf5c5256fccf1c2281951930fb9db337bd3328" + }, + { + "name": "CI", + "head_sha": "3b768e22617d2f21501c67f47b9b594f2722d2a9", + "status": "completed", + "conclusion": "success", + "updated_at": "2026-10-23T09:07:05Z", + "repo": "conloca/private", + "run": 39927097274, + "url": "https://github.com/conloca/private/actions/runs/39927097274", + "event": "pull_request", + "pr": 300, + "prHead": "3b768e22617d2f21501c67f47b9b594f2722d2a9", + "mergeSha": "1a9c773b28e1f39ff0b29dfe6488acfb6242eb60" } ], - "storybookPreviews": { - "verifiedAt": "2026-11-05T22:16:30.758703+00:00", - "workflowStatus": "implemented-awaiting-merge-approval", - "pullRequests": [ - { - "author": "alex-mextner", - "headRefOid": "018f52c31332dc3c1055eadfc6dde63be78b9e59", - "isDraft": false, - "number": 404, - "state": "OPEN", - "url": "https://github.com/conloca/private/pull/404" - }, - { - "author": "alex-mextner", - "headRefOid": "591024553d91fb0aeaad8081f9c39064cb024846", - "isDraft": false, - "number": 509, - "state": "OPEN", - "url": "https://github.com/conloca/private/pull/509" - } - ], - "status": "historical", - "historicalNote": "Receipts of an earlier catalogue publication on 5 November 2026. Superseded and not linked from the human reports.", - "segments": [ - { - "segment": "main", - "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/main/", - "sourceSha": "795967bd48a0f1d8f96d87a562b15922ef529775", - "publication": "operator-published", - "deployExit": 0, - "protectionProbeExit": 0 + "designCredits": [ + { + "name": "Saba", + "contribution": "Completed How it works design", + "source": "https://github.com/conloca/private/pull/342", + "sourceCommit": "https://github.com/conloca/landing/commit/9582b68455ae7b6b2d4987c7c93ee32303c76a3f", + "reportedWorkBy": "alex-mextner", + "reportedWork": "Integrated the completed design into the production website", + "includedInOwnerWork": false + } + ], + "inventory": { + "reviewedAt": "2026-11-06", + "window": "2026-10-01..2026-10-31 (GitHub merged: search, UTC)", + "rule": "A pull request is credited when every commit in it is authored by Alex Ultra (alex-mextner). Pull request author may be alex-mextner or smoothbricker; the latter is recorded explicitly. A pull request that mixes in other authors is credited only for Ultra's named commits (attribution commit-scope, mixedAuthors true) or not at all. Automated mirror-sync pull requests are not counted. The pull request count is supporting information, not a complete contribution census.", + "mergedInOctober": { + "hyperide/hyper-saas": 11, + "conloca/private": 183 + }, + "credited": { + "hyperide/hyper-saas": 11, + "conloca/private": 92 + }, + "excludedSummary": { + "total": 91, + "byRepository": { + "hyperide/hyper-saas": 0, + "conloca/private": 91 }, - { - "segment": "pr-404", - "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/pr-404/", - "sourceSha": "018f52c31332dc3c1055eadfc6dde63be78b9e59", - "publication": "operator-published", - "deployExit": 0, - "protectionProbeExit": 0, - "commitStatus": "success" + "byReason": { + "all commits by other contributors": 79, + "automated mirror-sync pull request": 11, + "mixed authorship, own contribution not counted": 1 }, - { - "segment": "pr-489", - "url": "https://pages.hyperide.ai/alex-mextner/conloca-storybook-previews/pr-489/", - "sourceSha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", - "publication": "operator-published", - "deployExit": 0, - "protectionProbeExit": 0, - "commitStatus": "success" - } - ], - "requiresForgeSignIn": true, - "authenticatedProductionBrowserVerified": false, - "verification": "Deployment receipts, exact-head GitHub statuses and anonymous access protection. The same archive was browser-tested on the real host binary locally; that is not production OAuth acceptance.", - "mainSandboxPathFix": "PR404 carries the prefixed sandbox-path fix; main contains the merged integration branch.", - "deployedE2E": "https://github.com/conloca/private/actions/runs/42052900149/job/127344610560" + "localAuditSha256": "fa336d9ba3fa7cefe55a92529fc8fc3d5d0dc19f2e4b0b2f2f68afc59e5e8f73", + "note": "Pull requests that are not ours are counted only in aggregate. The per-pull-request audit is kept locally and is not published." + } }, - "sourceScopes": { - "hyperide/hyper-saas#810": { - "title": "feat(state-lib): headless async toolkit and fail-closed export (HYP-1507)", - "author": "alex-mextner", - "mergeSha": "da611247987cc6b2fbb955857e4cc6f9d1410f8e", - "url": "https://github.com/hyperide/hyper-saas/pull/810", - "files": [ - "server/routes/git.ts", - "server/routes/__tests__/git-push.security.test.ts", - "server/services/git-push-error.ts", - "server/services/__tests__/git-push-tls.test.ts", - "server/utils/git-credentials.ts", - "packages/state-lib/toolkit/src/async-resource.ts", - "packages/state-lib/site/src/lib/highlight.ts", - "packages/state-lib/site/tools/heading-caption.check.mts" + "claims": [ + { + "id": "hyper-extension-release", + "group": "extension-release", + "report": "hyper-2026-10", + "prs": [ + 825 + ], + "coveredPrs": [ + 825 + ], + "evidence": [ + { + "type": "ci-run", + "run": 38834833575, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38834833575" + }, + { + "type": "ci-run", + "run": 38738722190, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38738722190" + }, + { + "type": "diff", + "path": "CHANGELOG.md", + "pr": 825, + "url": "https://github.com/hyperide/hyper-saas/pull/825/files" + } + ] + }, + { + "id": "hyper-git-push", + "group": "git-push", + "report": "hyper-2026-10", + "prs": [ + 810 + ], + "coveredPrs": [ + 810 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810" + }, + { + "type": "tests", + "path": "server/services/__tests__/git-push-tls.test.ts", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810/files" + }, + { + "type": "ci-run", + "run": 38547360197, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360197" + }, + { + "type": "ci-run", + "run": 38547359971, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547359971" + } + ] + }, + { + "id": "hyper-dependencies", + "group": "dependencies", + "report": "hyper-2026-10", + "prs": [ + 837, + 810 + ], + "coveredPrs": [ + 837, + 810 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 837, + "url": "https://github.com/hyperide/hyper-saas/pull/837" + }, + { + "type": "tests", + "path": "vscode-extension/hypercanvas-preview/src/__tests__/HyperMcpServer.test.ts", + "pr": 837, + "url": "https://github.com/hyperide/hyper-saas/pull/837/files" + }, + { + "type": "ci-run", + "run": 38547359971, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547359971" + } + ] + }, + { + "id": "hyper-local-checks", + "group": "local-checks", + "report": "hyper-2026-10", + "prs": [ + 810 + ], + "coveredPrs": [ + 810 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810" + }, + { + "type": "tests", + "path": "scripts/__tests__/conflict-markers.test.ts", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810/files" + } + ] + }, + { + "id": "state-async-toolkit", + "group": "async-toolkit", + "report": "state-lib-2026-10", + "prs": [ + 810 + ], + "coveredPrs": [ + 810 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810" + }, + { + "type": "tests", + "path": "packages/state-lib/toolkit/src/async-resource.ts", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810/files" + }, + { + "type": "ci-run", + "run": 38547360197, + "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360197" + } + ] + }, + { + "id": "state-records", + "group": "records", + "report": "state-lib-2026-10", + "prs": [ + 803 ], - "includedWork": [ - "Headless async toolkit", - "Git push authority, transport policy and typed failure handling", - "Quoted attribute and comment parsing in diagram captions" + "coveredPrs": [ + 803 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 803, + "url": "https://github.com/hyperide/hyper-saas/pull/803" + }, + { + "type": "tests", + "path": "packages/state-lib/runtime/src/record.test.ts", + "pr": 803, + "url": "https://github.com/hyperide/hyper-saas/pull/803/files" + } ] - } - }, - "checks": [ + }, { - "name": "CI", - "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", - "status": "completed", - "conclusion": "success", - "updated_at": "2026-10-14T10:22:11Z", - "repo": "hyperide/hyper-saas", - "run": 38547360197, - "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360197" + "id": "state-ownership", + "group": "ownership", + "report": "state-lib-2026-10", + "prs": [ + 826 + ], + "coveredPrs": [ + 826 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 826, + "url": "https://github.com/hyperide/hyper-saas/pull/826" + }, + { + "type": "tests", + "path": "packages/state-lib/toolkit/src/operation-scope.test.ts", + "pr": 826, + "url": "https://github.com/hyperide/hyper-saas/pull/826/files" + } + ] }, { - "name": "Security Scan", - "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", - "status": "completed", - "conclusion": "success", - "updated_at": "2026-10-14T10:09:02Z", - "repo": "hyperide/hyper-saas", - "run": 38547359971, - "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547359971" + "id": "state-export", + "group": "export", + "report": "state-lib-2026-10", + "prs": [ + 810 + ], + "coveredPrs": [ + 810 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810" + }, + { + "type": "tests", + "path": "packages/state-lib/toolkit/src/export-filesystem.test.ts", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810/files" + } + ] }, { - "name": "State docs reading and interactions", - "head_sha": "d4cca87cee086eead00392f1a662de7065a8019c", - "status": "completed", - "conclusion": "success", - "updated_at": "2026-10-14T10:19:19Z", - "repo": "hyperide/hyper-saas", - "run": 38547360009, - "url": "https://github.com/hyperide/hyper-saas/actions/runs/38547360009" + "id": "state-compiled-entries", + "group": "compiled-entries", + "report": "state-lib-2026-10", + "prs": [ + 802, + 832 + ], + "coveredPrs": [ + 802, + 832 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 802, + "url": "https://github.com/hyperide/hyper-saas/pull/802" + }, + { + "type": "pr-body", + "pr": 832, + "url": "https://github.com/hyperide/hyper-saas/pull/832" + }, + { + "type": "tests", + "path": "packages/state-lib/compiler/src/command.rs", + "pr": 802, + "url": "https://github.com/hyperide/hyper-saas/pull/802/files" + } + ] }, { - "name": "E2E Tests (Deployed Stage)", - "head_sha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", - "status": "completed", - "conclusion": "success", - "started_at": "2026-11-03T11:37:48Z", - "completed_at": "2026-11-03T11:48:51Z", - "repo": "conloca/private", - "run": 41626469902, - "url": "https://github.com/conloca/private/actions/runs/41626469902/job/125893569803", - "job": 125893569803 + "id": "state-cold-import", + "group": "cold-import", + "report": "state-lib-2026-10", + "prs": [ + 834 + ], + "coveredPrs": [ + 834 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 834, + "url": "https://github.com/hyperide/hyper-saas/pull/834" + }, + { + "type": "tests", + "path": "packages/state-lib/experiments/2026-09-19-cow/owned-import.test.ts", + "pr": 834, + "url": "https://github.com/hyperide/hyper-saas/pull/834/files" + } + ] }, { - "name": "E2E Tests (Deployed Stage)", - "head_sha": "018f52c31332dc3c1055eadfc6dde63be78b9e59", - "status": "completed", - "conclusion": "success", - "started_at": "2026-11-05T15:33:02Z", - "completed_at": "2026-11-05T15:42:55Z", - "repo": "conloca/private", - "run": 42052900149, - "url": "https://github.com/conloca/private/actions/runs/42052900149/job/127344610560", - "job": 127344610560 + "id": "state-live-docs", + "group": "live-docs", + "report": "state-lib-2026-10", + "prs": [ + 809, + 833, + 807 + ], + "coveredPrs": [ + 809, + 833, + 807 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 809, + "url": "https://github.com/hyperide/hyper-saas/pull/809" + }, + { + "type": "pr-body", + "pr": 833, + "url": "https://github.com/hyperide/hyper-saas/pull/833" + }, + { + "type": "pr-body", + "pr": 807, + "url": "https://github.com/hyperide/hyper-saas/pull/807" + }, + { + "type": "pr-body", + "pr": 810, + "url": "https://github.com/hyperide/hyper-saas/pull/810" + } + ] }, { - "name": "CI", - "head_sha": "ce20346cf302a70229c8378c583062414994be5d", - "status": "completed", - "conclusion": "success", - "updated_at": "2026-10-27T16:04:21Z", - "repo": "conloca/private", - "run": 40534284367, - "url": "https://github.com/conloca/private/actions/runs/40534284367", - "jobs": [ + "id": "conloca-editor", + "group": "editor", + "report": "conloca-2026-10", + "prs": [ + 299, + 306, + 302, + 296, + 301, + 297 + ], + "coveredPrs": [ + 299, + 306, + 302, + 296, + 307, + 301, + 262, + 297, + 316, + 293, + 295, + 196, + 239, + 248, + 220 + ], + "evidence": [ { - "conclusion": "success", - "head_sha": "ce20346cf302a70229c8378c583062414994be5d", - "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122295162949", - "id": 122295162949, - "name": "Validate", - "status": "completed" + "type": "ci-run", + "run": 39913205421, + "url": "https://github.com/conloca/private/actions/runs/39913205421" }, { - "conclusion": "success", - "head_sha": "ce20346cf302a70229c8378c583062414994be5d", - "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122299074596", - "id": 122299074596, - "name": "E2E Tests (Deployed Stage)", - "status": "completed" + "type": "ci-run", + "run": 39924273295, + "url": "https://github.com/conloca/private/actions/runs/39924273295" }, { - "conclusion": "success", - "head_sha": "ce20346cf302a70229c8378c583062414994be5d", - "html_url": "https://github.com/conloca/private/actions/runs/40534284367/job/122303701660", - "id": 122303701660, - "name": "Deploy Production", - "status": "completed" + "type": "ci-run", + "run": 39886342267, + "url": "https://github.com/conloca/private/actions/runs/39886342267" + }, + { + "type": "ci-run", + "run": 39964824309, + "url": "https://github.com/conloca/private/actions/runs/39964824309" + }, + { + "type": "pr-body", + "pr": 299, + "url": "https://github.com/conloca/private/pull/299" } ] }, { - "conclusion": "success", - "head_sha": "e3ec8ee55ba28030b81d808e2ec45b3d31b83f5c", - "name": "CI", - "status": "completed", - "updated_at": "2026-11-03T11:48:52Z", - "url": "https://github.com/conloca/private/actions/runs/41626469902", - "repo": "conloca/private", - "run": 41626469902 + "id": "conloca-workspace", + "group": "workspace", + "report": "conloca-2026-10", + "prs": [ + 288, + 289, + 192, + 224, + 240, + 225 + ], + "coveredPrs": [ + 288, + 289, + 294, + 305, + 292, + 192, + 224, + 225, + 240, + 253, + 223, + 188, + 191, + 222 + ], + "evidence": [ + { + "type": "ci-run", + "run": 39804895916, + "url": "https://github.com/conloca/private/actions/runs/39804895916" + }, + { + "type": "ci-run", + "run": 39861084298, + "url": "https://github.com/conloca/private/actions/runs/39861084298" + }, + { + "type": "ci-run", + "run": 39039673811, + "url": "https://github.com/conloca/private/actions/runs/39039673811" + }, + { + "type": "ci-run", + "run": 38721133962, + "url": "https://github.com/conloca/private/actions/runs/38721133962" + }, + { + "type": "ci-run", + "run": 38698806777, + "url": "https://github.com/conloca/private/actions/runs/38698806777" + } + ] + }, + { + "id": "conloca-content", + "group": "content", + "report": "conloca-2026-10", + "prs": [ + 197, + 243, + 235, + 247, + 259, + 177 + ], + "coveredPrs": [ + 197, + 243, + 235, + 256, + 259, + 247, + 308, + 228, + 177 + ], + "evidence": [ + { + "type": "ci-run", + "run": 39045562323, + "url": "https://github.com/conloca/private/actions/runs/39045562323" + }, + { + "type": "ci-run", + "run": 38765245205, + "url": "https://github.com/conloca/private/actions/runs/38765245205" + }, + { + "type": "ci-run", + "run": 39002501897, + "url": "https://github.com/conloca/private/actions/runs/39002501897" + }, + { + "type": "ci-run", + "run": 38719753633, + "url": "https://github.com/conloca/private/actions/runs/38719753633" + } + ] + }, + { + "id": "conloca-landing", + "group": "landing", + "report": "conloca-2026-10", + "prs": [ + 342, + 231 + ], + "coveredPrs": [ + 342, + 231 + ], + "evidence": [ + { + "type": "ci-run", + "run": 40534284367, + "url": "https://github.com/conloca/private/actions/runs/40534284367" + }, + { + "type": "ci-run", + "run": 40505784923, + "url": "https://github.com/conloca/private/actions/runs/40505784923" + }, + { + "type": "pr-body", + "pr": 342, + "url": "https://github.com/conloca/private/pull/342" + } + ] + }, + { + "id": "conloca-coverage", + "group": "coverage", + "report": "conloca-2026-10", + "prs": [ + 217, + 244, + 304, + 229, + 300, + 320 + ], + "coveredPrs": [ + 217, + 244, + 257, + 304, + 300, + 309, + 229, + 226, + 238, + 261, + 320, + 198, + 234, + 221, + 236, + 201, + 254 + ], + "evidence": [ + { + "type": "ci-run", + "run": 39053918519, + "url": "https://github.com/conloca/private/actions/runs/39053918519" + }, + { + "type": "ci-run", + "run": 39927097274, + "url": "https://github.com/conloca/private/actions/runs/39927097274" + }, + { + "type": "pr-body", + "pr": 244, + "url": "https://github.com/conloca/private/pull/244" + }, + { + "type": "pr-body", + "pr": 257, + "url": "https://github.com/conloca/private/pull/257" + } + ] + }, + { + "id": "conloca-stage", + "group": "stage", + "report": "conloca-2026-10", + "prs": [ + 200, + 241, + 169, + 155 + ], + "coveredPrs": [ + 200, + 155, + 168, + 169, + 193, + 241, + 258 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 200, + "url": "https://github.com/conloca/private/pull/200" + }, + { + "type": "pr-body", + "pr": 241, + "url": "https://github.com/conloca/private/pull/241" + }, + { + "type": "tests", + "path": "tooling/pr-stage-gc.test.ts", + "pr": 200, + "url": "https://github.com/conloca/private/pull/200/files" + } + ] + }, + { + "id": "conloca-gates", + "group": "gates", + "report": "conloca-2026-10", + "prs": [ + 251, + 166, + 263, + 303, + 311, + 255, + 315 + ], + "coveredPrs": [ + 251, + 166, + 167, + 263, + 303, + 322, + 319, + 260, + 314, + 311, + 313, + 255, + 290, + 315, + 174, + 230, + 194, + 232, + 129, + 158, + 175, + 176, + 178, + 195, + 204, + 233, + 237, + 298 + ], + "evidence": [ + { + "type": "pr-body", + "pr": 251, + "url": "https://github.com/conloca/private/pull/251" + }, + { + "type": "pr-body", + "pr": 263, + "url": "https://github.com/conloca/private/pull/263" + }, + { + "type": "pr-body", + "pr": 303, + "url": "https://github.com/conloca/private/pull/303" + }, + { + "type": "pr-body", + "pr": 311, + "url": "https://github.com/conloca/private/pull/311" + }, + { + "type": "pr-body", + "pr": 194, + "url": "https://github.com/conloca/private/pull/194" + } + ] } ], - "designCredits": [ + "figures": [ { - "name": "Saba", - "contribution": "Completed How it works design", - "source": "https://github.com/conloca/private/pull/342", - "sourceCommit": "https://github.com/conloca/landing/commit/9582b68455ae7b6b2d4987c7c93ee32303c76a3f", - "reportedWorkBy": "alex-mextner", - "reportedWork": "Integrated the completed design into the production website", - "includedInOwnerWork": false + "report": "hyper-2026-10", + "measure": "Extension high-severity npm audit, exit status (not an issue count)", + "before": "7, gate failing", + "after": "0", + "pr": 837, + "source": "#837 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "hyper-2026-10", + "measure": "Root bun audit at high severity", + "before": "Six advisories: MCP SDK, dompurify, happy-dom, undici, zod, body-parser", + "after": "No vulnerabilities reported", + "pr": 837, + "source": "#837 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "hyper-2026-10", + "measure": "MCP request body limit", + "before": "SDK limits did not apply to bodies the extension parsed itself", + "after": "4 MiB cap, 413 before any server is built", + "pr": 837, + "source": "#837 changelog entry and tests", + "repo": "hyperide/hyper-saas" + }, + { + "report": "hyper-2026-10", + "measure": "Extension release", + "before": "0.1.74", + "after": "0.1.75, tag pushed 16 Oct 2026 01:23 UTC", + "pr": 825, + "source": "Publish run 38834833575", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Point edit, 10,000-item benchmark fixture, Node median", + "before": "4.148 ms", + "after": "0.006 ms", + "pr": 802, + "source": "#802 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Move, 10,000-item benchmark fixture, Node median", + "before": "4.175 ms", + "after": "0.008 ms", + "pr": 802, + "source": "#802 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Entry size, 512-command fixture: raw / gzip / Brotli", + "before": "71,069 / 9,525 / 6,596 bytes", + "after": "42,284 / 8,619 / 5,779 bytes", + "pr": 802, + "source": "#802 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Task-completion handler, 1,200 visible rows, median", + "before": "63.2 ms Chromium, 93 ms WebKit", + "after": "1.0 ms Chromium, 1 ms WebKit", + "pr": 832, + "source": "#832 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Next animation frame, 1,200 visible rows", + "before": "311 ms Chromium, 546 ms WebKit", + "after": "13.8 ms Chromium, 7 ms WebKit", + "pr": 832, + "source": "#832 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Chromium retained heap, 10,000 rows, 1,200 visible", + "before": "15.58 MB", + "after": "4.73 MB", + "pr": 832, + "source": "#832 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Whole-document copies during cold load", + "before": "3", + "after": "2", + "pr": 834, + "source": "#834 body", + "repo": "hyperide/hyper-saas" + }, + { + "report": "state-lib-2026-10", + "measure": "Diagram caption in the docs site", + "before": "Quoted attribute text shown before the label", + "after": "Only the intended label", + "pr": 810, + "source": "Screenshots below", + "repo": "hyperide/hyper-saas" + }, + { + "report": "conloca-2026-10", + "measure": "Image movement on How it works during delayed hydration (browser test)", + "before": "397.587 px", + "after": "0 px across 53 frames", + "pr": 342, + "source": "#342 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "PR-stage Durable Object namespaces after the first eviction run", + "before": "About 170 leaked; Deploy Stage failing with error 10067", + "after": "386 of 500", + "pr": 200, + "source": "#200 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "Durable Object namespaces per stage", + "before": "10", + "after": "9", + "pr": 241, + "source": "#241 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "CMS site snapshot import", + "before": "33.6 MB in one call, over the 32 MiB limit", + "after": "Parts of at most 16 MiB", + "pr": 259, + "source": "#259 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "Anti-slop findings on one rebased pull request", + "before": "141, of which 116 on untouched lines", + "after": "Only changed lines counted", + "pr": 263, + "source": "#263 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "Resize events during a story play", + "before": "30 and 11", + "after": "0 and 0", + "pr": 257, + "source": "#257 body", + "repo": "conloca/private" + }, + { + "report": "conloca-2026-10", + "measure": "Summed test time over 141 tasks", + "before": "1,164 s", + "after": "1,079 s and 1,097 s", + "pr": 194, + "source": "#194 body", + "repo": "conloca/private" } ] } diff --git a/reports/conloca-2026-10/index.html b/reports/conloca-2026-10/index.html index edbdeaf..4e4c984 100644 --- a/reports/conloca-2026-10/index.html +++ b/reports/conloca-2026-10/index.html @@ -6,273 +6,11 @@ Conloca: October 2026 - +
- -
-

- Work by Ultra / Mextner. October 2026 results; status checked 5 - November. Source links may require repository access. -

-
-

Merged

-
-
-

Editor actions

-

- Restored block dragging and Undo after adding a block. Dashboard - New Page opens the create dialog. New unpublished pages display - Draft, including after translation edits. -

-

- #299 - · - #306 - · - #302 - · - #296 - · - #307 -

-
-
-

Correct workspace and branch

-

- Invites open the workspace the user joined. Writes stay on the - repository, branch and site shown in their tab, even when another - tab changes workspace. -

-

- #288 - · - #289 - · - #192 - · - #224 -

-
-
-

Content and media safety

-

- CMS commits preserve unrelated staged files. Asset moves do not - overwrite an existing file. Draft images render in the canvas, and - primary-root MDX saves return to the original file. -

-

- #197 - · - #243 - · - #235 -

-
-
-

How it works page

-

- Integrated Saba’s completed design into the production site. Added - responsive, enlarged-text and reduced-motion checks, and removed - the visible jump during delayed hydration. -

-

- #342 - · Production -

-
-
-

Storybook and browser coverage

-

- Added standalone CMS and composed app catalogues, interactive - state stories, desktop/mobile captures, and deployed-stage checks - for editor routes and primary actions. -

-

- #217 - · - #244 - · - #226 - · - #300 - · - #304 - · - #309 -

-
-
-
-
-

Theme picker preview

-

- Current preview, 5 November. Separate from the October merges above. -

-
- IMPLEMENTED · NOT MERGED -

Documentation theme picker

-

- Added Light, Dark and System controls with visible selection, - keyboard navigation and touch targets. Current-head CI and - deployed-stage E2E passed; the change awaits team review. -

-

- #489 - · - Preview - · - Deployed E2E -

-
-
-
-

Before / after

-

- Theme control on production and PR #489, captured at the same 1440px - viewport on 5 November. The new control is on the preview only. -

- -
-
-

Checks

-

- How it works: production deployment and E2E - · - Interactive Storybook scenarios and screenshot workflow - · - Theme-picker deployed-stage E2E. -

-
- +

Conloca: October 2026

Editor fixes, workspace safety, content integrity, the production How it works page

Ultra / Mextner · October 2026

Overview

Conloca is a visual CMS for Astro sites: editors change pages in the browser and the content is committed to Git. In October Ultra / Mextner delivered fixes and checks across the editor, invites and sign-in, content and media handling, the production site and the delivery pipeline, in 92 merged pull requests, one of them credited only for Ultra’s own commits.

The documentation theme picker is implemented and checked but awaits team review, so it is shown separately below.

397.6 → 0 px
How it works image movement during delayed hydration, in the browser test of #342
33.6 MB
snapshot that now imports in bounded parts of at most 16 MiB (#259)
160 files
changed in the move to validators generated from the TypeScript types (#251)

What we delivered

Editor and page actions

Dragging blocks into a page, Undo after adding a block and the Dashboard New Page button now work. A disabled Preview button explains why it is unavailable. Never-published pages read Draft in the Pages list and on the Dashboard. A route or schema error shows a CMS error page or notice instead of the developer screen, and the branch-name field formats as you type. These were everyday actions that did nothing or showed the wrong state.

Technical detail
  • Puck ignores a press on a real <button>, so the block-list item is a div role="button" again, and an empty page says how to add a block (#299). Undo and Redo remove and restore a block added by drag or double-click (#306).
  • The Dashboard New Page button opens the create-page dialog in place (#302). One pageStatusOf() and a LocaleVersion.unpublished marker decide page status, and saving a new translation keeps a never-published page a draft (#296, #307).
  • A route that fails to render shows RouteErrorPage, and a site schema that is not a generated host schema shows a notice instead of crashing the CMS (#301, #293, #295). The disabled Preview button shows its explanation when clicked (#262).
  • The New branch field lowercases, hyphenates and keeps the caret in place as you type (#297, #316). The editor opens pages with no English variant (#196), and draft previews parse records with each collection’s schema so dates and defaults match the build (#248).
  • Frontmatter keys such as __proto__.polluted cannot mutate Object.prototype, while own-data keys, including legitimate constructor and prototype names, are kept (#239). The sign-in divider is readable in dark mode; login-theme.spec.ts checks light and dark at 390 and 1280 px (#220).

Key pull requests: #299 · #306 · #302 · #296 · #301 · #297 · 15 pull requests in this group, all in the source record · CI run for #299 · CI run for #302 · CI run for #296

Invites, tabs and sign-in stay in the right place

Accepting an invite lands in the invited workspace, from both the in-app button and the emailed link. Each editor tab sends its repository, branch and site with every write, and the server rejects a mismatch with a 409 instead of writing to the wrong place. Tabs of one browser origin that refresh at the same moment share one token rotation instead of revoking the whole token family.

Technical detail
  • Mutations carry X-Conloca-Editor-Repo, -Branch and -Site headers. The worker answers 409 workspace-mismatch before any billing, storage or Git work, and the tab re-enters its own branch and retries once (#192, #224).
  • Accept waits at most 5 seconds for the membership flush and the Org Durable Object’s alarm delivers the rest; an invite screen that would stay on “accepting” is released after 20 seconds (#292, #305). A deployed-stage proof, invite-landing.spec.ts, covers an invitee who already has a workspace (#294).
  • A second use of a refresh cookie within 10 seconds gets the live token from the rotation chain, and the browser refreshes under a Web Lock so same-origin tabs send one request per rotation (#240). An OAuth failure shows its failure screen instead of looping (#225).
  • Splitting the sign-in and Members screens into props-only views fixed a double submit that requested two sign-in links and a double click that sent two invitations (#253, #223).
  • Cloudflare Access configuration fails closed with 401 when only one of its two settings is present (#191). Overlay rows for pages deleted in Git are pruned (#188). Workspace and flag types are narrowed instead of cast (#222).

Key pull requests: #288 · #289 · #192 · #224 · #240 · #225 · 14 pull requests in this group, all in the source record · CI run for #288 · CI run for #289 · CI run for #192

Scoped content commits, safe asset moves and correct write-back

CMS commits include only content files, so other people’s staged work is left out, and an asset move claims its destination instead of overwriting an existing file. Draft images render in the canvas before Publish, and a docs-root page is written back to the file it was read from. The hosted preview shows pages committed after its build, and a site snapshot over Cloudflare’s 32 MiB call limit imports in bounded parts.

Technical detail
  • CMS commits build their tree in a private index seeded from HEAD and move HEAD by compare-and-swap with update-ref, so a concurrent commit is not reverted. Asset moves run one at a time and claim the destination with a hard link. Tests use real temporary repositories: foreign staged files, two concurrent instances, a held index.lock and concurrent moves racing for one name (#197).
  • Draft images are served from /api/v1/assets/draft/<folder>/<file> while stored data keeps the canonical /assets/... reference (#243). A docs-root MDX page used to be written to a shadow file; mdx-pages-root.test.ts covers edit, delete, create-after-delete and a collision (#235).
  • The hosted preview records its own buildCommit and sends it as ?build=; the worker diffs that commit against the branch head and matches entries by blob id. A deployed-stage test commits a title without redeploying and expects the new heading (#247, spec change #228).
  • The depth-1 snapshot of one pull request packs to about 33.6 MB, over the 32 MiB RPC limit. It now lands in parts of at most 16 MiB with the tree and commit last, and a live check against github.com imported the full closure of 4,836 objects (#259). A missing base tree is fetched by object id instead of failing the import (#256).
  • Org import now always retries the tracker reconcile when a ref already matches upstream, so a stale preview session recovers (#177). Only three of Ultra’s 29 commits in #177 are credited: the repair, its at-head regression test and the browser publication proof. The vocabulary sample stays off the Git lookup behind the unpublished marker (#308).

Key pull requests: #197 · #243 · #235 · #247 · #259 · #177 · 9 pull requests in this group, all in the source record · CI run for #197 · CI run for #247 · CI run for #259

The finished How it works page is on conloca.com

The production How it works page uses the completed design: a four-step flow with MDX, JSON and editor visuals, twelve responsive images and an install banner that survives 200% text. The design is by Saba; our work is the integration into the production site and its checks. In the pull request’s delayed-hydration test, images moved 397.6 px before the fix and 0 px after it.

Technical detail
  • The twelve PNGs were imported byte for byte, with SHA-256 and byte lengths checked on the preview. Existing routes, app links, docs links and install tabs are kept, and text is darkened where the original failed contrast (#342).
  • The test measured 397.587 px of movement before and 0 px across 53 frames after. Twenty-one website targets and 50 browser checks were rerun.
  • The merge to the main branch ran Validate, deployed-stage browser tests and Deploy Production, all successful. Locally, the split-port development stack redirects backend landings to the app and keeps published media on local origins (#231).

Key pull requests: #342 · #231 · CI run for #342 · conloca.com/how-it-works

Browser and story coverage for the editor

The CMS and the app each build a static Storybook catalogue in CI, and state stories cover save, sync and workspace status, the page list and the conflict dialogs. Deployed-stage browser tests walk every CMS route, create a branch through the Branch menu, confirm a new page reads Draft and check that typed text survives reopening the editor in both themes. CI keeps the proof folder of every deployed-stage run.

Technical detail
  • State stories render the real components with fixtures that stop at HostClient and the content API fetch, so nothing reaches the network. Counts: SaveSlot 6 plus phone, SyncStatusSlot 8 plus phone, WorkspaceStatusSlot 8 plus phone, CmsHostPlaceholder 9 (#244). CI saves a screenshot of every story at 1280 × 800 and 390 × 844. The app Storybook runner now compiles Tailwind, because classes such as max-sm:hidden were missing from all app examples.
  • A flaky failure in the Several Locales scenario, caused by a viewport resize landing mid-play, is gone: resizes during play went from 30 and 11 to 0 and 0 in the probe runs (#257).
  • The deployed-stage job keeps its proof folder on every run and the Playwright report on failed runs (#320). A manual staging proof workflow adds two new legs (#261), and the emitted billing deploy bundle runs in CI (#238).
  • Real-engine and typed tests for Git paths, billing identity mapping, workspace recovery and memory behaviour were added or made deterministic (#198, #234, #221, #236, #201, #254). Branch creation and the Draft check are in #229 and #309, and the editor-reopen check is in #226.

Key pull requests: #217 · #244 · #304 · #229 · #300 · #320 · 17 pull requests in this group, all in the source record · CI run for #229 · CI run for #300

A pull-request stage environment that keeps working

Pull-request stages are cleaned up on a schedule with capacity reporting and stage leases, which brought the Cloudflare namespace count to 386 of 500 after the first eviction run. Each stage uses one Durable Object namespace fewer, and each deployment attempt gets its own preview fixture without resetting drafts. Before this, Deploy Stage was failing account-wide with Cloudflare error 10067 after about 170 namespaces leaked from closed pull requests.

Technical detail
  • A scheduled workflow runs every six hours, reports capacity and fails above 400 of 500 namespaces. Drafts hold a stage for 24 hours and ready pull requests for 72 hours; keep-stage and evict-stage override that. tooling/pr-stage-gc.test.ts checks that only closed same-repo pull requests are selected (#200).
  • Deleting the unused EventLogDO takes each stage from 10 namespaces to 9, which the pull request estimates moves live capacity from about 48 to about 53 stages (#241).
  • Readiness rejects dirty overlays and divergent session heads, and older attempt orgs are retired after 24 hours (#169). A read-only inventory of legacy preview resources deletes nothing (#155). A Deploy Production failure on a missing generated contracts module was fixed (#258), and E2E runs leave branches clean (#193).

Key pull requests: #200 · #241 · #169 · #155 · 7 pull requests in this group, all in the source record

Typed contracts and delivery gates

Project validation moved from hand-written Zod schemas to validators generated from the TypeScript types with Typia, in a 160-file change; we adapted the existing generated-contract work to the editor, loader, CLI and sites. CI gates now block only the debt a change adds, and dependency review, mirror sync and the devenv install kept running when GitHub-hosted jobs could not start. DOMPurify moved to 3.4.17 for a critical advisory.

Technical detail
  • Site schemas become HostSchema<T>: a generated validator with JSON Schema metadata. The editor builds its forms from that metadata, and the loader reports field paths. content-api drops zod and conformance rule A76 forbids it in every workspace package (#251).
  • Before #263 a rebased pull request got 141 findings, 116 of them on lines it never touched; the gate now looks at changed lines. A per-file type-assertion ratchet refuses to count when a library has no dist, because counts differ without built declarations (2,311 versus 2,325) (#263, #303, #322, #319).
  • GitHub-hosted jobs stopped starting from about 23 October because of a billing block, so dependency review and mirror sync moved to the self-hosted pool. devenv main had moved to a Nix version the cache does not serve, so the install is pinned to v2.4.0. A test now fails on unjustified sudo in workflows (#311, #313, #255, #314).
  • DOMPurify has a failing-then-passing floor test (#290, #315). Tests use a RAM-backed temp directory and Git without fsync: summed over 141 test tasks, time went from 1,164 s to 1,079 s and 1,097 s, about 6% less (#194). Bun installs stay out of Bun’s global store (#232).
  • Smaller changes in this group: Rig verification contract and commands (#174, #230), warning-only pre-push anti-slop check (#167), changed-source gates in CI (#166), dependency review green on private (#260), mirror and tooling fixes (#129, #158, #175, #176, #178, #195, #204, #233, #237, #298).

Key pull requests: #251 · #166 · #263 · #303 · #311 · #255 · #315 · 28 pull requests in this group, all in the source record

Before and after in numbers

Each row compares the state before the change with the state after it. Figures are taken from the pull request named in the last column.

MeasureBeforeAfterSource
Image movement on How it works during delayed hydration (browser test)397.587 px0 px across 53 frames#342 body
PR-stage Durable Object namespaces after the first eviction runAbout 170 leaked; Deploy Stage failing with error 10067386 of 500#200 body
Durable Object namespaces per stage109#241 body
CMS site snapshot import33.6 MB in one call, over the 32 MiB limitParts of at most 16 MiB#259 body
Anti-slop findings on one rebased pull request141, of which 116 on untouched linesOnly changed lines counted#263 body
Resize events during a story play30 and 110 and 0#257 body
Summed test time over 141 tasks1,164 s1,079 s and 1,097 s#194 body

Awaiting team review: theme picker

Opened in November and separate from the October merges above. Implemented and checked, not merged.

IMPLEMENTED · NOT MERGED

Documentation theme picker

The documentation site’s native Auto dropdown is replaced by Light, Dark and System controls with a visible selection, keyboard navigation and touch targets. The head of the pull request passed its deployed-stage browser tests, and the preview site is live. The change awaits team review.

#489 · Preview · Deployed E2E

Before and after

The theme control on production and on the PR #489 preview, both captured at 1440 px on 5 November. On a phone the pictures show the header where the control sits; tap one to open the full capture.

Proof

Hosted CI runs for the final commit of each pull request, or for the merge commit where noted.

Work by Ultra / Mextner (GitHub alex-mextner, Alex Ultra). Pull requests merged 1 to 31 October 2026 are credited by commit authorship. Status checked 6 November. Source links may require repository access.

Attribution: every commit in these pull requests is by Ultra, except #177. #167, #168 and #169 were opened from the smoothbricker account and merged by alex-mextner. #177 is credited only for three of Ultra’s 29 commits there: the stale preview-session repair, its at-head regression test and the browser publication proof. Pull requests whose commits are by other authors are counted only in aggregate in the source record.

All merged pull requests counted here are listed with their authors and merge commits in the source record.

diff --git a/reports/hyper-2026-10/index.html b/reports/hyper-2026-10/index.html index 9e1bc66..12a619f 100644 --- a/reports/hyper-2026-10/index.html +++ b/reports/hyper-2026-10/index.html @@ -6,98 +6,11 @@ HyperIDE: October 2026 - +
- -
-

- Work by Ultra / Mextner. October 2026 results; status checked 5 - November. Source links may require repository access. -

-
-

Merged

-
-
-

Extension 0.1.75 release cut

-

- Updated the extension version and changelog. The release - preparation is merged into main. -

-

- #825 -

-
-
-

Dependency fixes

-

- Updated the extension and root dependencies, added dependency - regression tests, and bounded MCP request handling. -

-

- #837 -

-
-
-

Safer Git push

-

- Bound push credentials to the checked project, preserved its - transport settings, and kept authentication failures out of raw - logs. This was part of #810, alongside the toolkit and docs - changes in the StateLib report. -

-

- #810 -

-
-
-
-
-

StateLib

-

- The async toolkit, immutable records, operation ownership, - complete-entry compiler and cold-import changes are covered in the - separate StateLib report. -

-
-
-

Checks

-

- The - tests, types and extension build - and - security scan - passed for the merged #810 change. -

-
- +

HyperIDE: October 2026

Extension 0.1.75, Git push hardening, dependency audits

Ultra / Mextner · October 2026

Overview

Published extension 0.1.75 to the VS Code Marketplace and Open VSX. Git push now isolates credentials and keeps a project’s transport settings. The extension and root dependency audits pass at high severity as recorded in #837, and the local pre-commit checks run on a stock Ubuntu shell.

The async state toolkit from the same pull request is in the StateLib report.

0.1.75
extension published to the VS Code Marketplace and Open VSX on 16 October
4 MiB
cap on one MCP request body; larger requests get a 413 (#837)
8 of 8
Lefthook jobs passed on native Ubuntu in 15.41 s at the #810 revision
0 findings
Semgrep, 177 rules over 2,820 targets, at the 14 October revision of #810

What we delivered

Extension 0.1.75 is published

We cut 0.1.75, tagged it ext-v0.1.75 and published it to Open VSX and the VS Code Marketplace on 16 October. The publish run validated the version, built the VSIX and confirmed that both registries list the tag. The release carries the changes the team had merged since 0.1.74; the release cut and its publication are ours.

Technical detail
  • Version and lockfile set to 0.1.75 with a 24-line [0.1.75] changelog entry dated 15 October.
  • The Publish VS Code Extension run started 16 October 01:23 UTC on the tag, and every step succeeded, including "Verify both registries have the tagged version".
  • The pull request’s own CI run passed lint, types, tests and the extension production build on its final commit.

Key pull requests: #825

Git push isolates credentials and preserves transport settings

Push credentials now come only from the checked project, the project’s TLS and transport settings are kept, and Git configuration inherited from the environment is refused. Credential helpers are reset for each operation and temporary credentials are removed afterwards. Failures come back as a clear authentication or pull-needed response instead of raw Git output.

Technical detail
  • Push authority comes from checkedProject; both push paths run without interactive prompts (server/utils/git-credentials.ts, server/services/git.ts).
  • Typed failures keep the 401 needsAuth and 409 needsPull responses without exposing raw diagnostics (server/services/git-push-error.ts).
  • Tests include git-push-tls.test.ts, git-credential-policy.test.ts, git-credentials-security.test.ts and git-push.security.test.ts. Two cases: a file-transport restriction that a credentialed push does not weaken, and a trusted Perl pre-push hook that does not load credential-capturing code through inherited configuration.
  • At the recorded 14 October revision the pull request lists 137 focused Git, Hono and CI tests passing, and 7,831 application tests passing on the parent commit.

Key pull requests: #810

Dependency audits and MCP request limits

The pull request records the extension’s high-severity npm audit and the root application’s high-severity bun audit both passing. The extension’s MCP endpoint now rejects request bodies over 4 MiB with a 413 before it builds a server, because the SDK’s own limits do not apply to bodies the extension parses itself.

Technical detail
  • Extension: @modelcontextprotocol/sdk moved to 1.32 and the markdown-it advisory was cleared with a non-force npm audit fix; the @hono/node-server override stays within its major version (#837).
  • Root: zod, happy-dom, dompurify and undici were updated for advisories in the MCP SDK, DOMPurify, happy-dom, undici, zod and body-parser (#837).
  • HyperMcpServer.ts counts streamed bodies as well as declared lengths. MAX_MCP_BODY_BYTES is 4 MiB and maxToolInputElements is 50,000. New tests send a 4 MiB padded body, a 16 MiB declared body and eight 1 MiB chunks.
  • #810 added a Security Scan workflow with a dependency audit and Semgrep; it passed on the 14 October revision, where the pull request records Semgrep running 177 rules over 2,820 targets with no findings.

Key pull requests: #837 · #810

Local pre-commit checks run on a stock Ubuntu shell

The staged-content conflict-marker check now works under dash, the default shell on Ubuntu. All eight Lefthook jobs passed on native Ubuntu in 15.41 seconds, so the checks that guard each commit run there.

Technical detail
  • Fixes are in ci/local-checks.sh and lefthook.yml, covered by scripts/__tests__/conflict-markers.test.ts and ci/local-checks.test.cjs.

Key pull requests: #810

Before and after in numbers

Each row compares the state before the change with the state after it, at the revision recorded in the pull request named in the last column.

MeasureBeforeAfterSource
Extension high-severity npm audit, exit status (not an issue count)7, gate failing0#837 body
Root bun audit at high severitySix advisories: MCP SDK, dompurify, happy-dom, undici, zod, body-parserNo vulnerabilities reported#837 body
MCP request body limitSDK limits did not apply to bodies the extension parsed itself4 MiB cap, 413 before any server is built#837 changelog entry and tests
Extension release0.1.740.1.75, tag pushed 16 Oct 2026 01:23 UTCPublish run 38834833575

Proof

Hosted CI runs for the final commit of each pull request, or for the merge commit where noted.

Work by Ultra / Mextner (GitHub alex-mextner, Alex Ultra). Pull requests merged 1 to 31 October 2026 are credited by commit authorship. Status checked 6 November. Source links may require repository access.

All merged pull requests counted here are listed with their authors and merge commits in the source record.

diff --git a/reports/shared/october-own-20261106.css b/reports/shared/october-own-20261106.css new file mode 100644 index 0000000..4a65e61 --- /dev/null +++ b/reports/shared/october-own-20261106.css @@ -0,0 +1,294 @@ +.report-section { + margin: 30px 0; +} +.report-section p, +.report-section li { + line-height: 1.65; + color: var(--text-dim); +} +.report-section p { + margin: 10px 0; +} +.report-section h2 { + margin-bottom: 14px; +} +.report-section h3 { + margin: 0 0 8px; + font-size: 1.08rem; +} +.report-section strong { + color: var(--text); +} +.results { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); + gap: 16px; +} +.result { + background: var(--card); + border: 1px solid var(--border); + border-radius: 10px; + padding: 20px; +} +.result p:last-child { + margin-bottom: 0; +} +.refs { + font-size: 0.85rem; +} +.byline { + color: var(--text-dim); + font-size: 0.85rem; + margin: 20px 0; +} +.status-label { + display: inline-block; + border: 1px solid var(--border); + border-radius: 5px; + font-size: 0.75rem; + padding: 4px 8px; + margin-bottom: 12px; +} +.gallery { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; + margin-top: 18px; +} +.gallery figure { + margin: 0; + background: var(--card); + border: 1px solid var(--border); + border-radius: 8px; + overflow: hidden; +} +.gallery img { + display: block; + width: 100%; + height: auto; +} +.gallery figcaption { + padding: 12px 14px; + color: var(--text-dim); + font-size: 0.85rem; + line-height: 1.5; +} +.overview { + margin-top: 8px; +} +.overview > p { + max-width: 78ch; + font-size: 1.02rem; +} +.overview .summary-grid { + margin: 22px 0 0; +} +.overview .summary-card { + text-align: left; + padding: 16px 18px; +} +.overview .summary-card:hover { + transform: none; + border-color: var(--border); +} +.overview .summary-card .value { + font-size: 1.7rem; + line-height: 1.2; + overflow-wrap: anywhere; +} +.overview .summary-card .label { + line-height: 1.45; +} +.outcomes { + display: grid; + gap: 18px; +} +.outcome { + background: var(--card); + border: 1px solid var(--border); + border-radius: 10px; + padding: 22px 24px; +} +.outcome h3 { + font-size: 1.2rem; + color: var(--text); +} +.outcome p { + max-width: 78ch; +} +.outcome .why { + color: var(--text-dim); +} +.outcome details { + margin-top: 12px; + border-top: 1px solid var(--border); + padding-top: 10px; +} +.outcome summary { + cursor: pointer; + color: var(--text); + font-size: 0.9rem; + font-weight: 600; +} +.outcome ul { + margin: 10px 0 0 20px; +} +.outcome li { + font-size: 0.92rem; + margin: 6px 0; +} +.outcome code, +.figures code { + background: rgba(110, 118, 129, 0.15); + border-radius: 4px; + padding: 1px 5px; + overflow-wrap: anywhere; +} +.figures { + width: 100%; + border-collapse: collapse; + font-size: 0.92rem; + margin-top: 8px; +} +.figures th, +.figures td { + text-align: left; + vertical-align: top; + padding: 10px 12px; + border-bottom: 1px solid var(--border); + color: var(--text-dim); +} +.figures th { + color: var(--text); + font-weight: 600; +} +.figures td:first-child { + color: var(--text); +} +.figures caption { + text-align: left; + color: var(--text-dim); + font-size: 0.85rem; + padding-bottom: 8px; +} +.crop { + display: block; +} +.report-nav { + display: flex; + gap: 18px; + flex-wrap: wrap; + margin: 24px 0; +} +a { + overflow-wrap: anywhere; +} +.fade-in { + opacity: 1; + transform: none; +} +footer { + border-top: 1px solid var(--border); + margin-top: 36px; + padding: 22px 0 36px; + color: var(--text-dim); + font-size: 0.8rem; +} +@media (max-width: 650px) { + .figures, + .figures tbody, + .figures tr, + .figures td { + display: block; + width: 100%; + } + .figures thead { + display: none; + } + .figures tr { + border: 1px solid var(--border); + border-radius: 8px; + margin: 0 0 12px; + padding: 8px 4px; + background: var(--card); + } + .figures td { + border-bottom: 0; + padding: 5px 12px; + } + .figures td::before { + content: attr(data-label) ": "; + color: var(--text-dim); + font-size: 0.78rem; + } + .figures td:first-child::before { + content: ""; + } + .outcome { + padding: 18px 16px; + } + .crop { + position: relative; + aspect-ratio: 16 / 9; + overflow: hidden; + } + .crop img { + position: absolute; + max-width: none; + } + .crop-tr img { + right: 0; + top: 0; + width: 360%; + } + .crop-tl img { + left: -19.7%; + top: -30%; + width: 281%; + } + + .gallery { + grid-template-columns: 1fr; + } + .container { + padding-left: 16px; + padding-right: 16px; + } + .result { + padding: 17px; + } + .report-nav { + margin: 12px 0 4px; + gap: 6px 16px; + } + .report-header { + padding: 12px 0 16px; + } + .report-header h1 { + font-size: 1.6rem; + } + .report-header .meta { + gap: 6px 14px; + } + .byline { + margin: 12px 0; + } + .report-section { + margin: 10px 0; + padding: 12px 0; + } + .report-section h2 { + font-size: 1.35rem; + margin-bottom: 10px; + } +} +@media print { + .fade-in { + opacity: 1 !important; + transform: none !important; + } + .result, + figure { + break-inside: avoid; + } +} diff --git a/reports/state-lib-2026-10/index.html b/reports/state-lib-2026-10/index.html index 79343d4..70080a6 100644 --- a/reports/state-lib-2026-10/index.html +++ b/reports/state-lib-2026-10/index.html @@ -6,180 +6,11 @@ StateLib: October 2026 - +
- -
-

- Work by Ultra / Mextner. October 2026 results; status checked 5 - November. Source links may require repository access. -

-
-

Merged

-
-
-

Async toolkit and immutable records

-

- Added framework-neutral async state and validated immutable - records on the existing Runtime. Production and testing exports - are separate. -

-

- #810 - · - #803 -

-
-
-

Operation ownership

-

- Prevented superseded async work from publishing state or feedback - under a newer operation. -

-

- #826 -

-
-
-

Complete application entries

-

- Added fixed-entry compilation and output rollback. Immutable save - capture and keyed-row completion updates avoid redundant document - work. -

-

- #832 -

-
-
-

One less full-document copy

-

- Certified a JSON field while importing it, then adopted that exact - root. The normal copying replace API keeps its existing behavior. -

-

- #834 -

-
-
-

Documentation fixes

-

- Preserved ordinary API names in generated docs and fixed quoted - attributes leaking into diagram captions. -

-

- #807 - · - #810 -

-
-
-
-
-

Before / after

-

- Diagram caption rendering, captured for #810. The same fixture now - displays the label without leaking attribute text. -

- -

- Original browser captures from 14 October, retained with - #810. -

-
-
-

Checks

-

- Documentation browser tests - · - Runtime, types and build checks. Source and test details for compilation and import are attached to - #832 - and - #834. -

-
- +

StateLib: October 2026

Async state, immutable records, operation ownership, compiled entries

Ultra / Mextner · October 2026

Overview

StateLib, in packages/state-lib of the HyperIDE repository, is a synchronous state Runtime with a Rust compiler for application entries and a documentation site with live examples. In October Ultra / Mextner added async state and immutable records to the Runtime, stopped stale async work from publishing, compiled whole entries with rollback, removed a document copy from cold import, and added live examples that compile in the browser.

The numbers on this page are historical local measurements on benchmark fixtures, each tied to the pull request that recorded it. They are not claims about the whole editor.

4.15 → 0.006 ms
point edit on a 10,000-item benchmark fixture, Node median (#802)
63 → 1 ms
completion handler, 1,200 visible rows, Chromium median (#832)
15.6 → 4.7 MB
Chromium retained heap, 10,000 rows with 1,200 visible (#832)

What we delivered

One tested async toolkit instead of per-framework glue

A framework-neutral async toolkit now sits on the Runtime, with an async resource, matchAsyncState and a conformance suite. Production and testing entry points are separate, and an import-boundary test checks the split. One implementation means an async-state bug is fixed once instead of once per framework.

Technical detail
  • Package @ultrabricks/state-toolkit-async@0.0.0-pilot.0 under packages/state-lib/toolkit, with a peer on @ultrabricks/state-lib@0.1.0-pilot.1. The . and ./testing exports are checked by import-boundary.test.ts and package-contract.test.ts.
  • Tests: async-conformance.test.ts, async-ownership.test.ts, async-resource.test.ts, async-thenable-once.test.ts and match-async-state.test.ts.

Key pull requests: #810

Validated immutable records on the existing Runtime

createRecord adds validated, deeply frozen records on the Runtime for small plain objects such as editor workspace preferences. Callers cannot change a committed snapshot, and a nested update that re-enters the same record now throws instead of letting a stale draft overwrite it. It reuses the Runtime’s transactions, so there is no second state engine to maintain.

Technical detail
  • A regression test written first reproduced the re-entrancy bug. The error is STATE_RECORD_REENTRANT, thrown before the inner mutation, and async recipes are rejected.
  • record.test.ts runs under a strict tsconfig.record.json; the pull request records 75 tests passing across core, regression, follow-up and adapter cases.

Key pull requests: #803

Stale async work cannot publish

createOperationScope gives each lane of async work a context generation. Once a lane is replaced, its context changes or it is disposed, the old write or feedback cannot publish, and an old finish or cancel cannot release a newer lease. It is library code; the pull request does not turn it on in the inspector.

Technical detail
  • Independent lanes, synchronous commit and notify gates, callback binding checked at invocation, and bounded metadata-only diagnostics.
  • Tests: operation-scope.test.ts, operation-scope-async.test.ts and a type fixture. A real-Chromium check runs the emitted package pair through nine scenarios, and with the stale-publication guard removed, five of seven checks fail.

Key pull requests: #826

Package export fails closed and records provenance

The package exporter assembles in an owner-only staging directory on the destination filesystem and publishes by rename. It refuses to overwrite existing files, directories or dangling symlinks and refuses an output directory inside the source trees. Each export records source and output hashes and tool versions, so a package can be traced to its source.

Technical detail
  • export-package.mjs keeps the original cause on errors and reports both failures if export and cleanup fail. export-filesystem.test.ts covers it, and #826 added cases. The pull request states the limits: the publish is not atomic no-replace and not crash-durable.

Key pull requests: #810

Generated commands and complete entries with rollback

The compiler generates immutable commands for declared edits such as assign, toggle, row assign and move, so on the benchmark fixture those edits no longer copy the whole document. state build compiles complete fixed application entries and publishes each output with rollback, and size budgets reject an oversized entry and keep the previous output. The figures below carry their fixtures and comparators; they are not a general speed or size claim.

Technical detail
  • Native Rust compiler: packages/state-lib/compiler/src/command.rs and lib.rs. Median improved in all 42 Node measurements; 26 of 42 also pass the stricter max-versus-min cell test (#802).
  • One ownership-aware publication and history module runs on a single dedicated Runtime. Entry budgets are maxRawBytes, maxGzipBytes and maxBrotliBytes plus a relative-growth limit (#802).
  • Fingerprint walks went from three to two and path resolution is cached within a build. A lock-cleanup failure after a successful install is only a warning (#832). A hole that let an alias into authored src/node_modules bypass the browser-root check was closed, with nine regression tests; the pull request says this is not a sandbox for third-party code.
  • An optional immutable-row adapter updates completion on existing rows in the board view and falls back to the full renderer for unsupported changes (#832). On the small fixtures the same pull request records about 32 to 38 KB more retained heap, and an entry of 42,166 gzip bytes against 37,132 for the equally optimized original.

Key pull requests: #802 · #832

Cold import skips a full-document copy

importJsonField certifies a JSON field while importing it, and replaceImported adopts that exact root. A cold load skips one whole-document structuredClone, while the normal replace() still copies and behaves as before.

Technical detail
  • replaceImported throws TypeError for anything not produced by importJsonField, so the shortcut cannot be used with an uncertified value. Certification, freezing, history reset and the save payload contract are unchanged.
  • owned-import.test.ts was written red first and has 11 passing tests. The pull request records whole-call structuredClone uses during load going from 3 to 2 and makes no timing claim.

Key pull requests: #834

Live examples, a keyed-row patch boundary and correct docs

The documentation site has two live examples, /repl/board-commands and /repl/issue-triage. Visitors edit multi-file source, compile it with the real Rust compiler in WebAssembly, and see generated commands, readable and minified output, sizes, live state, Undo and Redo, and browser benchmarks. A checked keyed-row patch boundary lets an app update real text edits without rebuilding the list, and the generated API docs keep ordinary member names.

Technical detail
  • Edited code runs in a disposable worker inside an opaque-origin, network-denied frame. Cancellation, latest-request authority, timeout and keeping the last good build after a failed build are tested (#809).
  • patchKeyedRows locates every target before the first row write and rejects a null or invalid plan without applying rows; the pull request documents that a throwing callback leaves a view to rebuild (#833). 14 planner and boundary tests pass.
  • apiSymbolName() used to throw on a real member named like __@iterator@999 and abort API-doc generation. It now accepts such a name only when a declaration’s string literal is exactly that name, and the regenerated docs are unchanged at 119 entries (#807).
  • Diagram captions no longer show quoted attribute text, and docs-site readiness waits for exactly three lazy editors. SVG comparison in the gallery tolerates only narrowly parsed coordinate roundoff (#810).

Key pull requests: #809 · #833 · #807

Before and after in numbers

Historical local measurements, recorded in the pull requests named in the last column; the first column gives the fixture. #802 improves the median in all 42 Node measurements and passes its stricter cell test in 26 of 42. #832 records about 32 to 38 KB more retained heap on small fixtures.

MeasureBeforeAfterSource
Point edit, 10,000-item benchmark fixture, Node median4.148 ms0.006 ms#802 body
Move, 10,000-item benchmark fixture, Node median4.175 ms0.008 ms#802 body
Entry size, 512-command fixture: raw / gzip / Brotli71,069 / 9,525 / 6,596 bytes42,284 / 8,619 / 5,779 bytes#802 body
Task-completion handler, 1,200 visible rows, median63.2 ms Chromium, 93 ms WebKit1.0 ms Chromium, 1 ms WebKit#832 body
Next animation frame, 1,200 visible rows311 ms Chromium, 546 ms WebKit13.8 ms Chromium, 7 ms WebKit#832 body
Chromium retained heap, 10,000 rows, 1,200 visible15.58 MB4.73 MB#832 body
Whole-document copies during cold load32#834 body
Diagram caption in the docs siteQuoted attribute text shown before the labelOnly the intended labelScreenshots below

Screenshots

Diagram caption in the StateLib documentation site, captured for #810 on 14 October. The same fixture is shown before and after the fix. Tap an image to open it full size.

Original browser captures from 14 October, retained with #810.

Proof

Hosted CI runs for the final commit of each pull request, or for the merge commit where noted.

Work by Ultra / Mextner (GitHub alex-mextner, Alex Ultra). Pull requests merged 1 to 31 October 2026 are credited by commit authorship. Status checked 6 November. Source links may require repository access.

Attribution: every commit in these pull requests is by Ultra. #802, #809 and #833 were opened from the smoothbricker account and merged by alex-mextner.

All merged pull requests counted here are listed with their authors and merge commits in the source record.

diff --git a/scripts/ci/check-october-render.mjs b/scripts/ci/check-october-render.mjs new file mode 100755 index 0000000..7ecce5c --- /dev/null +++ b/scripts/ci/check-october-render.mjs @@ -0,0 +1,174 @@ +#!/usr/bin/env node +/** + * Rendered contract for the three October 2026 reports. + * + * Complements validate-reports.mjs (structure, assets, smoke render) with what a reader sees: + * - the title, summary tiles and outcome sections are present with JavaScript blocked; + * - the same sections are visible, fully opaque and in reading order on desktop, + * Android-size and iPhone-size viewports, with no horizontal overflow; + * - the first screen names the report and starts the overview; + * - every image decodes at its natural size and screenshots are readable on phones; + * - the figures table stays readable (stacked rows) on phones. + * + * Usage: node scripts/ci/check-october-render.mjs [--root ] [--out ] + */ +import { chromium } from 'playwright'; +import { createServer } from 'node:http'; +import { readFileSync, mkdirSync, statSync } from 'node:fs'; +import { dirname, extname, join, resolve, sep } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const args = process.argv.slice(2); +const opt = (name) => { + const i = args.indexOf(name); + return i === -1 ? undefined : args[i + 1]; +}; +const ROOT = resolve(opt('--root') ?? join(dirname(fileURLToPath(import.meta.url)), '..', '..')); +const OUT = opt('--out'); +if (OUT) mkdirSync(OUT, { recursive: true }); + +const REPORTS = [ + { slug: 'hyper-2026-10', title: 'HyperIDE: October 2026', outcomes: 4, images: 0 }, + { slug: 'state-lib-2026-10', title: 'StateLib: October 2026', outcomes: 7, images: 2 }, + { slug: 'conloca-2026-10', title: 'Conloca: October 2026', outcomes: 7, images: 2 }, +]; + +const PROFILES = [ + { name: 'desktop-1440', viewport: { width: 1440, height: 900 } }, + { name: 'android-390', viewport: { width: 390, height: 844 }, isMobile: true, hasTouch: true, deviceScaleFactor: 2 }, + { name: 'iphone-393', viewport: { width: 393, height: 852 }, isMobile: true, hasTouch: true, deviceScaleFactor: 3 }, + { name: 'iphone-se-375', viewport: { width: 375, height: 667 }, isMobile: true, hasTouch: true, deviceScaleFactor: 2 }, + { name: 'no-js-390', viewport: { width: 390, height: 844 }, isMobile: true, javaScriptEnabled: false, deviceScaleFactor: 2 }, +]; + +const MIME = { '.html': 'text/html', '.css': 'text/css', '.js': 'text/javascript', '.json': 'application/json', '.png': 'image/png' }; + +const server = createServer((req, res) => { + try { + const path = decodeURIComponent(new URL(req.url, 'http://x').pathname); + if (path === '/favicon.ico') return res.writeHead(204).end(); + let file = resolve(ROOT, '.' + path); + if (file !== ROOT && !file.startsWith(ROOT + sep)) return res.writeHead(403).end(); + if (statSync(file).isDirectory()) file = join(file, 'index.html'); + res.writeHead(200, { 'Content-Type': MIME[extname(file)] ?? 'application/octet-stream' }).end(readFileSync(file)); + } catch { + res.writeHead(404).end(); + } +}); +await new Promise((ok) => server.listen(0, '127.0.0.1', ok)); +const base = `http://127.0.0.1:${server.address().port}`; + +const failures = []; +const fail = (tag, msg) => failures.push(`[${tag}] ${msg}`); + +const browser = await chromium.launch(); +try { + for (const report of REPORTS) { + for (const { name, ...contextOptions } of PROFILES) { + const tag = `${report.slug} ${name}`; + const noJs = contextOptions.javaScriptEnabled === false; + const context = await browser.newContext(contextOptions); + const page = await context.newPage(); + const problems = []; + page.on('pageerror', (e) => problems.push(String(e))); + page.on('console', (m) => m.type() === 'error' && problems.push(m.text())); + page.on('response', (r) => r.status() >= 400 && problems.push(`${r.status()} ${r.url()}`)); + await page.goto(`${base}/reports/${report.slug}/`, { waitUntil: 'networkidle' }); + await page.evaluate(() => document.fonts.ready); + const m = await page.evaluate(() => { + const box = (el) => el.getBoundingClientRect(); + const h1 = document.querySelector('h1'); + const overview = document.querySelector('#overview p'); + const ids = ['overview', 'outcomes', 'figures', 'proof'].map((id) => document.getElementById(id)); + const opaque = [...document.querySelectorAll('.outcome, .summary-card, .figures tbody tr, .report-section')].filter( + (el) => Number(getComputedStyle(el).opacity) < 1 || getComputedStyle(el).visibility !== 'visible' || box(el).height === 0, + ).length; + const rowsStacked = [...document.querySelectorAll('.figures tbody tr')].every((tr) => getComputedStyle(tr.firstElementChild).display === 'block' || innerWidth > 650); + const imgs = [...document.images].map((i) => i.getAttribute('src')); + return { + h1: h1 ? h1.innerText : null, + h1Top: h1 ? box(h1).top : null, + overviewTop: overview ? box(overview).top : null, + viewport: innerHeight, + scrollWidth: document.documentElement.scrollWidth, + innerWidth, + outcomes: document.querySelectorAll('.outcome').length, + tiles: document.querySelectorAll('.summary-card').length, + orderOk: ids.every((el, i) => el && (i === 0 || ids[i - 1].compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING)), + hiddenOrTransparent: opaque, + rowsStacked, + figureRows: document.querySelectorAll('.figures tbody tr').length, + details: [...document.querySelectorAll('.outcome details')].every((d) => !d.open && d.querySelector('summary')), + whatVisible: [...document.querySelectorAll('.outcome .what')].every((p) => p.getBoundingClientRect().height > 40 && getComputedStyle(p).visibility === 'visible'), + imgs, + }; + }); + + if (m.h1 !== report.title) fail(tag, `h1 is ${JSON.stringify(m.h1)}, expected ${JSON.stringify(report.title)}`); + if (m.h1Top === null || m.h1Top >= m.viewport) fail(tag, 'title is not on the first screen'); + if (m.overviewTop === null || m.overviewTop >= m.viewport) fail(tag, 'overview does not start on the first screen'); + if (m.scrollWidth > m.innerWidth + 1) fail(tag, `horizontal overflow ${m.scrollWidth} > ${m.innerWidth}`); + if (m.outcomes < report.outcomes) fail(tag, `${m.outcomes} outcome sections, expected at least ${report.outcomes}`); + if (m.tiles < 3) fail(tag, `${m.tiles} summary tiles`); + if (!m.orderOk) fail(tag, 'overview, outcomes, figures and proof are not in reading order'); + if (m.hiddenOrTransparent) fail(tag, `${m.hiddenOrTransparent} sections are transparent, hidden or empty`); + if (!m.details) fail(tag, 'technical detail must be collapsed by default with a summary'); + if (!m.whatVisible) fail(tag, 'an outcome paragraph is not visible'); + if (m.figureRows < 3) fail(tag, `${m.figureRows} figure rows`); + if (!m.rowsStacked) fail(tag, 'figures table is not stacked on a phone viewport'); + if (m.imgs.length !== report.images) fail(tag, `${m.imgs.length} images, expected ${report.images}`); + + // Technical detail is closed on load and must open on activation, with its content then visible. + const toggled = await page.evaluate(() => { + const d = document.querySelector('.outcome details'); + const before = d.open; + d.querySelector('summary').click(); + const body = d.querySelector('ul'); + const result = { before, after: d.open, visible: body.getBoundingClientRect().height > 0 }; + d.querySelector('summary').click(); + return { ...result, closedAgain: !d.open }; + }); + if (toggled.before || !toggled.after || !toggled.visible || !toggled.closedAgain) fail(tag, `technical detail does not toggle: ${JSON.stringify(toggled)}`); + + // Full-page pass: lazy images only load once they are near the viewport. + for (const image of await page.locator('img').all()) { + await image.scrollIntoViewIfNeeded(); + const ok = await image.evaluate((el) => el.decode().then(() => el.naturalWidth > 0, () => false)); + if (!ok) fail(tag, `image failed to decode: ${await image.getAttribute('src')}`); + } + if (contextOptions.isMobile) { + // Phone crop: the visible part of a screenshot must be large enough to read. + for (const el of await page.locator('.crop').all()) { + const { w, h, iw } = await el.evaluate((c) => ({ w: c.getBoundingClientRect().width, h: c.getBoundingClientRect().height, iw: c.querySelector('img').getBoundingClientRect().width })); + if (h < 150) fail(tag, `crop is only ${h}px tall`); + if (iw < w * 2.5) fail(tag, `image is shown at ${iw}px inside a ${w}px crop; detail is not magnified`); + } + } + if (!noJs) { + // The shared renderer must have run (the static header alone would satisfy a header check). + const init = await page.evaluate(() => Boolean(window.Report && window.Report.data && window.Report.data.title)); + if (!init) fail(tag, 'Report.init did not run'); + const header = await page.locator('[data-section="header"] h1').count(); + if (header !== 1) fail(tag, 'rendered header lost its title'); + } + await page.evaluate(() => window.scrollTo(0, 0)); + if (OUT) { + await page.screenshot({ path: join(OUT, `${report.slug}-${name}-first-screen.png`) }); + await page.screenshot({ path: join(OUT, `${report.slug}-${name}-full.png`), fullPage: true }); + } + // Everything the page logged or requested, including lazy images, toggles, crops and screenshots. + problems.forEach((p) => fail(tag, `console/network problem: ${p}`)); + await context.close(); + } + } +} finally { + await browser.close(); + server.close(); +} + +if (failures.length) { + console.error(`${failures.length} rendered-contract problem(s):\n - ${failures.join('\n - ')}`); + process.exitCode = 1; +} else { + console.log(`October reports rendered contract passed: ${REPORTS.length} reports x ${PROFILES.length} viewports.`); +} diff --git a/scripts/ci/check-own-results.py b/scripts/ci/check-own-results.py index c447dec..42b37c6 100644 --- a/scripts/ci/check-own-results.py +++ b/scripts/ci/check-own-results.py @@ -1,6 +1,6 @@ from pathlib import Path from html.parser import HTMLParser -import hashlib, json, unittest +import hashlib, html, json, re, unittest ROOT = Path(__file__).resolve().parents[2] @@ -55,12 +55,80 @@ def setUp(self): (ROOT / "reports/2026-10-own-results-evidence.json").read_text() ) + def _all_rows(self): + return [r for rows in self.data["reports"].values() for r in rows] + + def _assert_scoped_row(self, r): + # Mixed pull request: only our named commits are published, never the other authors' history. + self.assertTrue(r["mixedAuthors"]) + self.assertTrue(r["scopeCommits"]) + self.assertTrue(all(len(c) == 40 for c in r["scopeCommits"])) + self.assertEqual(r["creditedCommitAuthors"], {"alex-mextner": len(r["scopeCommits"])}) + self.assertGreater(r["ownCommits"], len(r["scopeCommits"])) + for key in ("commitAuthors", "changedFiles", "additions", "deletions"): + self.assertNotIn(key, r) + + def _assert_whole_row(self, r): + self.assertEqual(set(r["commitAuthors"]), {"alex-mextner"}) + expected = "pr-author" if r["author"] == "alex-mextner" else "commit-author" + self.assertEqual(r["attribution"], expected) + def test_only_owner_october_merges(self): - for rows in self.data["reports"].values(): - for r in rows: - self.assertEqual(r["author"], "alex-mextner") - self.assertEqual(r["state"], "MERGED") - self.assertTrue(r["mergedAt"].startswith("2026-10-")) + for r in self._all_rows(): + self.assertIn(r["author"], ("alex-mextner", "smoothbricker")) + self.assertEqual(r["state"], "MERGED") + self.assertTrue(r["mergedAt"].startswith("2026-10-")) + if r["author"] != "alex-mextner": + self.assertEqual(r["mergedBy"], "alex-mextner") + if r["attribution"] == "commit-scope": + self._assert_scoped_row(r) + else: + self._assert_whole_row(r) + + def test_inventory_counts_add_up_per_repo(self): + inv = self.data["inventory"] + keys = {(r["repo"], r["pr"]) for r in self._all_rows()} + summary = inv["excludedSummary"] + for repo, merged in inv["mergedInOctober"].items(): + self.assertEqual(inv["credited"][repo] + summary["byRepository"][repo], merged) + self.assertEqual(len({k for k in keys if k[0] == repo}), inv["credited"][repo]) + self.assertEqual(len(keys), sum(inv["credited"].values())) + self.assertEqual(sum(summary["byRepository"].values()), summary["total"]) + self.assertEqual(sum(summary["byReason"].values()), summary["total"]) + self.assertRegex(summary["localAuditSha256"], r"^[0-9a-f]{64}$") + self.assertEqual(inv["reviewedAt"], self.data["verifiedAt"]) + + LOGIN_KEYS = ("author", "mergedBy", "login", "account") + COUNT_KEYS = ("commitAuthors", "creditedCommitAuthors") + + def _logins(self, node): + if isinstance(node, list): + return set().union(*[self._logins(item) for item in node]) if node else set() + if not isinstance(node, dict): + return set() + found = set() + for key, value in node.items(): + if key in self.LOGIN_KEYS and isinstance(value, str): + found.add(value) + elif key in self.COUNT_KEYS and isinstance(value, dict): + found |= set(value) + found |= self._logins(value) + return found + + def test_public_record_has_no_census_of_other_peoples_work(self): + inv = self.data["inventory"] + self.assertNotIn("excluded", inv) + self.assertEqual( + set(inv["excludedSummary"]), + {"total", "byRepository", "byReason", "localAuditSha256", "note"}, + ) + # The only people who appear anywhere in the record are the owner and the alias account. + self.assertEqual(self._logins(self.data) - {"alex-mextner", "smoothbricker"}, set()) + self.assertNotIn("partialScope", (ROOT / "reports/2026-10-own-results-evidence.json").read_text()) + # Per-person commit counts exist only for our own credited pull requests. + for r in self._all_rows(): + if "commitAuthors" in r: + self.assertEqual(set(r["commitAuthors"]), {"alex-mextner"}) def test_images_match_recorded_evidence(self): for r in self.data["images"]: @@ -118,26 +186,27 @@ def test_pr810_combined_scope_is_supported(self): ) def test_report_styles_have_one_scoped_source(self): - style = ROOT / "reports/shared/october-own.css" + style = ROOT / "reports/shared/october-own-20261106.css" self.assertTrue(style.is_file()) for slug in self.data["reports"]: text = (ROOT / "reports" / slug / "index.html").read_text() - self.assertIn("../shared/october-own.css", text) + self.assertIn("../shared/october-own-20261106.css", text) self.assertNotIn("