has a greedy `Name` capture\nthat walks to the *last* `:` in a line. For TypeScript property\ndeclarations whose type is an arrow function -- e.g.\n`UnderlyingSource` in lib.dom.d.ts:\n\n pull?: (controller: ReadableStreamDefaultControll\n[…]\n the\n`ToObject` (dependent-DTO) and `ToTopLevelObject` paths.\n\nAdds three regression tests in ArrowFunctionPropertyFilterTests.cs.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Filter arrow-function-typed property lines in IsProperty", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T03:18:07Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "8d40daf7b2b03259b851fc577a985daf59b4ac7e", "body": "`lib.dom.d.ts` declares many trivial aliases that point at a primitive\nTS type, e.g.\n\n type DOMHighResTimeStamp = number;\n type GLuint = number;\n type GLboolean = boolean;\n type EpochTimeStamp = number;\n\nPreviously `TryGetPrimitiveType` only resolved string-literal-union\naliases (`type D\n[…]\nthe property, method-return, and parameter surfaces across\nthe three common alias shapes. Full suite: 279 -> 289 tests, all green.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Resolve single-primitive TypeScript aliases (DOMHighResTimeStamp, GL*)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T03:11:38Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "8f897c190b0f7cb0b621d74c1ac0100173251265", "body": "Three code paths produced uncompilable output when a method accepted\na TS callback with zero parameters (e.g. `VoidFunction`, `(): void;`,\nused by `WindowOrWorkerGlobalScope.queueMicrotask`):\n\n* `CSharpType.ToActionString` joined `ActionDeclaration.DependentTypes`\n keys into the generic argument li\n[…]\nross `CSharpTypeCallbackActionStringTests`\nand `SourceBuilderZeroParameterCallbackTests`. Full suite:\n274 -> 279 tests, all green.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Emit valid C# for zero-parameter TS callbacks (VoidFunction)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T03:03:50Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "41beab2bbf813f3e1515d9b8373ff618f4630ea5", "body": "When a method parameter or return type was an array of a user-defined\nTypeScript interface (e.g. `MutationRecord[]`), the generator looked\nthe literal type string up in the declaration map without stripping\nthe array suffix. Because the map keys the element type only, no\nmatch occurred, the element \n[…]\nntDependentTypeTests` covering\nparameter and return positions for all three array shapes. Full\nsuite: 268 -> 274 tests, all green.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Emit dependent DTOs for array-of-custom-type parameters and return types", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:58:05Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "466e854da35b911eac5d5c58e35b444c1f99092a", "body": "…positions\n\n`CSharpType.ToParameterString` and `CSharpMethodExtensions.GetMethodTypes`\nboth relied on `TypeMap.PrimitiveTypes.IsPrimitiveType(RawTypeName)`\nreturning `true` for the full type spelling. That works for scalar\nTS primitives (`number` -> `double`), but it returns `false` for the\narray fo\n[…]\nsts` (8 cases) and\n`CSharpMethodReturnTypeArrayTests` (11 cases) covering scalar +\nnullable + non-primitive forms. 268 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Map TypeScript primitive arrays to C# arrays in parameter and return …", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:55:51Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "1adaca3077d526200440fe20d0de46fde8e6f408", "body": "…nostic and polish messages\n\n`Descriptors.PathFromWindowRequiredDiagnostic` carried a stale name\nfrom an earlier iteration of `JSAutoInteropAttribute` (when the\nproperty was called `PathFromWindow`). It now flags a missing\n`Implementation` value, so the field name was misleading - any future\ncontrib\n[…]\ne\n controls\n\nThe diagnostics are still tracked as `Unshipped`, so the message\npolish is in-scope. All 249 tests continue to pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Rename PathFromWindowRequiredDiagnostic to ImplementationRequiredDiag…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:50:29Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "3458ec5e679371260a614b6585d7739687302f28", "body": "ToObject and ToTopLevelObject classified a property as nullable when\nits raw type string `Contains(\"| null\")`. That returns false positives\nfor shapes where `| null` appears only inside a generic argument or\narray element (e.g. `(number | null)[]`, `Map\u003cstring, string | null>`).\nThe reference itself\n[…]\nameterized cases covering the new boundary (including the two\nnested-`| null` regressions that previously failed). 249 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Tighten property-level nullable detection to top-level | null only", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:46:33Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "4d8702001e7db546f6dd06eb68d0b95722db6235", "body": "CSharpObject.IsActionParameter used to OR shape-based IsCallback with\na name-suffix fallback `TypeName.EndsWith(\"Callback\")`. The latter\nmisclassified any normal DTO whose name happens to end with the\nsubstring, silently dropping it from the generated output (the\npredicate gates AddDependentTypesSou\n[…]\nests with five regression cases\ncovering the previous false-positive and confirming the new\nshape-driven behavior. 242 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "Remove brittle Callback suffix fallback in IsActionParameter", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:44:03Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "42a066be5e76c6252ab1bc198262b1484153dca8", "body": "…lable arrays\n\n`CSharpProperty.IsArray` and `TryGetArrayElementTypeName` matched on\n`EndsWith(\"[]\")` (and the `Array\u003c...>` / `ReadonlyArray\u003c...>` generic\nprefixes) against the raw TypeScript type. For nullable arrays the\ntype ends with `null`, not `]` or `>`, so the array shape was never\nrecognized.\n[…]\ndouble[]\"\n\nAdds 13 parameterized regression cases across `IsArray`,\n`MappedTypeName`, and `GetPropertyTypes`.\n\nAll 234 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: recognize `T[] | null` (and Array/ReadonlyArray variants) as nul…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:40:32Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "47e68bddc64aa0d8f38104b17d8fc6abae2b809e", "body": "…le shapes\n\n`CSharpMethod.IsReturnTypeNullable` checked\n`RawReturnTypeName.Contains(\"null\")`, which returns `true` for any\nidentifier whose name happens to contain the substring \"null\" --\nincluding the bundled DOM types `OnBeforeUnloadEventHandlerNonNull`\nand `OnErrorEventHandlerNonNull`, plus any u\n[…]\nssion cases covering both true positives\n(real `| null` clauses) and false positives (identifier substrings).\n\nAll 221 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: tighten `IsReturnTypeNullable` to recognize only TS-level nullab…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:36:51Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "94fb3f0376c84d91fe81bd71226fc8425b7777a6", "body": "`ParseParameters` previously detected nullability only from the\nparameter name's trailing `?`. When a `.d.ts` parameter was instead\nwritten as `x: T | null` (without a `?` on the name), the parser\nkept the literal \"| null\" in the C# type token. For primitives like\n`string | null` this happened to wo\n[…]\ns the parameter's `IsNullable` flag flips and that\n`ToParameterString()` no longer contains the literal `| null`.\n\n210 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: normalize type-level `| null` parameter annotations to nullable C#", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:35:15Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "a37b986430b786027758326e7fbde5a38792f3bc", "body": "…ions\n\n`GenericMethodDescriptors`, `PureJavaScriptOverrides`, and\n`TypeDeclarationSources` accept `string[]?`. With C# 12 collection\nexpressions, consumers can write:\n\n [JSAutoGenericInterop(\n GenericMethodDescriptors = [\"getItem\", \"setItem:value\"])]\n\n`ReadStringArray` recognized `new[] { \n[…]\ner\n - [...] collection expression with literal strings\n - [...] collection expression with const references\n\nAll 207 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "feat: parse string-array attribute args from C# 12 collection express…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:31:33Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "59131477061f7b7b7aa470e503ed4a5d14017ed9", "body": "`ResolveParsers` constructed a fresh `TypeDeclarationParser` (and the\nunderlying `TypeDeclarationReader`) for every matched `.d.ts`\nreference in every target. When multiple `[JSAutoInterop]` targets\nin the same compilation point at the same `AdditionalFile` (the\ncommon case once `TypeDeclarationSour\n[…]\nis GC'd with the parsers\nthemselves; we do not extend their lifetime beyond the source-output\nboundary.\n\nAll 203 tests still pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "perf: share TypeDeclarationParser across targets within an Execute pass", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:29:39Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "df5dbb76d6942ef3fcf55162f8038815ad1c9ad1", "body": "The `Indentation` value type held a `Level` field that was never\nclamped. `Decrease()` computed `Level - 1 - extra`, and `ResetTo(int)`\ncopied the caller's value verbatim. Both could leave `Level` negative.\n`ToString()` then evaluates `new string(' ', Spaces * Level)` which\nthrows `ArgumentOutOfRang\n[…]\n regression tests covering Decrease-from-zero,\nDecrease-with-extra, ResetTo-negative, and the positive paths.\n\nAll 203 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: clamp Indentation Decrease/ResetTo to non-negative levels", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:26:35Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "685cdd3ed6ae2d523f4a392a2207d64626fb95d7", "body": "…ually shrinks\n\nThe previous test only asserted that *some* output was produced when\n'OnlyGeneratePureJS = true' was set, which any non-trivial code path\nwould satisfy. The flag's documented purpose is to *exclude* methods\nthat need JS-callback wiring (e.g. 'Geolocation.watchPosition'/\n'getCurrentPo\n[…]\ned out).\n\nThis catches regressions where the flag silently stops gating output,\nwhich the prior test did not.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "test: strengthen OnlyGeneratePureJS coverage to verify method-set act…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:25:11Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "8ce5d2ab50722d9d80064b8780364125e10a3233", "body": "…ehavior\n\nTwo internal comments still described TypeDeclarationSources as\n'reserved for future use' even though T5.1 fully wired the property\ninto the generator pipeline. Update both to describe the actual\nbehavior:\n\n* GeneratorOptions.BuildParsers — clarify that this is the fallback\n path used whe\n[…]\nReader(content) directly,\n which is what the generator already does for AdditionalFiles.\n\nNo behavior change. All 198 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "docs: refresh stale TypeDeclarationSources comments to reflect T5.1 b…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:23:58Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "7e5ff5b39f17a2b8b10ec2b7b8b5122ed27cd49a", "body": "….1 behavior\n\nThe emitted attribute's XML doc for `TypeDeclarationSources` still\nclaimed the property was \"reserved for future use\" and that \"setting\nit has no effect\". The audit's T5.1 work wired this property into the\ngenerator pipeline so the generator now reads matched `.d.ts` files\nfrom `Additi\n[…]\nle doc with the actual behavior, including the\n`AdditionalFiles` MSBuild snippet a consumer needs to wire up.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "docs: align JSAutoInteropAttribute.TypeDeclarationSources doc with T5…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:23:01Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "2a12791de33190827d119fee9c69926287b2c8de", "body": "Mark every regex in `SharedRegex` as `RegexOptions.Compiled |\nRegexOptions.CultureInvariant`. The parser evaluates these patterns\nmany times per generator run - once per matched interface, method,\nproperty, and array literal across ~800KB of lib.dom.d.ts plus any\nconsumer-supplied `.d.ts` files in `\n[…]\n removes culture-sensitive case-folding\nfrom the matcher even though none of these patterns use `IgnoreCase`.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "perf: compile shared parser regexes", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:21:19Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "63f31ff1ba80511890840f9ed14c707f5f31fe15", "body": "… interface\n\n`CSharpProperty.MappedTypeName` deliberately returns the *element* type\nfor array-shaped TypeScript types so that primitive-type lookups and\ndependency-graph walks can ignore the array wrapper. `CSharpObject.AppendProperty`\nalready re-attaches `[]` via a separate `IsArray` check, but th\n[…]\ng\nall three TypeScript array forms (`T[]`, `Array\u003cT>`, `ReadonlyArray\u003cT>`)\nagainst both `IsWebAssembly` arms.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: preserve `[]` suffix when emitting array properties on top-level…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:18:28Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "af4f9eabc7f78beda830d21c12826adeb02474eb", "body": "… lookups\n\nTwo small but correct improvements to the generator hot path:\n\n1. `JavaScriptInteropGenerator.Execute` now reads\n `context.CancellationToken` once and calls\n `ThrowIfCancellationRequested()` at the top of every outer-target\n iteration and inside the inner parser loop. Previously the\n[…]\ne across ~800KB of lib.dom.d.ts, so this O(1) lookup\n replaces what was effectively an O(n) per-check scan.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "perf: thread CancellationToken through Execute and speed up primitive…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:16:00Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "8fd9a5e78231085adcce6ebe7c58f99e63f294c7", "body": "`SourceBuilder.AppendConditionalDelegateCallbackMethods` only called\n`ResetIndentationTo(level)` after the entire loop. Each iteration\ncalls `AppendRaw(..., postIncreaseIndentation: true)` (twice through\n`AppendParameters`), so successive callback methods were emitted at\never-deeper indentation. The\n[…]\nInvokable] block starts at the outer indentation level\nregardless of what the previous iteration left behind.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: reset indentation per [JSInvokable] block in callback emit", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:13:47Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "58fa3cf5c470bf779d1e9ab14d966b123256e88d", "body": "Adds five additional [InlineData] cases to GeneratorOutputValidityTests\nthat exercise less-trodden code paths through the generator:\n\n* LocalStorage on Server (generic + non-generic)\n* LocalStorage on WASM (non-generic)\n* Geolocation with OnlyGeneratePureJS = true\n* SessionStorage on WASM (generic)\n\n[…]\nttribute parsing, hosting-model branches,\nand the OnlyGeneratePureJS flag without requiring snapshot updates.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "test: expand generator output validity sweep with 5 new scenarios", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-16T02:13:47Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "838a48e900a4e0cee1df345d7d0d3144626bcbbb", "body": "Until now `JSAutoInteropAttribute.TypeDeclarationSources` was a\ndocumented option that did nothing - the generator always parsed the\nembedded `lib.dom.d.ts` regardless. Consumers wanting to wire a\nnon-DOM TypeScript declaration file (their own ambient module, a\nthird-party `.d.ts`, or a polyfill typ\n[…]\nes_IsBenignNoOp` E2E test that pinned the old\nno-op behavior. Adds README documentation of the new option.\n\n187/187 tests passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "feat: wire TypeDeclarationSources into AdditionalTexts (T5.1)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T19:12:00Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "3c57b258b0b70b80e34fda60443c16035020edbc", "body": "The pre-audit attribute argument parser worked entirely on\n`AttributeArgumentSyntax.Expression.ToString()` and string-replaced\nquotes. That approach failed for:\n\n - String literals containing escape sequences. The naive\n `Replace(\"\\\"\", \"\")` mangled escaped quotes (`\"foo\\\"bar\"` became\n `foo\\ba\n[…]\ns) covering\nescape sequences, const references, nameof, verbatim strings,\nenum members, and bool literals.\n\n184/184 tests passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: parse attribute arguments via SemanticModel (T1.11)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T19:02:22Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "5fcce88ff9ed0ab72f489d17f598fb311a20dad3", "body": "Correctness fixes:\n\n - The \"Note\" about packaging incorrectly claimed Server packages\n expose a synchronous API. They expose `ValueTask`-based async\n methods through `IJSRuntime`; the WebAssembly variant uses\n `IJSInProcessRuntime` which is itself synchronous JS dispatch\n but still surf\n[…]\ndditions from the audit\n (previously the generator was silent on missing `partial`,\n unknown `TypeName`, or parse failures).\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "docs: README accuracy pass (post-audit)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:58:12Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "1f4e5c23ff5d55a943b5e2a4f7cb77d4af7da54c", "body": "`ToClassString` was a single ~65-line method building DTO source by\nhand with raw interpolated `\\n`-terminated strings inside one giant\n`foreach` over properties. The shape made it hard to spot anything\ndistinct - the special-case DOMTimeStamp / EpochTimeStamp UTC accessor\nwas buried inside the prop\n[…]\nng mode.\n - Two new snapshot tests pin the DTO output specifically, so any\n future change to `ToClassString` will fail loudly.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "refactor: split CSharpObject.ToClassString into named helpers (T3.9)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:56:02Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "217b870cee43e0da70f6c594f8796637b4a17bac", "body": "The implementation builder was a 286-line method with three structurally\ndistinct branches nested inside a `foreach (method)` loop:\n\n 1. Pure / non-bi-directional / JS-override invocations\n 2. Generic `TComponent` overload (bi-directional callback shape)\n 3. `Action\u003cT>` callback overload (same ca\n[…]\nweep (`GeneratorOutputValidityTests`) confirms\n every generated tree still parses without syntax errors.\n\nSnapshot diff: empty.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "refactor: split CSharpTopLevelObject.ToImplementationString (T3.8)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:53:14Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "687cacbc6e331ffc4504feec10263acfd397a9b9", "body": "T5.2 added `void -> void` to `TypeMap.PrimitiveTypes` so the parser\ncan short-circuit on void-returning methods instead of trying to\nrecurse into a non-existent `void` declaration. This (correctly)\nmade `IsPrimitiveType(\"void\")` return true for the first time.\n\nThat flipped a latent ordering bug in\n\n[…]\normalizeWhitespace removal, T3.8\n `ToImplementationString` refactor) producing malformed C#.\n\nTests: 176/176 (was 173 + 3 new).\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "fix: emit `ValueTask` (not `ValueTask\u003cvoid>`) for void Server methods", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:48:29Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "3b80dc675c58ee775c21bbcb36553d4a83e50e5e", "body": "Adds a lightweight string-snapshot helper plus 5 baseline snapshots\ncovering the most-exercised interop scenarios:\n\n - Geolocation_Wasm: interface, implementation, DI extension\n - Geolocation_Server: implementation (proves async ValueTask shape)\n - LocalStorage_Wasm_Generic: interface (proves JS\n[…]\nanother reference\nasset and disk layout convention isn't worth it for ~50 lines of\nhelper code.\n\nTests: 173/173 (was 168 + 5 new).\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "test: add hand-rolled snapshot harness for generator output", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:45:25Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "5572a36f5d0b85a195a0551905cc81fb5709b9d0", "body": "Adds primitive mappings for the TypeScript tokens that flow through\n`lib.dom.d.ts` but were previously unhandled by `TypeMap.PrimitiveTypes`.\nAnything not in the map falls through `IsPrimitiveType` to the\ndeclaration-recursion branch, which either emits an empty placeholder\nDTO (for declared interfa\n[…]\nrough a translated parameter type).\n - Negative cases - real DOM interface names still report `false`.\n\nTotal tests: 168 passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "feat: expand TypeMap to cover void/any/bigint/typed-arrays (T5.2)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-15T18:43:31Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "b4356a1ba8ecf0c8ff74e0c40c53ef8b2ce3b2f9", "body": "…T1.4)\n\nThe `TypeDeclarationSources` attribute parameter was documented as\naccepting \"URLs or file paths\" but the implementation is a no-op:\n`TypeDeclarationReader.Factory(string)` ignores its argument and\nreturns the default embedded-resource reader, with the URI handling\ncommented out.\n\nThis commi\n[…]\n the no-op contract so any future implementation has to\n actively change behavior, not just compile.\n\nTotal tests: 120 passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "refactor: clarify TypeDeclarationSources as reserved-for-future-use (…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-14T22:35:07Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "165ef6e8d907f9de2f677043b2a41ba8a229ca22", "body": "…T3.10)\n\nPreviously the parser identified TypeScript callback interfaces using a\nbrittle `typeName.EndsWith(\"Callback\")` heuristic in two places:\n\n - `TypeDeclarationParser.ParseParameters` - to decide whether to call\n `ToAction(...)` and emit an `Action\u003cT>` parameter, or `ToObject(...)`\n and\n[…]\negative cases (regular interfaces, properties-only, empty bodies,\n whitespace, non-interface input).\n\nTotal tests: 119 passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "refactor: replace `EndsWith(\"Callback\")` with shape-based detection (…", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-14T22:32:34Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "4aacf1c24785fcf3684f461904420839e94da6d4", "body": "Six end-to-end tests covering the actual shape of the generated\noutput across all four artifact kinds the generator emits per\n`[JSAutoInterop]` hit:\n\n- `Geolocation_InterfaceFile_DeclaresExpectedMembers` - the\n `IGeolocationService` interface file declares `ClearWatch`,\n `GetCurrentPosition`, `Wat\n[…]\ntic and hosting-model tests added earlier,\nthis closes the Tier 4 \"end-to-end generation\" coverage gap.\n\nTotal tests: 105 passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "test: add end-to-end snapshot-style generation tests (T4)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-14T22:29:04Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "279e214545947929f4fad5f44f297d3351ed93a6", "body": "Four tests verifying that the `HostingModel = BlazorHostingModel.X`\nattribute argument correctly switches the generator between\nWebAssembly (synchronous, `IJSInProcessRuntime`) and Server\n(asynchronous, `IJSRuntime`) output shapes.\n\n- `Default_GeneratesWebAssemblyExtensions` - default mode emits\n `\n[…]\nse the interface filename also ends with that\nsuffix - exact filename match is the only safe comparison.\n\nTotal tests: 99 passing.\n\nCo-authored-by: Copilot \u003c223556219+Copilot@users.noreply.github.com>", "is_bot": false, "headline": "test: add WebAssembly vs Server hosting-model regression tests (T4)", "author_name": "David Pine", "author_login": "IEvangelist", "committed_at": "2026-05-14T22:28:06Z", "body_truncated": true, "is_coding_agent": true } ], "releases_count": 43, "commits_last_year": 124, "latest_release_at": "2026-07-24T18:48:52Z", "latest_release_tag": "10.1.0", "releases_from_tags": false, "days_since_last_push": 0, "active_weeks_last_year": 5, "days_since_latest_release": 0, "mean_days_between_releases": 142 }, "community": { "has_readme": true, "has_license": true, "has_description": true, "has_contributing": false, "health_percentage": 71, "has_issue_template": false, "has_code_of_conduct": true, "has_pull_request_template": false }, "ecosystem": { "packages": [ { "name": "Blazor.DOM", "exists": true, "license": null, "keywords": [ "dotnet", "dotnetcore", "csharp", "blazor", "server", "dom", "interop", "jsinterop" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.DOM", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 1, "total_downloads": 0, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:39.883000Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.Clipboard", "exists": true, "license": null, "keywords": [ "dotnet", "blazor", "server", "dom", "interop", "clipboard" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.Clipboard", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 1, "total_downloads": 0, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:38.400000Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.Credentials", "exists": true, "license": null, "keywords": [ "dotnet", "blazor", "server", "dom", "interop", "credentials", "webauthn" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.Credentials", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 1, "total_downloads": 0, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:39Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.Geolocation", "exists": true, "license": null, "keywords": [ "dotnet", "dotnetcore", "csharp", "blazor", "server", "wasm", "generators", "sourcegen", "roslyn" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.Geolocation", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 19, "total_downloads": 94337, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:40.950000Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.LocalStorage", "exists": true, "license": null, "keywords": [ "dotnet", "dotnetcore", "csharp", "blazor", "generators", "sourcegen", "roslyn" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.LocalStorage", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 19, "total_downloads": 84532, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:41.440000Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.MediaDevices", "exists": true, "license": null, "keywords": [ "dotnet", "blazor", "server", "dom", "interop", "media-devices", "get-user-media", "display-capture" ], "ecosystem": "nuget", "matches_repo": true, "registry_url": "https://www.nuget.org/packages/Blazor.MediaDevices", "is_deprecated": false, "latest_version": "10.1.0", "repository_url": "https://github.com/IEvangelist/blazorators", "versions_count": 1, "total_downloads": 0, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2026-07-24T18:52:41.963000Z", "latest_version_yanked": null, "days_since_latest_publish": 0 }, { "name": "Blazor.Notifications", "exists": true, "license": null, "keywords": [ "Blazor", "Notifications", "C#", ".NET", "Standard", ".NET", "Core" ], "ecosystem": "nuget", "matches_repo": false, "registry_url": "https://www.nuget.org/packages/Blazor.Notifications", "is_deprecated": false, "latest_version": "0.2.0", "repository_url": "https://github.com/vertonghenb/Blazor.Notifications", "versions_count": 2, "total_downloads": 3360, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": null, "first_published_at": null, "latest_published_at": "2018-06-19T23:35:33.853000Z", "latest_version_yanked": null, "days_since_latest_publish": 2956 } ] }, "popularity": { "forks": 32, "stars": 392, "watchers": 13, "fork_history": { "days": [ { "date": "2021-10-12", "count": 1 }, { "date": "2022-03-08", "count": 1 }, { "date": "2022-03-25", "count": 1 }, { "date": "2022-04-04", "count": 1 }, { "date": "2022-04-08", "count": 1 }, { "date": "2022-04-12", "count": 3 }, { "date": "2022-04-14", "count": 1 }, { "date": "2022-04-21", "count": 1 }, { "date": "2022-05-11", "count": 1 }, { "date": "2022-10-07", "count": 1 }, { "date": "2022-10-23", "count": 1 }, { "date": "2022-11-04", "count": 1 }, { "date": "2022-12-01", "count": 1 }, { "date": "2023-01-24", "count": 1 }, { "date": "2023-02-02", "count": 1 }, { "date": "2023-02-10", "count": 1 }, { "date": "2023-02-15", "count": 1 }, { "date": "2023-02-16", "count": 1 }, { "date": "2023-02-17", "count": 1 }, { "date": "2023-04-20", "count": 1 }, { "date": "2023-04-22", "count": 1 }, { "date": "2023-06-09", "count": 1 }, { "date": "2023-11-18", "count": 1 }, { "date": "2024-01-01", "count": 1 }, { "date": "2024-01-08", "count": 1 }, { "date": "2024-01-14", "count": 1 }, { "date": "2024-03-19", "count": 1 }, { "date": "2024-07-02", "count": 1 }, { "date": "2025-04-04", "count": 1 }, { "date": "2025-05-17", "count": 1 } ], "complete": true, "collected": 32, "total_forks": 32 }, "star_history": null, "open_issues_and_prs": 0 }, "ai_readiness": { "has_nix": false, "example_dirs": [ "samples" ], "has_llms_txt": false, "has_dockerfile": false, "has_mcp_signal": false, "bootstrap_files": [], "api_schema_files": [], "has_devcontainer": false, "typecheck_configs": [ "tools/Blazor.DOM.TypeScriptModel/tsconfig.json" ], "toolchain_manifests": [ "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj", "samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj", "src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj", "src/Blazor.BrowserCoordination/Blazor.BrowserCoordination.csproj", "src/Blazor.Clipboard.WebAssembly/Blazor.Clipboard.WebAssembly.csproj", "src/Blazor.Clipboard/Blazor.Clipboard.csproj", "src/Blazor.Credentials.WebAssembly/Blazor.Credentials.WebAssembly.csproj", "src/Blazor.Credentials/Blazor.Credentials.csproj", "src/Blazor.DOM.Generation/Blazor.DOM.Generation.csproj", "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "src/Blazor.DOM/Blazor.DOM.csproj", "src/Blazor.FileSystemAccess.WebAssembly/Blazor.FileSystemAccess.WebAssembly.csproj", "src/Blazor.FileSystemAccess/Blazor.FileSystemAccess.csproj", "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj", "src/Blazor.Geolocation/Blazor.Geolocation.csproj", "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "src/Blazor.MediaDevices.WebAssembly/Blazor.MediaDevices.WebAssembly.csproj", "src/Blazor.MediaDevices/Blazor.MediaDevices.csproj", "src/Blazor.Notifications.WebAssembly/Blazor.Notifications.WebAssembly.csproj", "src/Blazor.Notifications/Blazor.Notifications.csproj", "src/Blazor.OfflineStorage.WebAssembly/Blazor.OfflineStorage.WebAssembly.csproj", "src/Blazor.OfflineStorage/Blazor.OfflineStorage.csproj", "src/Blazor.Performance.WebAssembly/Blazor.Performance.WebAssembly.csproj", "src/Blazor.Performance/Blazor.Performance.csproj", "src/Blazor.Permissions.WebAssembly/Blazor.Permissions.WebAssembly.csproj", "src/Blazor.Permissions/Blazor.Permissions.csproj", "src/Blazor.Screen.WebAssembly/Blazor.Screen.WebAssembly.csproj", "src/Blazor.Screen/Blazor.Screen.csproj", "src/Blazor.Serialization/Blazor.Serialization.csproj", "src/Blazor.SessionStorage.WebAssembly/Blazor.SessionStorage.WebAssembly.csproj", "src/Blazor.SessionStorage/Blazor.SessionStorage.csproj", "src/Blazor.Share.WebAssembly/Blazor.Share.WebAssembly.csproj", "src/Blazor.Share/Blazor.Share.csproj", "src/Blazor.SourceGenerators/Blazor.SourceGenerators.csproj", "src/Blazor.SpeechRecognition.WebAssembly/Blazor.SpeechRecognition.WebAssembly.csproj", "src/Blazor.SpeechRecognition/Blazor.SpeechRecognition.csproj", "src/Blazor.SpeechSynthesis.WebAssembly/Blazor.SpeechSynthesis.WebAssembly.csproj", "src/Blazor.SpeechSynthesis/Blazor.SpeechSynthesis.csproj", "src/Blazor.StorageManagement.WebAssembly/Blazor.StorageManagement.WebAssembly.csproj", "src/Blazor.StorageManagement/Blazor.StorageManagement.csproj", "src/Blazor.WakeLock.WebAssembly/Blazor.WakeLock.WebAssembly.csproj", "src/Blazor.WakeLock/Blazor.WakeLock.csproj", "src/Blazor.WebCrypto.WebAssembly/Blazor.WebCrypto.WebAssembly.csproj", "src/Blazor.WebCrypto/Blazor.WebCrypto.csproj", "tests/Blazor.BrowserCoordination.Tests/Blazor.BrowserCoordination.Tests.csproj", "tests/Blazor.Clipboard.Tests/Blazor.Clipboard.Tests.csproj", "tests/Blazor.Credentials.Tests/Blazor.Credentials.Tests.csproj", "tests/Blazor.DOM.Accessors.CompilationTests/Blazor.DOM.Accessors.CompilationTests.csproj", "tests/Blazor.DOM.AdvancedTypes.CompilationTests/Blazor.DOM.AdvancedTypes.CompilationTests.csproj", "tests/Blazor.DOM.CSharpGenerator.Tests/Blazor.DOM.CSharpGenerator.Tests.csproj", "tests/Blazor.DOM.Generic.CompilationTests/Blazor.DOM.Generic.CompilationTests.csproj", "tests/Blazor.DOM.GlobalNamespace.CompilationTests/Blazor.DOM.GlobalNamespace.CompilationTests.csproj", "tests/Blazor.DOM.NonEventDeferrals.CompilationTests/Blazor.DOM.NonEventDeferrals.CompilationTests.csproj", "tests/Blazor.DOM.ProfileRuntime/Blazor.DOM.ProfileRuntime.csproj", "tests/Blazor.DOM.ResolvedFailures.CompilationTests/Blazor.DOM.ResolvedFailures.CompilationTests.csproj", "tests/Blazor.DOM.Server.CompilationTests/Blazor.DOM.Server.CompilationTests.csproj", "tests/Blazor.DOM.SupplementalBrowserApis.CompilationTests/Blazor.DOM.SupplementalBrowserApis.CompilationTests.csproj", "tests/Blazor.DOM.Tests/Blazor.DOM.Tests.csproj", "tests/Blazor.DOM.TypedEvents.CompilationTests/Blazor.DOM.TypedEvents.CompilationTests.csproj", "tests/Blazor.DOM.TypedUnions.CompilationTests/Blazor.DOM.TypedUnions.CompilationTests.csproj", "tests/Blazor.DOM.WakeLock.CompilationTests/Blazor.DOM.WakeLock.CompilationTests.csproj", "tests/Blazor.DOM.WebAssembly.CompilationTests/Blazor.DOM.WebAssembly.CompilationTests.csproj", "tests/Blazor.ExampleConsumer.EndToEndTests/Blazor.ExampleConsumer.EndToEndTests.csproj", "tests/Blazor.FileSystemAccess.Tests/Blazor.FileSystemAccess.Tests.csproj", "tests/Blazor.OfflineStorage.Tests/Blazor.OfflineStorage.Tests.csproj", "tests/Blazor.Performance.Tests/Blazor.Performance.Tests.csproj", "tests/Blazor.Screen.Tests/Blazor.Screen.Tests.csproj", "tests/Blazor.Share.Tests/Blazor.Share.Tests.csproj", "tests/Blazor.SourceGenerators.Tests/Blazor.SourceGenerators.Tests.csproj", "tests/Blazor.StorageManagement.Tests/Blazor.StorageManagement.Tests.csproj", "tests/Blazor.WakeLock.Tests/Blazor.WakeLock.Tests.csproj", "tests/Blazor.WebCrypto.Tests/Blazor.WebCrypto.Tests.csproj", "tools/Blazor.DOM.CSharpGenerator/Blazor.DOM.CSharpGenerator.csproj" ], "largest_source_bytes": 816786, "source_files_sampled": 429, "oversized_source_files": 7, "agent_instruction_files": [], "agent_instruction_max_bytes": null }, "dependencies": { "manifests": [], "advisories": { "error": null, "scope": "repository_graph", "source": "osv", "findings": [ { "name": "fast-uri", "direct": false, "version": "3.1.3", "severity": "high", "ecosystem": "npm", "cvss_score": 7.5, "advisory_ids": [ "GHSA-v2hh-gcrm-f6hx" ], "fixed_version": "4.1.1", "advisory_count": 1, "oldest_advisory_days": 2 }, { "name": "ajv", "direct": false, "version": "8.17.1", "severity": "moderate", "ecosystem": "npm", "cvss_score": 5.3, "advisory_ids": [ "GHSA-2g4f-4pwh-qvx6" ], "fixed_version": "8.18.0", "advisory_count": 1, "oldest_advisory_days": 162 } ], "collected": true, "malicious": [], "truncated": false, "by_severity": { "high": 1, "moderate": 1 }, "advisory_count": 2, "affected_count": 2, "assessed_count": 19, "malicious_count": 0, "assessed_package": null, "unassessed_count": 19, "direct_affected_count": 0 }, "ecosystems": [], "dependencies": [ { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.AspNetCore.Components.WebAssembly", "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.DependencyInjection", "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.DOM/Blazor.DOM.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.DOM/Blazor.DOM.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.AspNetCore.Components.Web", "manifest": "src/Blazor.DOM/Blazor.DOM.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.DependencyInjection", "manifest": "src/Blazor.DOM/Blazor.DOM.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.JSInterop", "manifest": "src/Blazor.DOM/Blazor.DOM.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.AspNetCore.Components.Web", "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.AspNetCore.Components.Web", "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.DependencyInjection", "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.Primitives", "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.JSInterop", "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.SourceLink.GitHub", "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "MinVer", "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.DependencyInjection", "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.Extensions.Primitives", "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "ecosystem": "nuget", "version_constraint": null }, { "name": "Microsoft.JSInterop", "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "ecosystem": "nuget", "version_constraint": null } ], "all_dependencies": { "error": null, "source": "github-sbom", "packages": [ { "name": "Microsoft.AspNetCore.Components.Web", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.AspNetCore.Components.WebAssembly", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.Extensions.DependencyInjection", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.Extensions.Primitives", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.JSInterop", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.SourceLink.GitHub", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "MinVer", "direct": true, "version": null, "ecosystem": "nuget" }, { "name": "@pagefind/darwin-arm64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/darwin-x64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/freebsd-x64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/linux-arm64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/linux-x64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/windows-arm64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@pagefind/windows-x64", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "@types/node", "direct": false, "version": "26.1.1", "ecosystem": "npm" }, { "name": "@webgpu/types", "direct": false, "version": "0.1.71", "ecosystem": "npm" }, { "name": "@webref/idl", "direct": false, "version": "3.81.3", "ecosystem": "npm" }, { "name": "ajv", "direct": false, "version": "8.17.1", "ecosystem": "npm" }, { "name": "fast-deep-equal", "direct": false, "version": "3.1.3", "ecosystem": "npm" }, { "name": "fast-uri", "direct": false, "version": "3.1.3", "ecosystem": "npm" }, { "name": "json-schema-traverse", "direct": false, "version": "1.0.0", "ecosystem": "npm" }, { "name": "pagefind", "direct": false, "version": "1.5.0", "ecosystem": "npm" }, { "name": "require-from-string", "direct": false, "version": "2.0.2", "ecosystem": "npm" }, { "name": "typescript", "direct": false, "version": "5.9.3", "ecosystem": "npm" }, { "name": "undici-types", "direct": false, "version": "8.3.0", "ecosystem": "npm" }, { "name": "webidl2", "direct": false, "version": "24.5.0", "ecosystem": "npm" }, { "name": "Basic.Reference.Assemblies", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "coverlet.collector", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Deque.AxeCore.Playwright", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Humanizer.Core", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.AspNetCore.Components.WebAssembly.DevServer", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.CodeAnalysis.Analyzers", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.CodeAnalysis.CSharp", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.NET.Test.Sdk", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "Microsoft.Playwright", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "System.Reactive.Linq", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "xunit", "direct": false, "version": null, "ecosystem": "nuget" }, { "name": "xunit.runner.visualstudio", "direct": false, "version": null, "ecosystem": "nuget" } ], "collected": true, "truncated": false, "total_count": 38, "direct_count": 7, "indirect_count": 31 } }, "maintainership": { "issues": { "open_prs": 0, "merged_prs": 28, "open_issues": 0, "closed_ratio": 1, "closed_issues": 32, "closed_unmerged_prs": 3 }, "bus_factor": 1, "bot_contributors": 2, "top_contributors": [ { "type": "User", "login": "IEvangelist", "commits": 300, "avatar_url": "https://avatars.githubusercontent.com/u/7679720?v=4" }, { "type": "User", "login": "WeihanLi", "commits": 3, "avatar_url": "https://avatars.githubusercontent.com/u/7604648?v=4" }, { "type": "User", "login": "colindembovsky", "commits": 2, "avatar_url": "https://avatars.githubusercontent.com/u/1932561?v=4" }, { "type": "User", "login": "taori", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/5545184?v=4" }, { "type": "User", "login": "robertmclaws", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/1657085?v=4" }, { "type": "User", "login": "TanayParikh", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/14852843?v=4" } ], "contributors_sampled": 6, "top_contributor_share": 0.974 }, "quality_signals": { "has_ci": true, "has_tests": true, "ci_workflows": [ "build-validation.yml", "pr-validation.yml", "publish-nuget.yml", "publish-to-gh-pages.yml" ], "has_docs_dir": false, "linter_configs": [], "has_editorconfig": true, "has_linter_config": false, "has_precommit_config": false }, "security_signals": { "lockfiles": [ "package-lock.json" ], "scorecard": { "checks": [ { "name": "Binary-Artifacts", "score": 10, "reason": "no binaries found in the repo", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts" }, { "name": "Branch-Protection", "score": null, "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection" }, { "name": "CI-Tests", "score": 7, "reason": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests" }, { "name": "CII-Best-Practices", "score": 0, "reason": "no effort to earn an OpenSSF best practices badge detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices" }, { "name": "Code-Review", "score": 0, "reason": "Found 0/28 approved changesets -- score normalized to 0", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review" }, { "name": "Contributors", "score": 10, "reason": "project has 6 contributing companies or organizations", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors" }, { "name": "Dangerous-Workflow", "score": 10, "reason": "no dangerous workflow patterns detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow" }, { "name": "Dependency-Update-Tool", "score": 0, "reason": "no update tool detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool" }, { "name": "Fuzzing", "score": 0, "reason": "project is not fuzzed", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing" }, { "name": "License", "score": 10, "reason": "license file detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license" }, { "name": "Maintained", "score": 10, "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained" }, { "name": "Packaging", "score": 10, "reason": "packaging workflow detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging" }, { "name": "Pinned-Dependencies", "score": 1, "reason": "dependency not pinned by hash detected -- score normalized to 1", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies" }, { "name": "SAST", "score": 0, "reason": "SAST tool is not run on all commits -- score normalized to 0", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast" }, { "name": "Security-Policy", "score": 10, "reason": "security policy file detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy" }, { "name": "Signed-Releases", "score": null, "reason": "no releases found", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases" }, { "name": "Token-Permissions", "score": 0, "reason": "detected GitHub workflow tokens with excessive permissions", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions" }, { "name": "Vulnerabilities", "score": 8, "reason": "2 existing vulnerabilities detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities" } ], "commit": "abe9091425dc6bd6126011894642fc370bc2876d", "ran_at": "2026-07-24T19:01:55Z", "aggregate_score": 5.4, "scorecard_version": "v5.5.0" }, "has_codeql_workflow": false, "has_security_policy": false, "has_dependabot_config": false }, "contribution_flow": { "collected": true, "ci_last_run_at": "2026-07-24T19:01:34Z", "oldest_open_prs": [], "last_merged_pr_at": "2026-07-23T20:57:01Z", "ci_last_conclusion": "SUCCESS", "oldest_open_issues": [] } }, "config": { "disabled_metrics": [], "disabled_categories": [], "disabled_components": {} }, "source": { "url": "https://github.com/IEvangelist/blazorators", "host": "github.com", "name": "blazorators", "owner": "IEvangelist" }, "metrics": { "overall": { "key": "overall", "band": "moderate", "name": "Overall health", "note": null, "notes": [], "value": 68, "inputs": { "security": 63, "vitality": 74, "community": 64, "governance": 66, "engineering": 71 }, "components": [] }, "categories": [ { "key": "vitality", "band": "good", "name": "Vitality", "value": 74, "weight": 0.22, "metrics": [ { "key": "development_activity", "band": "moderate", "name": "Development activity", "note": null, "notes": [], "value": 68, "inputs": { "commits_last_year": 124, "human_commit_share": 1, "days_since_last_push": 0, "active_weeks_last_year": 5 }, "components": [ { "key": "push_recency", "name": "Push recency", "detail": "last push 0 days ago", "points": 36, "status": "met", "details": [ { "code": "push_recency", "params": { "days": 0 } } ], "max_points": 36 }, { "key": "commit_cadence", "name": "Commit cadence", "detail": "5/52 weeks with commits", "points": 3.5, "status": "partial", "details": [ { "code": "commit_cadence_weeks", "params": { "weeks": 5 } } ], "max_points": 36 }, { "key": "commit_volume", "name": "Commit volume", "detail": "124 commits in the last year", "points": 18, "status": "met", "details": [ { "code": "commits_last_year", "params": { "count": 124 } } ], "max_points": 18 }, { "key": "openssf_scorecard_maintained", "name": "OpenSSF Scorecard: Maintained", "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10", "points": 10, "status": "met", "details": [], "max_points": 10 } ] }, { "key": "release_discipline", "band": "good", "name": "Release discipline", "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "openssf_scorecard_signed_releases" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 84, "inputs": { "releases_count": 43, "latest_release_tag": "10.1.0", "releases_from_tags": false, "days_since_latest_release": 0, "mean_days_between_releases": 142 }, "components": [ { "key": "ships_releases", "name": "Ships releases", "detail": "43 releases published", "points": 27, "status": "met", "details": [ { "code": "releases_published", "params": { "count": 43 } } ], "max_points": 27 }, { "key": "release_recency", "name": "Release recency", "detail": "latest release 0 days ago", "points": 36, "status": "met", "details": [ { "code": "release_recency", "params": { "days": 0 } } ], "max_points": 36 }, { "key": "release_cadence", "name": "Release cadence", "detail": "a release every ~142 days", "points": 12.6, "status": "partial", "details": [ { "code": "release_cadence", "params": { "gap": 142 } } ], "max_points": 27 }, { "key": "openssf_scorecard_signed_releases", "name": "OpenSSF Scorecard: Signed-Releases", "detail": "no releases found", "points": 0, "status": "excluded", "details": [ { "code": "no_data", "params": {} } ], "max_points": 10 } ] }, { "key": "abandonment", "band": "excellent", "name": "Abandonment", "note": null, "notes": [], "value": 100, "inputs": { "cap": null, "state": "maintained", "guards": [], "signals": [], "red_flag": false, "multiplier_pct": 100, "declared_reason": null, "unverified_reason": null, "unanswered_open_prs": null, "unanswered_open_issues": null, "days_since_last_merged_pr": null, "days_since_last_human_commit": 0, "days_since_last_human_commit_is_floor": false }, "components": [ { "key": "project_is_still_maintained", "name": "Project is still maintained", "detail": "last human commit 0 days ago", "points": 100, "status": "met", "details": [ { "code": "abandonment_maintained", "params": { "days": 0 } } ], "max_points": 100 } ] } ], "description": "Is the project alive — is code being written and are releases shipping?" }, { "key": "community", "band": "moderate", "name": "Community & Adoption", "value": 64, "weight": 0.18, "metrics": [ { "key": "popularity", "band": "moderate", "name": "Popularity & adoption", "note": null, "notes": [], "value": 60, "inputs": { "forks": 32, "stars": 392, "watchers": 13, "growth_state": "unverified", "growth_factor_pct": 100, "growth_unverified_reason": "no_history" }, "components": [ { "key": "stars", "name": "Stars", "detail": "392 stars", "points": 42, "status": "partial", "details": [ { "code": "stars", "params": { "count": 392 } } ], "max_points": 60 }, { "key": "forks", "name": "Forks", "detail": "32 forks", "points": 12.4, "status": "partial", "details": [ { "code": "forks", "params": { "count": 32 } } ], "max_points": 25 }, { "key": "watchers", "name": "Watchers", "detail": "13 watchers", "points": 6, "status": "partial", "details": [ { "code": "watchers", "params": { "count": 13 } } ], "max_points": 15 } ] }, { "key": "community_health", "band": "moderate", "name": "Community health", "note": null, "notes": [], "value": 65, "inputs": { "has_readme": true, "has_license": true, "has_contributing": false, "has_issue_template": false, "has_code_of_conduct": true, "has_pull_request_template": false }, "components": [ { "key": "readme", "name": "README", "detail": null, "points": 22.5, "status": "met", "details": [], "max_points": 22.5 }, { "key": "license", "name": "License", "detail": "recognized license (MIT)", "points": 22.5, "status": "met", "details": [ { "code": "license_standard", "params": {} }, { "code": "license_spdx", "params": { "spdx": "MIT" } } ], "max_points": 22.5 }, { "key": "contributing_guide", "name": "CONTRIBUTING guide", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 18 }, { "key": "code_of_conduct", "name": "Code of conduct", "detail": null, "points": 13.5, "status": "met", "details": [], "max_points": 13.5 }, { "key": "issue_template", "name": "Issue template", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 7.2 }, { "key": "pr_template", "name": "PR template", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 6.3 } ] }, { "key": "ecosystem_adoption", "band": "moderate", "name": "Ecosystem adoption (downloads)", "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "registry_dependents" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 68, "inputs": { "packages": [ "Blazor.DOM", "Blazor.Clipboard", "Blazor.Credentials", "Blazor.Geolocation", "Blazor.LocalStorage", "Blazor.MediaDevices" ], "dependents": null, "ecosystems": "nuget", "total_downloads": 178869, "monthly_downloads": null }, "components": [ { "key": "total_downloads", "name": "Total downloads", "detail": "178,869 downloads all-time across nuget", "points": 54.6, "status": "partial", "details": [ { "code": "downloads_total", "params": { "count": 178869, "ecosystems": "nuget" } } ], "max_points": 80 }, { "key": "registry_dependents", "name": "Registry dependents", "detail": "not reported by this ecosystem", "points": 0, "status": "excluded", "details": [ { "code": "not_reported_by_this_ecosystem", "params": {} } ], "max_points": 20 } ] } ], "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?" }, { "key": "governance", "band": "moderate", "name": "Sustainability & Governance", "value": 66, "weight": 0.24, "metrics": [ { "key": "maintainer_resilience", "band": "critical", "name": "Maintainer resilience (bus factor)", "note": null, "notes": [], "value": 28, "inputs": { "bus_factor": 1, "contributors_sampled": 6, "top_contributor_share": 0.974 }, "components": [ { "key": "bus_factor", "name": "Bus factor", "detail": "1 contributor(s) cover half of all commits", "points": 9, "status": "partial", "details": [ { "code": "bus_factor", "params": { "count": 1 } } ], "max_points": 54 }, { "key": "commit_distribution", "name": "Commit distribution", "detail": "top contributor authored 97% of commits", "points": 0.6, "status": "partial", "details": [ { "code": "top_contributor_share", "params": { "share": 97 } } ], "max_points": 22.5 }, { "key": "contributor_breadth", "name": "Contributor breadth", "detail": "6 contributors", "points": 8.1, "status": "partial", "details": [ { "code": "contributors_sampled", "params": { "count": 6 } } ], "max_points": 13.5 }, { "key": "openssf_scorecard_contributors", "name": "OpenSSF Scorecard: Contributors", "detail": "project has 6 contributing companies or organizations", "points": 10, "status": "met", "details": [], "max_points": 10 } ] }, { "key": "responsiveness", "band": "good", "name": "Issue & PR responsiveness", "note": null, "notes": [], "value": 81, "inputs": { "merged_prs": 28, "open_issues": 0, "closed_issues": 32, "issue_closed_ratio": 1, "closed_unmerged_prs": 3 }, "components": [ { "key": "issue_resolution", "name": "Issue resolution", "detail": "100% of issues closed", "points": 46.8, "status": "met", "details": [ { "code": "issues_closed_share", "params": { "share": 100 } } ], "max_points": 46.75 }, { "key": "pr_acceptance", "name": "PR acceptance", "detail": "28/31 decided PRs merged", "points": 34.5, "status": "partial", "details": [ { "code": "decided_prs_merged", "params": { "merged": 28, "decided": 31 } } ], "max_points": 38.25 }, { "key": "openssf_scorecard_code_review", "name": "OpenSSF Scorecard: Code-Review", "detail": "Found 0/28 approved changesets -- score normalized to 0", "points": 0, "status": "missed", "details": [], "max_points": 15 } ] }, { "key": "stewardship", "band": "good", "name": "Ownership & stewardship", "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "verified_domain" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 71, "inputs": { "followers": 1017, "owner_type": "User", "is_verified": null, "owner_login": "IEvangelist", "public_repos": 336, "account_age_days": 4445 }, "components": [ { "key": "ownership_backing", "name": "Ownership backing", "detail": "personal (user) account", "points": 10, "status": "partial", "details": [ { "code": "owner_personal", "params": {} } ], "max_points": 30 }, { "key": "verified_domain", "name": "Verified domain", "detail": "not applicable to user accounts", "points": 0, "status": "excluded", "details": [ { "code": "not_applicable_to_user_accounts", "params": {} } ], "max_points": 20 }, { "key": "owner_reach", "name": "Owner reach", "detail": "1,017 followers of IEvangelist", "points": 21.6, "status": "partial", "details": [ { "code": "owner_followers", "params": { "count": 1017, "login": "IEvangelist" } } ], "max_points": 25 }, { "key": "track_record", "name": "Track record", "detail": "336 public repos, account ~12 yr old", "points": 25, "status": "met", "details": [ { "code": "public_repos", "params": { "count": 336 } }, { "code": "account_age_years", "params": { "years": 12 } } ], "max_points": 25 } ] }, { "key": "package_maintenance", "band": "excellent", "name": "Package maintenance", "note": null, "notes": [], "value": 100, "inputs": { "packages": [ "Blazor.DOM", "Blazor.Clipboard", "Blazor.Credentials", "Blazor.Geolocation", "Blazor.LocalStorage", "Blazor.MediaDevices" ], "ecosystems": "nuget", "any_deprecated": false, "min_days_since_publish": 0 }, "components": [ { "key": "published_resolvable", "name": "Published & resolvable", "detail": "6 package(s) on nuget", "points": 25, "status": "met", "details": [ { "code": "packages_published", "params": { "count": 6, "ecosystems": "nuget" } } ], "max_points": 25 }, { "key": "publish_recency", "name": "Publish recency", "detail": "latest publish 0 days ago", "points": 35, "status": "met", "details": [ { "code": "publish_recency", "params": { "days": 0 } } ], "max_points": 35 }, { "key": "version_history", "name": "Version history", "detail": "19 published versions", "points": 20, "status": "met", "details": [ { "code": "published_versions", "params": { "count": 19 } } ], "max_points": 20 }, { "key": "not_deprecated", "name": "Not deprecated", "detail": "active, not deprecated or yanked", "points": 20, "status": "met", "details": [ { "code": "package_not_deprecated", "params": {} } ], "max_points": 20 } ] } ], "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?" }, { "key": "engineering", "band": "good", "name": "Engineering Quality", "value": 71, "weight": 0.2, "metrics": [ { "key": "engineering_practices", "band": "moderate", "name": "Engineering practices", "note": null, "notes": [], "value": 68, "inputs": { "has_ci": true, "has_tests": true, "has_editorconfig": true, "has_linter_config": false, "has_precommit_config": false }, "components": [ { "key": "ci_workflows", "name": "CI workflows", "detail": "4 workflow(s)", "points": 24, "status": "met", "details": [ { "code": "ci_workflows", "params": { "count": 4 } } ], "max_points": 24 }, { "key": "tests_present", "name": "Tests present", "detail": null, "points": 24, "status": "met", "details": [], "max_points": 24 }, { "key": "linter_config", "name": "Linter config", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 16 }, { "key": "pre_commit_hooks", "name": "Pre-commit hooks", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 9.6 }, { "key": "editorconfig", "name": ".editorconfig", "detail": null, "points": 6.4, "status": "met", "details": [], "max_points": 6.4 }, { "key": "openssf_scorecard_ci_tests", "name": "OpenSSF Scorecard: CI-Tests", "detail": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7", "points": 14, "status": "partial", "details": [], "max_points": 20 } ] }, { "key": "documentation", "band": "good", "name": "Documentation", "note": null, "notes": [], "value": 75, "inputs": { "topics": [ "blazor", "blazor-webassembly", "javascript", "typescript", "javascript-interop", "source-generators", "hacktoberfest" ], "has_wiki": true, "homepage": "https://ievangelist.github.io/blazorators/", "has_readme": true, "has_docs_dir": false, "has_description": true }, "components": [ { "key": "readme", "name": "README", "detail": null, "points": 30, "status": "met", "details": [], "max_points": 30 }, { "key": "documentation_directory", "name": "Documentation directory", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 25 }, { "key": "documentation_homepage_site", "name": "Documentation / homepage site", "detail": "https://ievangelist.github.io/blazorators/", "points": 15, "status": "met", "details": [], "max_points": 15 }, { "key": "repository_description", "name": "Repository description", "detail": null, "points": 10, "status": "met", "details": [], "max_points": 10 }, { "key": "topics", "name": "Topics", "detail": "7 topics", "points": 10, "status": "met", "details": [ { "code": "topics_count", "params": { "count": 7 } } ], "max_points": 10 }, { "key": "wiki", "name": "Wiki", "detail": null, "points": 10, "status": "met", "details": [], "max_points": 10 } ] } ], "description": "Are baseline engineering and documentation practices in place?" }, { "key": "security", "band": "moderate", "name": "Security", "value": 63, "weight": 0.16, "metrics": [ { "key": "security_posture", "band": "moderate", "name": "Security posture", "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Signed-Releases. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "branch_protection", "signed_releases" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 54, "inputs": { "source": "openssf_scorecard", "checks_evaluated": 16, "scorecard_version": "v5.5.0", "checks_inconclusive": 2, "scorecard_aggregate": 5.4 }, "components": [ { "key": "binary_artifacts", "name": "Binary-Artifacts", "detail": "no binaries found in the repo", "points": 7.5, "status": "met", "details": [], "max_points": 7.5 }, { "key": "branch_protection", "name": "Branch-Protection", "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md", "points": 0, "status": "excluded", "details": [ { "code": "no_data", "params": {} } ], "max_points": 7.5 }, { "key": "ci_tests", "name": "CI-Tests", "detail": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7", "points": 1.8, "status": "partial", "details": [], "max_points": 2.5 }, { "key": "cii_best_practices", "name": "CII-Best-Practices", "detail": "no effort to earn an OpenSSF best practices badge detected", "points": 0, "status": "missed", "details": [], "max_points": 2.5 }, { "key": "code_review", "name": "Code-Review", "detail": "Found 0/28 approved changesets -- score normalized to 0", "points": 0, "status": "missed", "details": [], "max_points": 7.5 }, { "key": "contributors", "name": "Contributors", "detail": "project has 6 contributing companies or organizations", "points": 2.5, "status": "met", "details": [], "max_points": 2.5 }, { "key": "dangerous_workflow", "name": "Dangerous-Workflow", "detail": "no dangerous workflow patterns detected", "points": 10, "status": "met", "details": [], "max_points": 10 }, { "key": "dependency_update_tool", "name": "Dependency-Update-Tool", "detail": "no update tool detected", "points": 0, "status": "missed", "details": [], "max_points": 7.5 }, { "key": "fuzzing", "name": "Fuzzing", "detail": "project is not fuzzed", "points": 0, "status": "missed", "details": [], "max_points": 5 }, { "key": "license", "name": "License", "detail": "license file detected", "points": 2.5, "status": "met", "details": [], "max_points": 2.5 }, { "key": "maintained", "name": "Maintained", "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10", "points": 7.5, "status": "met", "details": [], "max_points": 7.5 }, { "key": "packaging", "name": "Packaging", "detail": "packaging workflow detected", "points": 5, "status": "met", "details": [], "max_points": 5 }, { "key": "pinned_dependencies", "name": "Pinned-Dependencies", "detail": "dependency not pinned by hash detected -- score normalized to 1", "points": 0.5, "status": "partial", "details": [], "max_points": 5 }, { "key": "sast", "name": "SAST", "detail": "SAST tool is not run on all commits -- score normalized to 0", "points": 0, "status": "missed", "details": [], "max_points": 5 }, { "key": "security_policy", "name": "Security-Policy", "detail": "security policy file detected", "points": 5, "status": "met", "details": [], "max_points": 5 }, { "key": "signed_releases", "name": "Signed-Releases", "detail": "no releases found", "points": 0, "status": "excluded", "details": [ { "code": "no_data", "params": {} } ], "max_points": 7.5 }, { "key": "token_permissions", "name": "Token-Permissions", "detail": "detected GitHub workflow tokens with excessive permissions", "points": 0, "status": "missed", "details": [], "max_points": 7.5 }, { "key": "vulnerabilities", "name": "Vulnerabilities", "detail": "2 existing vulnerabilities detected", "points": 6, "status": "partial", "details": [], "max_points": 7.5 } ] }, { "key": "dependency_advisories", "band": "excellent", "name": "Dependency advisories", "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 19 resolved dependencies against OSV; 19 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "indirect_dependencies_free_of_known_advisories", "no_advisories_left_outstanding" ] } }, { "code": "weights_renormalized", "params": {} }, { "code": "advisories_scope_repository", "params": { "assessed": 19 } }, { "code": "advisories_unassessed", "params": { "count": 19 } }, { "code": "advisories_repo_graph_caveat", "params": {} }, { "code": "advisories_reachability", "params": {} } ], "value": 100, "inputs": { "source": "osv", "advisories": 2, "affected_packages": 2, "assessed_packages": 19, "unassessed_packages": 19, "affected_by_severity": "high 1, moderate 1", "direct_affected_packages": 0 }, "components": [ { "key": "direct_dependencies_free_of_known_advisories", "name": "Direct dependencies free of known advisories", "detail": "no direct dependency carries a known advisory", "points": 35, "status": "met", "details": [ { "code": "no_direct_advisories", "params": {} } ], "max_points": 35 }, { "key": "indirect_dependencies_free_of_known_advisories", "name": "Indirect dependencies free of known advisories", "detail": "transitive set not separable from development and test dependencies in this scope", "points": 0, "status": "excluded", "details": [ { "code": "advisories_scope_not_separable", "params": {} } ], "max_points": 25 }, { "key": "no_advisories_left_outstanding", "name": "No advisories left outstanding", "detail": "no advisory carries a publication date", "points": 0, "status": "excluded", "details": [ { "code": "advisories_no_publication_date", "params": {} } ], "max_points": 40 } ] }, { "key": "malicious_dependencies", "band": "excellent", "name": "Malicious dependencies", "note": null, "notes": [], "value": 100, "inputs": { "source": "osv", "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored", "packages": [], "red_flag": false, "assessed_packages": 19, "malicious_packages": 0, "direct_malicious_packages": 0, "withdrawn_malicious_packages": 0, "installable_malicious_packages": 0 }, "components": [ { "key": "no_dependency_reported_as_a_malicious_package", "name": "No dependency reported as a malicious package", "detail": "no dependency is reported as a malicious package", "points": 100, "status": "met", "details": [ { "code": "no_malicious_dependencies", "params": {} } ], "max_points": 100 } ] }, { "key": "high_risk_jurisdiction_exposure", "band": "excellent", "name": "High-Risk Jurisdiction Exposure", "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.", "notes": [ { "code": "jurisdiction_evidence_limits", "params": {} } ], "value": 100, "inputs": { "meaning": "self-published location evidence; not nationality or citizenship", "red_flag": false, "exposures": [], "policy_countries": [ "Russia", "Iran", "North Korea" ], "review_only_matches": 0, "assessed_self_published_locations": 14 }, "components": [ { "key": "policy_exposure_multiplier", "name": "Policy exposure multiplier", "detail": "no confirmed policy-scope location match", "points": 100, "status": "met", "details": [ { "code": "jurisdiction_no_match", "params": {} } ], "max_points": 100 } ] } ], "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?" }, { "key": "ai_readiness", "band": "moderate", "name": "AI Readiness", "value": 60, "weight": 0, "metrics": [ { "key": "ai_agent_context", "band": "at_risk", "name": "Agent context & guidance", "note": null, "notes": [], "value": 40, "inputs": { "has_llms_txt": false, "legible_history_share": 0.92, "agent_instruction_files": [], "agent_instruction_max_bytes": null }, "components": [ { "key": "agent_instructions", "name": "Agent instructions", "detail": "no CLAUDE.md / AGENTS.md / editor rules", "points": 0, "status": "missed", "details": [ { "code": "no_agent_instructions", "params": {} } ], "max_points": 45 }, { "key": "machine_readable_docs_llms_txt", "name": "Machine-readable docs (llms.txt)", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 15 }, { "key": "legible_commit_history", "name": "Legible commit history", "detail": "92 of 100 human commits state their intent (structured subject or explanatory body)", "points": 40, "status": "met", "details": [ { "code": "legible_history", "params": { "legible": 92, "sampled": 100 } } ], "max_points": 40 } ] }, { "key": "ai_verify_loop", "band": "moderate", "name": "Verify loop (build / test / typecheck)", "note": null, "notes": [], "value": 67, "inputs": { "has_nix": false, "has_tests": true, "lockfiles": [ "package-lock.json" ], "has_dockerfile": false, "typed_language": true, "bootstrap_files": [], "has_devcontainer": false, "has_linter_config": false, "typecheck_configs": [ "tools/Blazor.DOM.TypeScriptModel/tsconfig.json" ], "agent_commit_share": 0.98, "toolchain_manifests": [ "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj", "samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj", "src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj", "src/Blazor.BrowserCoordination/Blazor.BrowserCoordination.csproj", "src/Blazor.Clipboard.WebAssembly/Blazor.Clipboard.WebAssembly.csproj", "src/Blazor.Clipboard/Blazor.Clipboard.csproj", "src/Blazor.Credentials.WebAssembly/Blazor.Credentials.WebAssembly.csproj", "src/Blazor.Credentials/Blazor.Credentials.csproj", "src/Blazor.DOM.Generation/Blazor.DOM.Generation.csproj", "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj", "src/Blazor.DOM/Blazor.DOM.csproj", "src/Blazor.FileSystemAccess.WebAssembly/Blazor.FileSystemAccess.WebAssembly.csproj", "src/Blazor.FileSystemAccess/Blazor.FileSystemAccess.csproj", "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj", "src/Blazor.Geolocation/Blazor.Geolocation.csproj", "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj", "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj", "src/Blazor.MediaDevices.WebAssembly/Blazor.MediaDevices.WebAssembly.csproj", "src/Blazor.MediaDevices/Blazor.MediaDevices.csproj", "src/Blazor.Notifications.WebAssembly/Blazor.Notifications.WebAssembly.csproj", "src/Blazor.Notifications/Blazor.Notifications.csproj", "src/Blazor.OfflineStorage.WebAssembly/Blazor.OfflineStorage.WebAssembly.csproj", "src/Blazor.OfflineStorage/Blazor.OfflineStorage.csproj", "src/Blazor.Performance.WebAssembly/Blazor.Performance.WebAssembly.csproj", "src/Blazor.Performance/Blazor.Performance.csproj", "src/Blazor.Permissions.WebAssembly/Blazor.Permissions.WebAssembly.csproj", "src/Blazor.Permissions/Blazor.Permissions.csproj", "src/Blazor.Screen.WebAssembly/Blazor.Screen.WebAssembly.csproj", "src/Blazor.Screen/Blazor.Screen.csproj", "src/Blazor.Serialization/Blazor.Serialization.csproj", "src/Blazor.SessionStorage.WebAssembly/Blazor.SessionStorage.WebAssembly.csproj", "src/Blazor.SessionStorage/Blazor.SessionStorage.csproj", "src/Blazor.Share.WebAssembly/Blazor.Share.WebAssembly.csproj", "src/Blazor.Share/Blazor.Share.csproj", "src/Blazor.SourceGenerators/Blazor.SourceGenerators.csproj", "src/Blazor.SpeechRecognition.WebAssembly/Blazor.SpeechRecognition.WebAssembly.csproj", "src/Blazor.SpeechRecognition/Blazor.SpeechRecognition.csproj", "src/Blazor.SpeechSynthesis.WebAssembly/Blazor.SpeechSynthesis.WebAssembly.csproj", "src/Blazor.SpeechSynthesis/Blazor.SpeechSynthesis.csproj", "src/Blazor.StorageManagement.WebAssembly/Blazor.StorageManagement.WebAssembly.csproj", "src/Blazor.StorageManagement/Blazor.StorageManagement.csproj", "src/Blazor.WakeLock.WebAssembly/Blazor.WakeLock.WebAssembly.csproj", "src/Blazor.WakeLock/Blazor.WakeLock.csproj", "src/Blazor.WebCrypto.WebAssembly/Blazor.WebCrypto.WebAssembly.csproj", "src/Blazor.WebCrypto/Blazor.WebCrypto.csproj", "tests/Blazor.BrowserCoordination.Tests/Blazor.BrowserCoordination.Tests.csproj", "tests/Blazor.Clipboard.Tests/Blazor.Clipboard.Tests.csproj", "tests/Blazor.Credentials.Tests/Blazor.Credentials.Tests.csproj", "tests/Blazor.DOM.Accessors.CompilationTests/Blazor.DOM.Accessors.CompilationTests.csproj", "tests/Blazor.DOM.AdvancedTypes.CompilationTests/Blazor.DOM.AdvancedTypes.CompilationTests.csproj", "tests/Blazor.DOM.CSharpGenerator.Tests/Blazor.DOM.CSharpGenerator.Tests.csproj", "tests/Blazor.DOM.Generic.CompilationTests/Blazor.DOM.Generic.CompilationTests.csproj", "tests/Blazor.DOM.GlobalNamespace.CompilationTests/Blazor.DOM.GlobalNamespace.CompilationTests.csproj", "tests/Blazor.DOM.NonEventDeferrals.CompilationTests/Blazor.DOM.NonEventDeferrals.CompilationTests.csproj", "tests/Blazor.DOM.ProfileRuntime/Blazor.DOM.ProfileRuntime.csproj", "tests/Blazor.DOM.ResolvedFailures.CompilationTests/Blazor.DOM.ResolvedFailures.CompilationTests.csproj", "tests/Blazor.DOM.Server.CompilationTests/Blazor.DOM.Server.CompilationTests.csproj", "tests/Blazor.DOM.SupplementalBrowserApis.CompilationTests/Blazor.DOM.SupplementalBrowserApis.CompilationTests.csproj", "tests/Blazor.DOM.Tests/Blazor.DOM.Tests.csproj", "tests/Blazor.DOM.TypedEvents.CompilationTests/Blazor.DOM.TypedEvents.CompilationTests.csproj", "tests/Blazor.DOM.TypedUnions.CompilationTests/Blazor.DOM.TypedUnions.CompilationTests.csproj", "tests/Blazor.DOM.WakeLock.CompilationTests/Blazor.DOM.WakeLock.CompilationTests.csproj", "tests/Blazor.DOM.WebAssembly.CompilationTests/Blazor.DOM.WebAssembly.CompilationTests.csproj", "tests/Blazor.ExampleConsumer.EndToEndTests/Blazor.ExampleConsumer.EndToEndTests.csproj", "tests/Blazor.FileSystemAccess.Tests/Blazor.FileSystemAccess.Tests.csproj", "tests/Blazor.OfflineStorage.Tests/Blazor.OfflineStorage.Tests.csproj", "tests/Blazor.Performance.Tests/Blazor.Performance.Tests.csproj", "tests/Blazor.Screen.Tests/Blazor.Screen.Tests.csproj", "tests/Blazor.Share.Tests/Blazor.Share.Tests.csproj", "tests/Blazor.SourceGenerators.Tests/Blazor.SourceGenerators.Tests.csproj", "tests/Blazor.StorageManagement.Tests/Blazor.StorageManagement.Tests.csproj", "tests/Blazor.WakeLock.Tests/Blazor.WakeLock.Tests.csproj", "tests/Blazor.WebCrypto.Tests/Blazor.WebCrypto.Tests.csproj", "tools/Blazor.DOM.CSharpGenerator/Blazor.DOM.CSharpGenerator.csproj" ], "dependency_bot_commit_share": 0 }, "components": [ { "key": "one_command_bootstrap", "name": "One-command bootstrap", "detail": "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj (toolchain convention, no task runner)", "points": 12.6, "status": "partial", "details": [ { "code": "toolchain_convention", "params": { "files": "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj" } } ], "max_points": 18 }, { "key": "automated_tests", "name": "Automated tests", "detail": null, "points": 22, "status": "met", "details": [], "max_points": 22 }, { "key": "lint_format_config", "name": "Lint / format config", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 11 }, { "key": "static_type_checking", "name": "Static type checking", "detail": "tools/Blazor.DOM.TypeScriptModel/tsconfig.json", "points": 11, "status": "met", "details": [ { "code": "file_list", "params": { "files": "tools/Blazor.DOM.TypeScriptModel/tsconfig.json" } } ], "max_points": 11 }, { "key": "reproducible_environment", "name": "Reproducible environment", "detail": "lockfile", "points": 10, "status": "met", "details": [ { "code": "file_list", "params": { "files": "lockfile" } } ], "max_points": 10 }, { "key": "demonstrated_agent_practice", "name": "Demonstrated agent practice", "detail": "98 of the last 100 commits agent-authored or agent-credited", "points": 10, "status": "met", "details": [ { "code": "agent_authored_commits", "params": { "count": 98, "sampled": 100 } } ], "max_points": 10 }, { "key": "automated_maintenance", "name": "Automated maintenance", "detail": "no automated dependency updates observed", "points": 0, "status": "missed", "details": [ { "code": "no_dependency_automation", "params": {} } ], "max_points": 8 }, { "key": "openssf_scorecard_pinned_dependencies", "name": "OpenSSF Scorecard: Pinned-Dependencies", "detail": "dependency not pinned by hash detected -- score normalized to 1", "points": 1, "status": "partial", "details": [], "max_points": 10 } ] }, { "key": "ai_code_legibility", "band": "excellent", "name": "Code legibility for models", "note": null, "notes": [], "value": 99, "inputs": { "primary_language": "C#", "largest_source_bytes": 816786, "source_files_sampled": 429, "oversized_source_files": 7 }, "components": [ { "key": "type_checkable_code", "name": "Type-checkable code", "detail": "C# (statically typed)", "points": 45, "status": "met", "details": [ { "code": "statically_typed_language", "params": { "language": "C#" } } ], "max_points": 45 }, { "key": "manageable_file_sizes", "name": "Manageable file sizes", "detail": "7/429 source files over 60KB", "points": 54.1, "status": "partial", "details": [ { "code": "oversized_source_files", "params": { "kb": 60, "sampled": 429, "oversized": 7 } } ], "max_points": 55 } ] }, { "key": "ai_interfaces", "band": "at_risk", "name": "Machine-readable interfaces", "note": null, "notes": [], "value": 40, "inputs": { "example_dirs": [ "samples" ], "has_mcp_signal": false, "api_schema_files": [] }, "components": [ { "key": "api_schema_openapi_graphql_proto", "name": "API schema (OpenAPI/GraphQL/proto)", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 40 }, { "key": "mcp_server", "name": "MCP server", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 20 }, { "key": "runnable_examples", "name": "Runnable examples", "detail": "samples", "points": 40, "status": "met", "details": [ { "code": "file_list", "params": { "files": "samples" } } ], "max_points": 40 } ] } ], "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score." } ], "metrics_version": "1.13.0" }, "warnings": [ "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token", "nuget package 'Blazor.Notifications' points at a different repository (https://github.com/vertonghenb/Blazor.Notifications); excluded from ecosystem scoring", "Could not fetch nuget package 'Blazor.DOM.WebAssembly' from its registry" ], "report_type": "repository", "generated_at": "2026-07-24T19:02:09.211042Z", "schema_version": "0.27.0", "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/i/IEvangelist/blazorators.svg", "full_name": "IEvangelist/blazorators", "license_state": "standard", "license_spdx": "MIT" }, "repoMeta": null, "notFound": false, "related": [ { "id": 8520, "full_name": "pulumi/coconut", "url": "https://github.com/pulumi/coconut", "description": "Pulumi - Infrastructure as Code in any programming language 🚀", "ecosystem": "go", "ecosystems": [ "go", "npm", "pypi" ], "primary_language": "Go", "languages": [ "Go" ], "topics": [ "infrastructure-as-code", "serverless", "containers", "aws", "azure", "gcp", "kubernetes", "cloud", "cloud-computing", "iac", "csharp", "typescript", "javascript", "golang", "go", "dotnet", "fsharp", "python" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25446, "forks": 1400, "watchers": 190, "monthly_downloads": null, "latest_score": 88, "latest_band": "excellent", "latest_scanned_at": "2026-07-16T00:04:24.854453Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" }, { "id": 8508, "full_name": "marapongo/mu", "url": "https://github.com/marapongo/mu", "description": "Pulumi - Infrastructure as Code in any programming language 🚀", "ecosystem": "go", "ecosystems": [ "go", "npm", "pypi" ], "primary_language": "Go", "languages": [ "Go" ], "topics": [ "infrastructure-as-code", "serverless", "containers", "aws", "azure", "gcp", "kubernetes", "cloud", "cloud-computing", "iac", "csharp", "typescript", "javascript", "golang", "go", "dotnet", "fsharp", "python" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25446, "forks": 1400, "watchers": 190, "monthly_downloads": null, "latest_score": 88, "latest_band": "excellent", "latest_scanned_at": "2026-07-16T00:03:47.348908Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" }, { "id": 8521, "full_name": "pulumi/lumi", "url": "https://github.com/pulumi/lumi", "description": "Pulumi - Infrastructure as Code in any programming language 🚀", "ecosystem": "go", "ecosystems": [ "go", "npm", "pypi" ], "primary_language": "Go", "languages": [ "Go" ], "topics": [ "infrastructure-as-code", "serverless", "containers", "aws", "azure", "gcp", "kubernetes", "cloud", "cloud-computing", "iac", "csharp", "typescript", "javascript", "golang", "go", "dotnet", "fsharp", "python" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25446, "forks": 1400, "watchers": 190, "monthly_downloads": null, "latest_score": 88, "latest_band": "excellent", "latest_scanned_at": "2026-07-16T00:04:26.631408Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" }, { "id": 8526, "full_name": "pulumi/pulumi-fabric", "url": "https://github.com/pulumi/pulumi-fabric", "description": "Pulumi - Infrastructure as Code in any programming language 🚀", "ecosystem": "go", "ecosystems": [ "go", "npm", "pypi" ], "primary_language": "Go", "languages": [ "Go" ], "topics": [ "infrastructure-as-code", "serverless", "containers", "aws", "azure", "gcp", "kubernetes", "cloud", "cloud-computing", "iac", "csharp", "typescript", "javascript", "golang", "go", "dotnet", "fsharp", "python" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25446, "forks": 1400, "watchers": 190, "monthly_downloads": null, "latest_score": 88, "latest_band": "excellent", "latest_scanned_at": "2026-07-16T00:05:04.618338Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" }, { "id": 13240, "full_name": "Pulumi/pulumi", "url": "https://github.com/Pulumi/pulumi", "description": "Pulumi - Infrastructure as Code in any programming language 🚀", "ecosystem": "npm", "ecosystems": [ "npm", "go", "pypi" ], "primary_language": "Go", "languages": [ "Go" ], "topics": [ "infrastructure-as-code", "serverless", "containers", "aws", "azure", "gcp", "kubernetes", "cloud", "cloud-computing", "iac", "csharp", "typescript", "javascript", "golang", "go", "dotnet", "fsharp", "python" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25448, "forks": 1402, "watchers": 190, "monthly_downloads": 22181, "latest_score": 87, "latest_band": "excellent", "latest_scanned_at": "2026-07-17T06:52:58.753694Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" }, { "id": 30292, "full_name": "microsoft/kiota", "url": "https://github.com/microsoft/kiota", "description": "OpenAPI based HTTP Client code generator", "ecosystem": "npm", "ecosystems": [ "npm" ], "primary_language": "C#", "languages": [ "C#" ], "topics": [ "openapi", "csharp", "typescript", "java", "dotnet", "golang", "ruby", "php", "http", "api", "python", "kiota", "hacktoberfest", "openapi-codegen", "openapi-specification", "openapi3" ], "license_spdx": "MIT", "license_state": "standard", "stars": 3786, "forks": 326, "watchers": 42, "monthly_downloads": null, "latest_score": 85, "latest_band": "excellent", "latest_scanned_at": "2026-07-20T23:26:18.979279Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "unverified", "red_flags": [], "badge_url": "" } ] } }
Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-24 19:02 UTC

IEvangelist / blazorators

This project converts TypeScript type declarations into C# representations, and use C# source generators to expose automatic JavaScript interop functionality.

C#MIT★ 392 estrellas⑂ 32 forksdesde oct 2021Ver en GitHub ↗

IEvangelist/blazorators tiene un índice de salud de 68 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (74/100) y la más baja, AI Readiness (60/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

68
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

68
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

David PineCuenta personal
1017 seguidores336 repositorios públicosdesde may 2014@microsoft

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

Ecosistemas de paquetes

Métricas por categoría

Vitalidad

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

74Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
3.5/36Cadencia de commits — 5/52 semanas con commits
18/18Volumen de commits — 124 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year124
human_commit_share1
days_since_last_push0
active_weeks_last_year5
Cómo se puntúa
27/27Publica versiones — 43 versiones publicadas
36/36Recencia de las versiones — última versión hace 0 días
12.6/27Cadencia de publicación — una versión cada ~142 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count43
latest_release_tag10.1.0
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases142
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

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

64Moderado · 18% del índice global
Cómo se puntúa
42/60Estrellas — 392 estrellas
12.4/25Forks — 32 forks
6/15Observadores — 13 observadores
Datos de entrada utilizados
forks32
stars392
watchers13
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
0/18Guía CONTRIBUTING
13.5/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conduct
has_pull_request_templateno
Cómo se puntúa
54.6/80Descargas totales — 178.869 descargas históricas en nuget
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packagesBlazor.DOM, Blazor.Clipboard, Blazor.Credentials, Blazor.Geolocation, Blazor.LocalStorage, Blazor.MediaDevices
dependents
ecosystemsnuget
total_downloads178.869
monthly_downloads
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

66Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0.6/22.5Distribución de commits — el principal contribuyente firma el 97% de los commits
8.1/13.5Amplitud de contribuyentes — 6 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 6 contributing companies or organizations
Datos de entrada utilizados
bus_factor1
contributors_sampled6
top_contributor_share0,974
Cómo se puntúa
46.8/46.8Resolución de issues — 100% de issues cerradas
34.5/38.3Aceptación de PR — 28/31 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/28 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs28
open_issues0
closed_issues32
issue_closed_ratio1
closed_unmerged_prs3
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
21.6/25Alcance del propietario — 1017 seguidores de IEvangelist
25/25Trayectoria — 336 repos públicos, cuenta de ~12 años
Datos de entrada utilizados
followers1017
owner_typeUser
is_verified
owner_loginIEvangelist
public_repos336
account_age_days4445
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 6 paquete(s) en nuget
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 19 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesBlazor.DOM, Blazor.Clipboard, Blazor.Credentials, Blazor.Geolocation, Blazor.LocalStorage, Blazor.MediaDevices
ecosystemsnuget
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

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

71Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 4 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
6.4/6.4.editorconfig
14/20OpenSSF Scorecard: CI-Tests — 3 out of 4 merged PRs checked by a CI test -- score normalized to 7
Datos de entrada utilizados
has_ci
has_tests
has_editorconfig
has_linter_configno
has_precommit_configno
Cómo se puntúa
30/30README
0/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://ievangelist.github.io/blazorators/
10/10Descripción del repositorio
10/10Topics — 7 topics
10/10Wiki
Datos de entrada utilizados
topicsblazor, blazor-webassembly, javascript, typescript, javascript-interop, source-generators, hacktoberfest
has_wiki
homepagehttps://ievangelist.github.io/blazorators/
has_readme
has_docs_dirno
has_description

Seguridad

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

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

Preparación para IA

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

60Moderado · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 92 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,92
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
12.6/18Arranque con un solo comando — samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — tools/Blazor.DOM.TypeScriptModel/tsconfig.json
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 98 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
1/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
Datos de entrada utilizados
has_nixno
has_tests
lockfilespackage-lock.json
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configstools/Blazor.DOM.TypeScriptModel/tsconfig.json
agent_commit_share0,98
toolchain_manifestssamples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj, src/Blazor.BrowserCoordination/Blazor.BrowserCoordination.csproj, src/Blazor.Clipboard.WebAssembly/Blazor.Clipboard.WebAssembly.csproj, src/Blazor.Clipboard/Blazor.Clipboard.csproj, src/Blazor.Credentials.WebAssembly/Blazor.Credentials.WebAssembly.csproj, src/Blazor.Credentials/Blazor.Credentials.csproj, src/Blazor.DOM.Generation/Blazor.DOM.Generation.csproj, src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj, src/Blazor.DOM/Blazor.DOM.csproj, src/Blazor.FileSystemAccess.WebAssembly/Blazor.FileSystemAccess.WebAssembly.csproj, src/Blazor.FileSystemAccess/Blazor.FileSystemAccess.csproj, src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj, src/Blazor.Geolocation/Blazor.Geolocation.csproj, src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj, src/Blazor.LocalStorage/Blazor.LocalStorage.csproj, src/Blazor.MediaDevices.WebAssembly/Blazor.MediaDevices.WebAssembly.csproj, src/Blazor.MediaDevices/Blazor.MediaDevices.csproj, src/Blazor.Notifications.WebAssembly/Blazor.Notifications.WebAssembly.csproj, src/Blazor.Notifications/Blazor.Notifications.csproj, src/Blazor.OfflineStorage.WebAssembly/Blazor.OfflineStorage.WebAssembly.csproj, src/Blazor.OfflineStorage/Blazor.OfflineStorage.csproj, src/Blazor.Performance.WebAssembly/Blazor.Performance.WebAssembly.csproj, src/Blazor.Performance/Blazor.Performance.csproj, src/Blazor.Permissions.WebAssembly/Blazor.Permissions.WebAssembly.csproj, src/Blazor.Permissions/Blazor.Permissions.csproj, src/Blazor.Screen.WebAssembly/Blazor.Screen.WebAssembly.csproj, src/Blazor.Screen/Blazor.Screen.csproj, src/Blazor.Serialization/Blazor.Serialization.csproj, src/Blazor.SessionStorage.WebAssembly/Blazor.SessionStorage.WebAssembly.csproj, src/Blazor.SessionStorage/Blazor.SessionStorage.csproj, src/Blazor.Share.WebAssembly/Blazor.Share.WebAssembly.csproj, src/Blazor.Share/Blazor.Share.csproj, src/Blazor.SourceGenerators/Blazor.SourceGenerators.csproj, src/Blazor.SpeechRecognition.WebAssembly/Blazor.SpeechRecognition.WebAssembly.csproj, src/Blazor.SpeechRecognition/Blazor.SpeechRecognition.csproj, src/Blazor.SpeechSynthesis.WebAssembly/Blazor.SpeechSynthesis.WebAssembly.csproj, src/Blazor.SpeechSynthesis/Blazor.SpeechSynthesis.csproj, src/Blazor.StorageManagement.WebAssembly/Blazor.StorageManagement.WebAssembly.csproj, src/Blazor.StorageManagement/Blazor.StorageManagement.csproj, src/Blazor.WakeLock.WebAssembly/Blazor.WakeLock.WebAssembly.csproj, src/Blazor.WakeLock/Blazor.WakeLock.csproj, src/Blazor.WebCrypto.WebAssembly/Blazor.WebCrypto.WebAssembly.csproj, src/Blazor.WebCrypto/Blazor.WebCrypto.csproj, tests/Blazor.BrowserCoordination.Tests/Blazor.BrowserCoordination.Tests.csproj, tests/Blazor.Clipboard.Tests/Blazor.Clipboard.Tests.csproj, tests/Blazor.Credentials.Tests/Blazor.Credentials.Tests.csproj, tests/Blazor.DOM.Accessors.CompilationTests/Blazor.DOM.Accessors.CompilationTests.csproj, tests/Blazor.DOM.AdvancedTypes.CompilationTests/Blazor.DOM.AdvancedTypes.CompilationTests.csproj, tests/Blazor.DOM.CSharpGenerator.Tests/Blazor.DOM.CSharpGenerator.Tests.csproj, tests/Blazor.DOM.Generic.CompilationTests/Blazor.DOM.Generic.CompilationTests.csproj, tests/Blazor.DOM.GlobalNamespace.CompilationTests/Blazor.DOM.GlobalNamespace.CompilationTests.csproj, tests/Blazor.DOM.NonEventDeferrals.CompilationTests/Blazor.DOM.NonEventDeferrals.CompilationTests.csproj, tests/Blazor.DOM.ProfileRuntime/Blazor.DOM.ProfileRuntime.csproj, tests/Blazor.DOM.ResolvedFailures.CompilationTests/Blazor.DOM.ResolvedFailures.CompilationTests.csproj, tests/Blazor.DOM.Server.CompilationTests/Blazor.DOM.Server.CompilationTests.csproj, tests/Blazor.DOM.SupplementalBrowserApis.CompilationTests/Blazor.DOM.SupplementalBrowserApis.CompilationTests.csproj, tests/Blazor.DOM.Tests/Blazor.DOM.Tests.csproj, tests/Blazor.DOM.TypedEvents.CompilationTests/Blazor.DOM.TypedEvents.CompilationTests.csproj, tests/Blazor.DOM.TypedUnions.CompilationTests/Blazor.DOM.TypedUnions.CompilationTests.csproj, tests/Blazor.DOM.WakeLock.CompilationTests/Blazor.DOM.WakeLock.CompilationTests.csproj, tests/Blazor.DOM.WebAssembly.CompilationTests/Blazor.DOM.WebAssembly.CompilationTests.csproj, tests/Blazor.ExampleConsumer.EndToEndTests/Blazor.ExampleConsumer.EndToEndTests.csproj, tests/Blazor.FileSystemAccess.Tests/Blazor.FileSystemAccess.Tests.csproj, tests/Blazor.OfflineStorage.Tests/Blazor.OfflineStorage.Tests.csproj, tests/Blazor.Performance.Tests/Blazor.Performance.Tests.csproj, tests/Blazor.Screen.Tests/Blazor.Screen.Tests.csproj, tests/Blazor.Share.Tests/Blazor.Share.Tests.csproj, tests/Blazor.SourceGenerators.Tests/Blazor.SourceGenerators.Tests.csproj, tests/Blazor.StorageManagement.Tests/Blazor.StorageManagement.Tests.csproj, tests/Blazor.WakeLock.Tests/Blazor.WakeLock.Tests.csproj, tests/Blazor.WebCrypto.Tests/Blazor.WebCrypto.Tests.csproj, tools/Blazor.DOM.CSharpGenerator/Blazor.DOM.CSharpGenerator.csproj
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — C# (tipado estático)
54.1/55Tamaños de archivo manejables — 7/429 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageC#
largest_source_bytes816.786
source_files_sampled429
oversized_source_files7
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — samples
Datos de entrada utilizados
example_dirssamples
has_mcp_signalno
api_schema_files

Datos clave

392estrellas de GitHub
6contribuidores
124commits en los últimos 12 meses
0días desde el último push
43versiones publicadas
1factor bus
0issues abiertas
ecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • nuget package 'Blazor.Notifications' points at a different repository (https://github.com/vertonghenb/Blazor.Notifications); excluded from ecosystem scoring
  • Could not fetch nuget package 'Blazor.DOM.WebAssembly' from its registry

Más detalle

Historial de estrellas y forks 0 ★ / 32 ⇿
0Estrellas
32Forks
41Versiones

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

01325383232021-102023-072025-05
Mayor 5Menor 5Parche 30

Cada punto abarca 4 días.

OpenSSF Scorecard 5.4 / 10
5.4agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-24 19:01 UTC

10Binary-Artifactsno binaries found in the repo
n/dBranch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
7CI-Tests3 out of 4 merged PRs checked by a CI test -- score normalized to 7
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/28 approved changesets -- score normalized to 0
10Contributorsproject has 6 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
1Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 1
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
8Vulnerabilities2 existing vulnerabilities detected
Dependencias directas 25
RegistroPaqueteRestricción de versiónManifiesto
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj
NuGetMinVersrc/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj
NuGetMicrosoft.AspNetCore.Components.WebAssemblysrc/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj
NuGetMicrosoft.Extensions.DependencyInjectionsrc/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.DOM/Blazor.DOM.csproj
NuGetMinVersrc/Blazor.DOM/Blazor.DOM.csproj
NuGetMicrosoft.AspNetCore.Components.Websrc/Blazor.DOM/Blazor.DOM.csproj
NuGetMicrosoft.Extensions.DependencyInjectionsrc/Blazor.DOM/Blazor.DOM.csproj
NuGetMicrosoft.JSInteropsrc/Blazor.DOM/Blazor.DOM.csproj
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj
NuGetMinVersrc/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj
NuGetMicrosoft.AspNetCore.Components.Websrc/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.Geolocation/Blazor.Geolocation.csproj
NuGetMinVersrc/Blazor.Geolocation/Blazor.Geolocation.csproj
NuGetMicrosoft.AspNetCore.Components.Websrc/Blazor.Geolocation/Blazor.Geolocation.csproj
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj
NuGetMinVersrc/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj
NuGetMicrosoft.Extensions.DependencyInjectionsrc/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj
NuGetMicrosoft.Extensions.Primitivessrc/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj
NuGetMicrosoft.JSInteropsrc/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj
NuGetMicrosoft.SourceLink.GitHubsrc/Blazor.LocalStorage/Blazor.LocalStorage.csproj
NuGetMinVersrc/Blazor.LocalStorage/Blazor.LocalStorage.csproj
NuGetMicrosoft.Extensions.DependencyInjectionsrc/Blazor.LocalStorage/Blazor.LocalStorage.csproj
NuGetMicrosoft.Extensions.Primitivessrc/Blazor.LocalStorage/Blazor.LocalStorage.csproj
NuGetMicrosoft.JSInteropsrc/Blazor.LocalStorage/Blazor.LocalStorage.csproj
Todas las dependencias 38

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

RegistroPaqueteVersiónRelación
NuGetMicrosoft.AspNetCore.Components.Webdirecta
NuGetMicrosoft.AspNetCore.Components.WebAssemblydirecta
NuGetMicrosoft.Extensions.DependencyInjectiondirecta
NuGetMicrosoft.Extensions.Primitivesdirecta
NuGetMicrosoft.JSInteropdirecta
NuGetMicrosoft.SourceLink.GitHubdirecta
NuGetMinVerdirecta
npm@pagefind/darwin-arm641.5.0indirecta
npm@pagefind/darwin-x641.5.0indirecta
npm@pagefind/freebsd-x641.5.0indirecta
npm@pagefind/linux-arm641.5.0indirecta
npm@pagefind/linux-x641.5.0indirecta
npm@pagefind/windows-arm641.5.0indirecta
npm@pagefind/windows-x641.5.0indirecta
npm@types/node26.1.1indirecta
npm@webgpu/types0.1.71indirecta
npm@webref/idl3.81.3indirecta
npmajv8.17.1indirecta
npmfast-deep-equal3.1.3indirecta
npmfast-uri3.1.3indirecta
npmjson-schema-traverse1.0.0indirecta
npmpagefind1.5.0indirecta
npmrequire-from-string2.0.2indirecta
npmtypescript5.9.3indirecta
npmundici-types8.3.0indirecta
npmwebidl224.5.0indirecta
NuGetBasic.Reference.Assembliesindirecta
NuGetcoverlet.collectorindirecta
NuGetDeque.AxeCore.Playwrightindirecta
NuGetHumanizer.Coreindirecta
NuGetMicrosoft.AspNetCore.Components.WebAssembly.DevServerindirecta
NuGetMicrosoft.CodeAnalysis.Analyzersindirecta
NuGetMicrosoft.CodeAnalysis.CSharpindirecta
NuGetMicrosoft.NET.Test.Sdkindirecta
NuGetMicrosoft.Playwrightindirecta
NuGetSystem.Reactive.Linqindirecta
NuGetxunitindirecta
NuGetxunit.runner.visualstudioindirecta
Avisos de dependencias 2

Este repositorio no publica ningún paquete que el índice resuelva, así que se evaluó su propio grafo de dependencias — 19 paquetes, que incluyen también fijaciones de desarrollo y prueba que nunca se distribuyen: 2 tienen avisos conocidos, de los cuales 0 son directas. 19 no pudieron evaluarse: sin versión resuelta, ecosistema no admitido, o fuera de la lista de paquetes informada.

PaqueteVersiónRelaciónGravedadAvisosCorregido en
fast-uri3.1.3indirectaalta14.1.1
ajv8.17.1indirectamoderada18.18.0

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "blazor",
        "blazor-webassembly",
        "javascript",
        "typescript",
        "javascript-interop",
        "source-generators",
        "hacktoberfest"
      ],
      "is_fork": false,
      "size_kb": 211371,
      "has_wiki": true,
      "homepage": "https://ievangelist.github.io/blazorators/",
      "languages": {
        "C#": 2701130,
        "JavaScript": 45237,
        "TypeScript": 192143
      },
      "pushed_at": "2026-07-24T18:56:46Z",
      "created_at": "2021-10-12T15:02:44Z",
      "owner_type": "User",
      "updated_at": "2026-07-24T18:56:50Z",
      "description": "This project converts TypeScript type declarations into C# representations, and use C# source generators to expose automatic JavaScript interop functionality.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "C#",
      "significant_languages": [
        "C#"
      ]
    },
    "owner": {
      "blog": "https://davidpine.dev/",
      "name": "David Pine",
      "type": "User",
      "login": "IEvangelist",
      "company": "@microsoft",
      "location": "Pewaukee, WI",
      "followers": 1017,
      "avatar_url": "https://avatars.githubusercontent.com/u/7679720?v=4",
      "created_at": "2014-05-23T11:18:56Z",
      "is_verified": null,
      "public_repos": 336,
      "account_age_days": 4445
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "10.1.0",
          "kind": "minor",
          "published_at": "2026-07-24T18:48:52Z"
        },
        {
          "tag": "10.0.0",
          "kind": "major",
          "published_at": "2026-05-14T20:49:04Z"
        },
        {
          "tag": "9.0.2",
          "kind": "patch",
          "published_at": "2025-04-29T04:53:45Z"
        },
        {
          "tag": "9.0.1",
          "kind": "patch",
          "published_at": "2024-12-01T02:39:23Z"
        },
        {
          "tag": "9.0.0",
          "kind": "major",
          "published_at": "2024-11-22T15:21:41Z"
        },
        {
          "tag": "8.0.0",
          "kind": "major",
          "published_at": "2023-11-17T19:22:21Z"
        },
        {
          "tag": "8.0.0-rc.2.23480.2",
          "kind": "prerelease",
          "published_at": "2023-10-13T20:44:16Z"
        },
        {
          "tag": "7.0.3",
          "kind": "patch",
          "published_at": "2023-02-15T19:42:16Z"
        },
        {
          "tag": "7.0.2",
          "kind": "patch",
          "published_at": "2023-02-07T20:59:21Z"
        },
        {
          "tag": "7.0.1",
          "kind": "patch",
          "published_at": "2023-01-24T04:05:45Z"
        },
        {
          "tag": "7.0.0",
          "kind": "major",
          "published_at": "2023-01-11T00:35:08Z"
        },
        {
          "tag": "2.0.11",
          "kind": "patch",
          "published_at": "2022-10-10T14:57:16Z"
        },
        {
          "tag": "2.0.10",
          "kind": "patch",
          "published_at": "2022-05-19T13:50:01Z"
        },
        {
          "tag": "2.0.9",
          "kind": "patch",
          "published_at": "2022-04-18T16:13:40Z"
        },
        {
          "tag": "2.0.8",
          "kind": "patch",
          "published_at": "2022-04-14T20:29:27Z"
        },
        {
          "tag": "2.0.7",
          "kind": "patch",
          "published_at": "2022-04-14T20:16:04Z"
        },
        {
          "tag": "2.0.6",
          "kind": "patch",
          "published_at": "2022-04-07T16:16:31Z"
        },
        {
          "tag": "2.0.5",
          "kind": "patch",
          "published_at": "2022-04-05T23:51:23Z"
        },
        {
          "tag": "2.0.4",
          "kind": "patch",
          "published_at": "2022-04-05T23:47:44Z"
        },
        {
          "tag": "2.0.3",
          "kind": "patch",
          "published_at": "2022-04-05T23:40:49Z"
        },
        {
          "tag": "2.0.2",
          "kind": "patch",
          "published_at": "2022-04-04T18:09:07Z"
        },
        {
          "tag": "2.0.1",
          "kind": "patch",
          "published_at": "2022-04-04T17:48:05Z"
        },
        {
          "tag": "2.0.0",
          "kind": "major",
          "published_at": "2022-04-04T17:26:16Z"
        },
        {
          "tag": "1.5.0",
          "kind": "minor",
          "published_at": "2022-03-29T15:21:33Z"
        },
        {
          "tag": "1.4.5",
          "kind": "patch",
          "published_at": "2022-03-26T14:50:10Z"
        },
        {
          "tag": "1.4.4",
          "kind": "patch",
          "published_at": "2022-03-26T01:38:06Z"
        },
        {
          "tag": "1.4.3",
          "kind": "patch",
          "published_at": "2022-03-25T02:28:12Z"
        },
        {
          "tag": "1.4.2",
          "kind": "patch",
          "published_at": "2022-03-23T15:48:27Z"
        },
        {
          "tag": "1.4.1",
          "kind": "patch",
          "published_at": "2022-03-23T15:40:36Z"
        },
        {
          "tag": "1.4.0",
          "kind": "minor",
          "published_at": "2022-03-22T14:31:38Z"
        },
        {
          "tag": "1.3.3",
          "kind": "patch",
          "published_at": "2022-03-18T03:39:04Z"
        },
        {
          "tag": "1.3.2",
          "kind": "patch",
          "published_at": "2022-03-18T03:34:15Z"
        },
        {
          "tag": "1.3.1",
          "kind": "patch",
          "published_at": "2022-03-16T12:44:06Z"
        },
        {
          "tag": "1.3.0",
          "kind": "minor",
          "published_at": "2022-03-16T04:01:16Z"
        },
        {
          "tag": "1.2.0",
          "kind": "minor",
          "published_at": "2022-03-13T21:20:48Z"
        },
        {
          "tag": "1.1.1",
          "kind": "patch",
          "published_at": "2022-03-08T02:44:22Z"
        },
        {
          "tag": "1.1.0",
          "kind": "minor",
          "published_at": "2022-03-05T20:25:13Z"
        },
        {
          "tag": "1.0.5",
          "kind": "patch",
          "published_at": "2022-03-04T21:34:08Z"
        },
        {
          "tag": "1.0.4",
          "kind": "patch",
          "published_at": "2022-03-03T14:33:59Z"
        },
        {
          "tag": "1.0.3",
          "kind": "patch",
          "published_at": "2022-02-24T02:18:39Z"
        },
        {
          "tag": "1.0.2",
          "kind": "patch",
          "published_at": "2022-02-22T21:16:36Z"
        },
        {
          "tag": "1.0.1",
          "kind": "patch",
          "published_at": "2022-02-22T05:06:56Z"
        },
        {
          "tag": "1.0.0",
          "kind": "major",
          "published_at": "2022-02-22T04:35:23Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "abe9091425dc6bd6126011894642fc370bc2876d",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 23daf7e5-e07e-4c52-a278-a7bfbffc0ffb",
          "is_bot": false,
          "headline": "Resume trusted NuGet publishing",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-24T18:56:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e98ca363727d0822bbd459813a4735a7c7b8886c",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 23daf7e5-e07e-4c52-a278-a7bfbffc0ffb",
          "is_bot": false,
          "headline": "Add rich file previews and site search",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-24T18:36:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "88e901f4b12904351e049bf63e8101c6f1534b42",
          "body": "* Build semantic DOM model\n\nAdd the pinned TypeScript and Web IDL extraction pipeline, strict schemas, deterministic JSONL artifacts, exact reconciliation accounting, provenance, and regression coverage for the Window DOM profile.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.\n[…]\n: 92c2c670-2273-4668-8c4a-17d93d697fbe\nCopilot-Session: cd6af8e4-1463-4f41-83cd-ef1f047d6ae6\nCopilot-Session: 317df431-f8e4-4b29-ae31-1f05ed91ba9d\nCopilot-Session: b1e23c54-4ce6-4df2-a413-08cfa975fab2",
          "is_bot": false,
          "headline": "Generate exhaustive Blazor DOM interop packages (#73)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-23T20:57:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "eb9ca1efea44740481e29d4a17657d0b43a121a9",
          "body": "Smooth demo background transitions",
          "is_bot": false,
          "headline": "Merge pull request #72 from IEvangelist/ievangelist-neon-tattoo-restyle",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-20T02:19:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "139c4fcdba44674b7954cdc70b7715585d6aa0a9",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 6df4716c-f65a-42de-9816-7d5c9b8ebe7c",
          "is_bot": false,
          "headline": "Smooth demo background transitions",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-20T02:19:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "723b1a3eff8cbeac9946c746f6a2646f00504db8",
          "body": "Restyle demo with neon tattoo theme",
          "is_bot": false,
          "headline": "Merge pull request #71 from IEvangelist/ievangelist-neon-tattoo-restyle",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-19T15:58:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "395f330d6c4526b8b3e382b59ae6688d125af263",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 6df4716c-f65a-42de-9816-7d5c9b8ebe7c",
          "is_bot": false,
          "headline": "Restyle demo with neon tattoo theme",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-19T15:57:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a9829e4f79395e45345aa1ff57e23cf14a5688d4",
          "body": "* Fix resilient docs startup and CI\n\nRetry transient Pages boot-resource failures without weakening SRI, respect reduced-motion preferences, and align the browser regressions with the typewriter implementation.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\n\nCopilot-Sessio\n[…]\nnsure sample-site and workflow changes trigger pull-request validation.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\n\nCopilot-Session: cad5f07b-0de7-4065-8dbb-8bc3166fecb0",
          "is_bot": false,
          "headline": "Fix resilient docs startup and CI (#70)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-17T18:41:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9f639a55a8542ab6c2394410c78dd85cb9b03e4c",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Update GitHub logo mark",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-14T11:40:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1f6f0ca129461cb72175f16a8550920ada9dbc63",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Add typewriter suffix spacing",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:52:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7e0df5bfa48db352c841c59dc391a894d199689d",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Use typewriter hero phrase transition",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:47:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9312510f0f9f0e3d8ac385361c64f4af131c961b",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Render hero phrase suffix",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:27:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a23cb72abd3b3bfd6a6a40f1415f87ff5f665930",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Animate full hero phrase",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:24:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "567e26d29272bdd659e96f0e3db12e6765a1e84e",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fix delayed hero rotator visibility",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:14:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "245f07b5650712fb56f25fc6495991ab94eab0fd",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Make hero rotator swap discretely",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:10:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "43df647f97751c820d62216d26a68a2938f30140",
          "body": "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fix hero word rotator overlay",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-07-11T18:06:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5ec733ba29ecd4f4781062dc64e158913b7eba00",
          "body": "The W3C watchPosition contract only fires the callback when the browser\ndetects meaningful device motion, so stationary desktops never re-fire\nafter the first fix. This adds an opt-in polling cadence (5/15/30/60s)\nand a manual \"Refresh now\" trigger alongside the live watch mode.\n\nImplementation note\n[…]\node.\n- New E2E test asserts the ARIA contract, aria-pressed toggling, and\n  status-badge transitions between WATCHING and POLLING.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Add refresh-interval toggle to /track demo",
          "author_name": "David Pine",
          "author_login": null,
          "committed_at": "2026-06-02T04:48:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5ee6f22d48804838001e6473d560b49cbcd945a3",
          "body": "Live axe sweep across all 8 routes flagged two serious color-contrast violations on /geolocation, /sandbox, /track:\n\n- .codeblock.is-error .codeblock-filename rendered #EF4343 on a near-white tint (~3.5:1, fails AA 4.5:1 for normal text).\n\n- .hljs-string rendered #1A9948 on the same tinted body bg (\n[…]\n routes x light+dark (16 page-states). Local E2E still 21/21 (one Firefox playwright-protocol teardown flake re-passed on re-run).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Bump destructive/warning/hljs colors to meet WCAG AA contrast",
          "author_name": "David Pine",
          "author_login": null,
          "committed_at": "2026-06-02T04:17:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "59963957881a78b1609e25ffffc28368c2989234",
          "body": "The hero rotating word (e.g. 'promised') was rendering visibly below the baseline of Browser APIs, and in C#.. The .word-rotator container used display: inline-grid with \u000bertical-align: -0.22em, an explicit 1.46em height, and inline-flex children centered with min-height: 100%. Because an inline-gri\n[…]\nline probe matches the surrounding text baseline exactly (delta 0.00px) at desktop and mobile, and local E2E (21/21) still passes.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Align hero word rotator to surrounding text baseline",
          "author_name": "David Pine",
          "author_login": null,
          "committed_at": "2026-06-02T03:55:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e2ccc96c540d5e6c9c9be99f1ab0181a7f6af044",
          "body": "Add a [JSAutoEnum] attribute + generator pipeline branch that anchors\non a C# interface and emits a sibling C# enum next to it, plus a\nper-enum JsonConverter<TEnum> that maps each member to its exact raw\nTypeScript string (and back) without relying on JsonStringEnumConverter's\nname-based heuristics.\n[…]\nespaces,\n  duplicate-identity dedup, multi-source resolution, and end-to-end\n  \"the generated enum source compiles cleanly\" check.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Project TypeScript string-literal unions as C# enums (C2)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "35b0e03739005e49bb21c37f21a0e50422bb41db",
          "body": "Adds a single, deterministic-per-compilation\n`BlazoratorsServiceCollectionExtensions.AddBlazoratorsAll(this IServiceCollection)`\nhelper that chains every per-service `Add{ImplementationName}Services()`\nthe generator emitted. Consumers can now write one line to register\nthe full set:\n\n    builder.Ser\n[…]\ntor), and syntactic\nvalidity (the generated tree parses cleanly with two chained\ninvocations).\n\nFull suite: 560/560 (was 554/554).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit `AddBlazoratorsAll()` aggregator DI extension (G4)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e02ac8849bf9e76a06e52143824373b873298e86",
          "body": "Adds a zero-ceremony, assembly-targeted entry point for service\nprojection. Consumers can now write:\n\n  [assembly: JSAutoService(\"Geolocation\")]\n  [assembly: JSAutoService(\"Clipboard\", \"Storage\")]\n\nand the generator emits the full `I{Name}Service` partial interface,\n`{Name}Service` implementation, a\n[…]\nerride path, BR0006 surface\nwhen the inferred TS type is unknown, and the collision-dedup case.\nFull suite: 554/554 (was 545/545).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Project services from `[assembly: JSAutoService(...)]` (G2)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dea9491e3c76f9af075ffd312405012623d796c9",
          "body": "Consumers can now opt into a minimal attribute form:\n\n    [JSAutoInterop]\n    public partial interface IGeolocationService { }\n\nis equivalent to\n\n    [JSAutoInterop(\n        TypeName = \"Geolocation\",\n        Implementation = \"window.geolocation\")]\n    public partial interface IGeolocationService { }\n[…]\nurface. The diagnostic descriptor\n    is retained for defensive use.\n\nFull suite: 545 / 545 green (was 513 pre-G1, +32 new tests).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Infer TypeName and Implementation on `[JSAutoInterop]` (G1)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "67885640fc731a856f07995695c5416e8cef8a1d",
          "body": "TS intersection aliases (`type X = A & B`) merge member sets at the\ntype-system level. The closest C# projection would be a synthesized\nDTO that carries members from both sides, which requires resolving\neach arm independently (interface vs. alias vs. generic invocation)\nplus a dedup pass -- a much l\n[…]\nhis slice -- they include `typeof` and\nparens that need a wider parser change. Existing behavior on those\nproperties is unchanged.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fall back unsupported intersection aliases to `object` (B7)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9e9813666e0fe929e6ebb73c96cec6127b3628d6",
          "body": "The `Record<K, V>` -> `Dictionary<TKey, TValue>` translation in both\n`CSharpProperty.MappedTypeName` and `CSharpType.ToParameterString`\nrouted K and V through a single `TypeMap.PrimitiveTypes[...]` lookup.\nThat worked for the DOM corpus (all hits are\n`Record<string, number>`, `Record<string, string>\n[…]\negression)\n- Record<string, Element>             -> Dictionary<string, Element> (regression)\n\nSuite: 506 / 506 pass (500 + 6 new).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Recursively map nested generic args in Record (B11)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "64d57a1e85b9499b6076dd6e6ea75c77d5d95286",
          "body": "Before this change, TypeScript alias declarations like\n\n  type BodyInit = ReadableStream | XMLHttpRequestBodyInit;\n  type RequestInfo = Request | string;\n  type HeadersInit = [string, string][] | Record<string, string> | Headers;\n\nleaked the raw alias identifier (`BodyInit`, `RequestInfo`,\n`HeadersI\n[…]\nuble  (regression)\n- HTMLElement (unknown alias / interface ref) -> HTMLElement (regression)\n\nSuite: 500 / 500 pass (493 + 7 new).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fall back unsupported union aliases to `object` (B8)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "67484a1163aed0054ddf3d5ab8e061108bb57951",
          "body": "Phase B4. A handful of `lib.dom.d.ts` interfaces -- notably `Document`\nand `Window` -- declare properties using the ES2015 accessor syntax:\n\n    get location(): Location;\n    set location(href: string | Location);\n\nBoth lines were silently dropped today. The getter falls through\n`IsMethod` (regex `\\\n[…]\non`, and a regression guard that the accessor must not\n  produce a `get`/`set` method.\n\nFull suite: 493/493 passing (488 + 5 new).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Recover ES2015 getter-accessor properties (e.g. Document.location)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "41309abacbb71b8460a222c2212e2bb2e8f9bad4",
          "body": "Add a pure-detection helper that recognizes TypeScript string-literal\nunion aliases (e.g. `type DocumentReadyState = \"complete\" |\n\"interactive\" | \"loading\";`) and converts each raw value into a valid\nC# enum member identifier. This is the foundation for opt-in C# enum\nprojection in a future slice; n\n[…]\nus\nspot checks (`DocumentReadyState`, `PermissionName`, `InsertPosition`)\nplus a `BodyInit` negative. Full suite: 488/488 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Detect string-literal union aliases (B3 slice 1, no emission)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8471b16e9f393b257569ffc23ac49915b77b2753",
          "body": "`InterfaceTypeNameRegex` greedy-matches non-whitespace, so a TypeScript\nheader like `interface CustomEventInit<T = any> extends EventInit { ... }`\nused to surface `TypeName = \"CustomEventInit<T\"` -- breaking both\n`TypeDeclarationReader._typeDeclarationMap` lookups (the bare name\n`\"CustomEventInit\"` \n[…]\nEventInit`\n  keeps `Map<string, number>` whole as the primary base and still\n  merges `EventInit`'s members.\n\nFull suite: 438/438.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Normalize generic interface names + depth-aware extends split",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b2e7eaf4dc4ca693bb67b74562fc7722a748fc7e",
          "body": "`TypeDeclarationParser.Interfaces.ToObject` only captured the first\nbase via the single-token `ExtendsTypeNameRegex`, and that capture\ngreedily included the trailing comma — so `interface DocumentFragment\nextends Node, NonElementParentNode, ParentNode { ... }` produced\n`ExtendsTypeName = \"Node,\"` an\n[…]\nd\nmembers from `Node` + `NonElementParentNode` + `ParentNode` present\nplus the overriding `getElementById`).\n\nFull suite: 436/436.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Merge multi-extends base members in interface parser",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1a8aff22dbd6aee884c075cc0a15406c61960f6e",
          "body": "This is the safety net the rest of the universal-coverage work hangs\noff of. Three new xUnit tests in CorpusCoverageTests drive every\ninterface (1062) and type alias (222) in the bundled lib.dom.d.ts\nthrough the parser, assert that nothing throws, and write a coverage\nreport under <BaseDirectory>/co\n[…]\n thin\nwrapper over the existing dictionaries with no behavior change.\n\nAll 435 tests pass (the prior 432 plus three corpus tests).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Add Phase A corpus coverage harness + parser cycle guard & memoization",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-06-02T03:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "33c021584daa16a5b65bf935dd526ea3dea5000b",
          "body": "Allow the deployed GitHub Pages route canonicalization to add a trailing slash while still asserting the skip link preserves the route and focuses main content.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Handle Pages route slashes in skip-link test",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-30T04:41:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7ab26878cda6b9be29ce027a63bb05faed684978",
          "body": "Add comprehensive Playwright end-to-end coverage for every sample route, tighten WCAG-oriented contrast and semantics, improve keyboard/focus behavior, and fix layout polish for the hero rotator and track page panels.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Polish sample site accessibility and UX",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-30T04:19:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3eaf7cfbb8d2087d9718839d5566c2b124fd47ce",
          "body": "Iterated through every demo route capturing screenshots and fixed the\nissues that stood out at typical desktop and mobile widths.\n\nMainLayout\n- Hamburger now toggles the sidebar on every viewport. Single\n  `.nav-toggled` class on `.app` collapses the desktop sidebar (grid\n  column animates to 0 + si\n[…]\nso we only split when there's\n  real room; below that, the animation sits at full width on top with\n  the code preview underneath.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Polish UX after audit: hamburger, bubbles, timeline, footer",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-17T00:31:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a1d7831a6bf612413ba6dd91a341600c5fbc42c6",
          "body": "…ento copy\n\n* Live event timeline on /track: map + timeline side-by-side with prepended\n  entries (max 25, dedup'd), pulsing newest dot, splat-in animation,\n  HH:mm:ss.fff timestamps, accuracy badges, and lat/lng/speed/heading\n  stats; collapses to single column on mobile and respects\n  prefers-redu\n[…]\nth\n  natural chat-style transcripts (Hello, are you ready?, Listening live...,\n  Transcribe everything., Type-safe, cancellable.).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Add live event timeline to /track, richer audio waveform & polished b…",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T17:57:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "db3cb2eb38aa991970bf3911fb079a8ce590bf9e",
          "body": "Each demo card now hosts a self-contained CSS/SVG animation panel\nthat illustrates the API it represents:\n\n- Featured Local storage: split layout with an animated stack of mini\n  todo cards flying right into a pulsing 'localStorage' disk, beside\n  the existing inline code preview (flex-stretched to \n[…]\n on dashed rings\n\nAll animations honor prefers-reduced-motion, and cards subtly speed up\non hover to amplify the spotlight + glow.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Give every bento card its own inner micro-animation",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T17:02:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "882b34b4b93678bcf2a3737cf1dee74ba8a81e25",
          "body": "- Aurora-blob hero background with subtle grid overlay and slow drift\n- Cross-fading word rotator (type-safe / ergonomic / promised / generated)\n- Hero stats strip with gradient numerals and net8/9/10 multi-target chip\n- 12-col bento layout with featured 8x2 'Local storage, type-safe' card\n- Inline \n[…]\n icon rotate, shimmer on preview\n- Staggered rise-in entrance via [data-reveal] / .bento children\n- Honours prefers-reduced-motion\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Reimagine landing UX with bento grid + spotlight cards",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T11:28:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b3e576a90ad14872bc24c93d6586a236a1daddaf",
          "body": "The sample now targets net10.0 (via global.json \rollForward: latestFeature\npinning to 10.0.100). The workflow was still hard-coded to 9.0.x, which\nwould fail to restore/publish. Use global-json-file so the workflow\nalways tracks the project's SDK without further drift.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "ci: pin gh-pages deploy to project's .NET SDK via global.json",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T11:03:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "24fd57033dba35a22dc68a4b5f3ddef7fb7783ec",
          "body": "\u0007ria-pressed=@bool was rendering as \u0007ria-pressed=\"\" for true (Blazor\nemits bool attributes as boolean-style attributes), so the CSS selector\n[aria-pressed=\"true\"] never matched and no button looked active.\n\nBind a string ternary so the attribute is always literally \"true\" or\n\"false\". Also bump the a\n[…]\nund instead of --background (which is nearly\nidentical to --muted in dark mode) so the selection reads at a glance\nin both themes.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fix theme toggle active-state visibility",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T11:03:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bad4298b4cc67791e4b68e835ebac42bc427fa9a",
          "body": "Strips Bootstrap and the deprecated Open Iconic font from\n`samples/Blazor.ExampleConsumer`, replaces them with an Unlumen UI\ninspired design language built entirely in CSS + inline SVG. Adds a\nlight/dark theme system, swaps the expired Bing Maps integration for\nMapLibre GL JS over the free, OSS Open\n[…]\n-generator\n  parser keeps working on Windows checkouts (it parses\n  `Data/lib.dom.d.ts` via a regex that assumes LF line endings).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Modernize GH Pages demo UX with Unlumen-style design",
          "author_name": "IEvangelist",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T11:03:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ac0152c7de1d6d0ff867e872be4573dfeacc902b",
          "body": "A typed declaration like `getItem<T>(key: string): Promise<T | null>;`\nwent through three independent issues at once:\n\n1. `CSharpMethod.IsReturnTypeNullable` looked only at the outer\n   `RawReturnTypeName`. For `Promise<T | null>` that string ends\n   with `>`, not `| null`, so `HasNullClause` return\n[…]\npts into `[JSAutoGenericInterop]` against a Promise-\nreturning declaration.\n\n432 tests passing (up from 424; +8 regression cases).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Wrap generic Promise<T> returns in ValueTask under WebAssembly",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:56:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a5b4a317e8e7ce7b2da116ad8e6b8714c4e52e83",
          "body": "`string.Contains(string)` and `string.LastIndexOf(string)` lack\n`StringComparison` overloads on netstandard2.0 (the target framework\nfor analyzers and source generators). Both fall through to the\nculture-sensitive default implementation, which is the same Turkish-\nlocale class of bug that motivated \n[…]\nNo emit-behaviour change for the existing snapshots; defensive\nfollow-up to the broader culture-invariant pass. 424 tests passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Replace culture-sensitive Contains/LastIndexOf with ordinal lookups",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:50:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4053b6cae073e69cbbf87890a10f8e7aeb6188cb",
          "body": "`EmitActionComponentMethod` in `CSharpTopLevelObject.Implementation`\ncalls `arg.Substring(2)` unguarded to strip the synthetic `on`\nprefix added by `ToArgumentString` for callback parameters before\nlooking up the matching `[JSInvokable]` method (e.g. `onSuccess` ->\n`Success` -> `OnSuccess`). For non\n[…]\nng-ops pass).\n\nNo emit-behaviour change for the existing snapshots; defensive fix\nplus matching parity with the rest of the audit.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Harden Action-callback emit path against short parameter names",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:44:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "224304f64ef8a7634de920d0c3d0fcf77bd4ccd7",
          "body": "`CSharpObject.AppendHeader` hardcoded `namespace Microsoft.JSInterop;`\nfor every dependent type file (e.g. `PositionOptions.g.cs`,\n`PermissionDescriptor.g.cs`), but the generated interface and\nimplementation land in the consumer's containing namespace and\nreference those types unqualified. Any consu\n[…]\nia the default\nparameter.\n\nAdds `CustomNamespace_DependentTypes_Use_Consumer_Namespace` as\nregression coverage. 424 tests passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit dependent DTOs into the consumer's namespace",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:42:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f962d9d10695345acef207f5bb4aa4fc5a3fe8a0",
          "body": "The generated interface and implementation surfaces routinely emit\n`Action<...>` parameters for TS callback bindings (e.g.\n`Geolocation.GetCurrentPosition(Action<GeolocationPosition> ...)`).\nThe previous output relied on the consumer project having\n`<ImplicitUsings>enable</ImplicitUsings>` for `Syst\n[…]\nre\nself-contained regardless of the host project's settings. Snapshots\nregenerated for the six interface / implementation outputs.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Always emit `using System;` in generated interop sources",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:40:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a1a9d6e78ebf888c0139500d188ab4834a726cfc",
          "body": "A source generator runs in the host build process, which inherits the\nmachine's current culture. Two related families of operations were\ndefaulting to current-culture behavior:\n\n1. `char.ToUpper` / `char.ToLower` in `StringExtensions.{Capitalize,LowerCase}FirstLetter`\n   — these drive every type/met\n[…]\n silently misclassify nullable / readonly modifiers\nunder any locale where casing-sensitive prefix matching diverges\nfrom ordinal.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Use culture-invariant string ops in the source generator",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:37:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "44c842be3739ef5779115a075fb804f64eae5ffa",
          "body": "…ions\n\n`CSharpAction.ParameterDefinitions` is declared `List<CSharpType>?`\n(nullable, default `null`). The constructor in\n`TypeDeclarationParser.ToAction` initializes a `CSharpAction` with\njust the type name and only fills `ParameterDefinitions` via a `with`\nclone if the call-signature regex matches\n[…]\n (the\nparallel API on the same record) already had a `is null` guard, so\nthis just brings the dependency-graph walker into parity.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Harden `CSharpAction.AllDependentTypes` against null ParameterDefinit…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:35:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f597c98aa0591f4f97c1a90cef8a5be746064e1e",
          "body": "The generated `*ServiceCollectionExtensions.g.cs` always lives in\n`Microsoft.Extensions.DependencyInjection` so consumers can chain\n`services.Add*Services()` without an extra `using`. The interface and\nimplementation it references, however, are emitted into the\nconsumer's containing namespace (the n\n[…]\nss of consumer\nnamespace. Adds an inline assertion test\n(`CustomNamespace_DI_Extension_Adds_Consumer_Using`) for the new\nbehavior.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit consumer `using` in generated DI extension class",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:34:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bb7eda2eeee8ee61aa40c133bdf600580f406c83",
          "body": "The emitted `JSAutoInteropAttribute` / `JSAutoGenericInteropAttribute`\ndocs claimed the attribute is placed on a `public static partial`\nextension-method class. In reality both attributes have\n`[AttributeUsage(AttributeTargets.Interface)]` and every consumer in\nthe repo places them on a `public part\n[…]\nat `RegisterPostInitial-\nizationOutput` time, so the change ships to every consumer the next\ntime they build against the analyzer.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Correct XML doc examples on emitted interop attributes",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:31:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e257cbcfac1f46a27b2b71a3b34db75de78265c0",
          "body": "Internal local in `PropertyBuilderDetails.Create` was spelled\n`javaScriptIndentifier` (missing the first `i` in \"Identifier\"),\nwhich sat next to the correctly-spelled record property\n`FullyQualifiedJavaScriptIdentifier`. Internal-only rename, no\nbehavior change.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Fix `javaScriptIndentifier` typo in `PropertyBuilderDetails`",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:27:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "674ca6713ad84645ed44ae52fbc9e8300946dc47",
          "body": "The root README's \"WebAssembly libraries\" and \"Server libraries\"\ntables -- and the analyzer package README's \"consumed by\" list --\nwere missing entries for `Blazor.Permissions.WebAssembly` and the\n`Blazor.SpeechRecognition`/`Blazor.SpeechRecognition.WebAssembly`\npair, even though those projects exist in the solution and ship\nmatching NuGet packages. Add the missing rows so the documentation\nmatches the actual shipping surface.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Update README package tables to include all shipping libraries",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:26:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "145049bb1a7584e0631ca7c9c3efbbb64e330ead",
          "body": "`CSharpPropertyExtensions.GetPropertyTypes` drives the property\nshape emitted into the top-level generated interface and\nimplementation classes. It already mapped TS `T[]` / `Array<T>` /\n`ReadonlyArray<T>` to a C# array suffix, but silently dropped the\nnullable annotation for any case where `CSharpP\n[…]\nrted-but-incorrect\n`T[]` (the test was added during T1.10 to pin element-mapping but\nlocked in the nullability drop alongside it).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Preserve nullable annotation on non-primitive top-level properties",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:24:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a09698587457040a47ab5ce674a2c4e9b5b6a533",
          "body": "The Geolocation_Wasm scenario already pinned the generated\n`AddGeolocationServices` extension shape; the Permissions_Wasm\nscenario was missing the matching snapshot. Add it so the DI wiring\nshape -- specifically the singleton `IJSInProcessRuntime` adapter\nthat resolves `IJSRuntime` and casts to the WASM in-process runtime\n-- is pinned under the Promise/async generation path too.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Pin Permissions DI extension snapshot",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:21:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b8b0935972b5b70949b83ef85d9db603c7e763ff",
          "body": "Two coupled gaps prevented the package from being usable:\n\n1. The csproj targeted `Microsoft.NET.Sdk` rather than\n   `Microsoft.NET.Sdk.Razor`, so `wwwroot/blazorators.permissions.g.js`\n   was never published as a static web asset under\n   `_content/Blazor.Permissions.WebAssembly/`. Consumers adding\n[…]\nissions API surface (including the\n`_content/Blazor.Permissions.WebAssembly/blazorators.permissions.g.js`\nscript tag instruction).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Convert Blazor.Permissions.WebAssembly to Razor class library",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:18:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4545ace2ab72616c594a878e769c3e56e9cdbed4",
          "body": "Promise-returning interop methods route through the async path even\nunder WebAssembly hosting (forced by `MethodBuilderDetails.Create`\nbecause a TS `Promise<T>` can't resolve synchronously). That means\nthe generated service references `ValueTask<T>` regardless of\nhosting model -- but the previous `A\n[…]\nendUsingDeclarations` and emit the using whenever the value is\ntrue. Updated the `Permissions_Wasm` snapshots to pin the new line.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit `using System.Threading.Tasks;` for Promise-returning WASM services",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:14:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ccb48144de39a68b24e0d25be561f3da7c443a4",
          "body": "Activating `[JSAutoInterop]` on `IPermissionsService` causes the\ngenerator to route the `Permissions.query(...)` call through\n`blazorators.permissions.query` (the standard `blazorators.<type>.<method>`\nshim path used whenever a parameter is a custom DTO). Ship the\nmatching JS file so `await Permissi\n[…]\nator strips `extends\n    EventTarget` and the `onchange` event-handler property, so the\n    payload only needs `Name` and `State`.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Add JS shim for `blazorators.permissions.query`",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:09:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ca589a6989488e73491916f0285ff818e1116099",
          "body": "Bring the published `Blazor.Permissions.WebAssembly` package in line\nwith the rest of the family (Geolocation, LocalStorage,\nSessionStorage, SpeechRecognition, SpeechSynthesis) by enabling the\n`[JSAutoInterop]` attribute that was previously commented out. The\ngenerator now correctly emits the full s\n[…]\nr\n    artefacts (`IPermissionsService.g.cs`, `PermissionsService.g.cs`,\n    `PermissionDescriptor.g.cs`, `PermissionStatus.g.cs`).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Activate `[JSAutoInterop]` on Blazor.Permissions.WebAssembly",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:07:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "43fdda018df614de808198e2e1de29a4a1fca432",
          "body": "The TS utility type `Record<K, V>` (the dictionary primitive) was\npreviously left untouched by the generator -- a property typed\n`Record<string, number>` emitted as the literal `Record<string,\nnumber>` into the C# DTO, which isn't a valid CLR type and broke\nany consumer that referenced the property.\n[…]\nwnstream DTO\nresolution.\n\n11 new tests in `TypeShapeRecordTests` cover the splitter and the\nproperty mapping. Full suite: 412/412.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Map TS `Record<K, V>` to C# `Dictionary<K, V>`",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T04:04:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c07fc681a6169b37e03c2dd04127a2c69bdc7b2e",
          "body": "Adds four snapshot tests around the Permissions DOM type\n(`navigator.permissions.query() -> Promise<PermissionStatus>`) to lock\nin three pre-existing behaviours under one realistic interop surface:\n\n  * `Promise<T>` returns map to `ValueTask<T>` with the `Async` method\n    suffix and `InvokeAsync<T>\n[…]\nsync, and strip a\ntrailing `| null` / `| undefined` clause so `Promise<T | null>` and\n`T | null` returns resolve against bare `T`.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Pin Permissions sample end-to-end + unwrap Promise<T> for dependent DTOs",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:58:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "42c23f09cac23d757d98dcf7d5e25babc0d6f3b8",
          "body": "Real DOM declarations use ` | undefined` interchangeably with\n` | null` to mean \"this value might not be present\", especially on\nPromise-returned values. Examples:\n\n  * `Cache.match(): Promise<Response | undefined>`\n  * `ServiceWorkerContainer.getRegistration(): Promise<ServiceWorkerRegistration | u\n[…]\nturn predicate, array-element extraction across both\nclause forms, and the property mapped-type helper. Full suite is\nnow 388/388.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Treat TS `| undefined` clause as nullable in all emit paths",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:52:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c94759703e6041c9312ea59dcc69db55fa8226d3",
          "body": "`AppendTripleSlashMethodComments` derived the generic-argument list\nfor the rendered `<c>System.Action{T1, T2, ...}</c>` token from\n`param.ActionDeclaration.DependentTypes.Keys`. That collection only\ncaptures *custom* types pulled into the dependency graph:\n\n  * TS primitives never go through the de\n[…]\nray, mixed, and zero-parameter\ncallback doc rendering, plus a regression assertion for the stray\nquote. Full suite is now 368/368.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Render accurate `System.Action<>` doc comment for callback parameters",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:47:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f33dde3452989e04919bfdd87114751784ad8bfb",
          "body": "Real DOM declarations declare parameters whose names collide with C#\nreserved keywords -- e.g. `Document.createElementNS(namespace: string,\nqualifiedName: string, ...)`, `Element.getAttributeNS(namespace, ...)`,\nseveral callback shims with parameters named `event`. The generator\nemitted the bare Typ\n[…]\n and without JSON marshalling), and the\n`null`-bearing parameter shape. Full suite now 363/363 green\n(was 328 before this commit).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Escape C# reserved keywords in generated parameter names",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:43:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "109a0e2b77f77fbc822326e82f5c09aeed8f73f3",
          "body": "TypeScript declares dozens of DOM APIs as `Promise<T>`-returning:\n`Permissions.query()`, `Body.arrayBuffer()`,\n`AudioContext.close()`, `Lock.request()`, etc. The generator\npreviously dropped the verbatim `Promise<T>` token straight into\nthe C# method signature and the `_javaScript.Invoke<T>()` call,\n[…]\ne,\nWASM and Server return-type emission for scalar / custom / nullable\n/ array payloads, and the `Promise<void>` shape end-to-end.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Unwrap TS `Promise<T>` return types to `ValueTask<T>`",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:40:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6c02169be93ec91d9e611647620a067086d9f0c0",
          "body": "Custom-type return types with a trailing TypeScript `| null` (e.g.\n`getElementById(id: string): HTMLElement | null;`,\n`getActiveElement(): Element | null;`) previously dropped the raw\nTS spelling straight into the generated method signature and the\n`_javaScript.Invoke<T>()` call. `Node | null` is no\n[…]\nom nullable, custom-array nullable,\nprimitive-array nullable, and the existing primitive scalar nullable\npath (regression-pinned).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Map TS `| null` clause to C# nullable suffix for method return types",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:33:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a239908c6dbad74690ed697499c21f243bfad8a1",
          "body": "The top-level emit path in CSharpTopLevelObject filters TypeScript\nindex-signature properties (`[key: string]: T;`) via\n`CSharpProperty.IsIndexer` before generating the interface and\nimplementation. The dependent-DTO emit path\n(`CSharpObject.ToClassString`) iterated the same property\ndictionary with\n[…]\no the dependent-DTO path mirrors the top-level path's behavior.\n\nAdds three regression tests in CSharpObjectIndexerFilterTests.cs.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Filter indexer properties from dependent DTO class emit",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:26:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ac96bd8b7e159a9f709f56e5b6133ad2f8df60c7",
          "body": "The two emit paths for a TS-callback-typed parameter -- the\npublic-facing `Action<...>?` signature in `CSharpType.ToActionString`\nand the private backing field in\n`SourceBuilder.AppendConditionalDelegateFields` -- derived their\ngeneric argument lists from different collections:\n\n* `ToActionString` j\n[…]\nts in CallbackPrimitiveParameterTests.cs\ncovering single-primitive, mixed primitive+custom, nullable, and\nboolean parameter cases.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Map TS primitive params to C# in callback emit paths",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:23:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "08a47aa34d4cc8bf3345357ff770695956a87c19",
          "body": "The shared property regex\n`^(?'Name'.*)\\:(?:.{1})(?'Type'.*)\\;$` has a greedy `Name` capture\nthat walks to the *last* `:` in a line. For TypeScript property\ndeclarations whose type is an arrow function -- e.g.\n`UnderlyingSource` in lib.dom.d.ts:\n\n    pull?: (controller: ReadableStreamDefaultControll\n[…]\n the\n`ToObject` (dependent-DTO) and `ToTopLevelObject` paths.\n\nAdds three regression tests in ArrowFunctionPropertyFilterTests.cs.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Filter arrow-function-typed property lines in IsProperty",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:18:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8d40daf7b2b03259b851fc577a985daf59b4ac7e",
          "body": "`lib.dom.d.ts` declares many trivial aliases that point at a primitive\nTS type, e.g.\n\n    type DOMHighResTimeStamp = number;\n    type GLuint = number;\n    type GLboolean = boolean;\n    type EpochTimeStamp = number;\n\nPreviously `TryGetPrimitiveType` only resolved string-literal-union\naliases (`type D\n[…]\nthe property, method-return, and parameter surfaces across\nthe three common alias shapes. Full suite: 279 -> 289 tests, all green.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Resolve single-primitive TypeScript aliases (DOMHighResTimeStamp, GL*)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:11:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8f897c190b0f7cb0b621d74c1ac0100173251265",
          "body": "Three code paths produced uncompilable output when a method accepted\na TS callback with zero parameters (e.g. `VoidFunction`, `(): void;`,\nused by `WindowOrWorkerGlobalScope.queueMicrotask`):\n\n* `CSharpType.ToActionString` joined `ActionDeclaration.DependentTypes`\n  keys into the generic argument li\n[…]\nross `CSharpTypeCallbackActionStringTests`\nand `SourceBuilderZeroParameterCallbackTests`. Full suite:\n274 -> 279 tests, all green.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit valid C# for zero-parameter TS callbacks (VoidFunction)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T03:03:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "41beab2bbf813f3e1515d9b8373ff618f4630ea5",
          "body": "When a method parameter or return type was an array of a user-defined\nTypeScript interface (e.g. `MutationRecord[]`), the generator looked\nthe literal type string up in the declaration map without stripping\nthe array suffix. Because the map keys the element type only, no\nmatch occurred, the element \n[…]\nntDependentTypeTests` covering\nparameter and return positions for all three array shapes. Full\nsuite: 268 -> 274 tests, all green.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Emit dependent DTOs for array-of-custom-type parameters and return types",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:58:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "466e854da35b911eac5d5c58e35b444c1f99092a",
          "body": "…positions\n\n`CSharpType.ToParameterString` and `CSharpMethodExtensions.GetMethodTypes`\nboth relied on `TypeMap.PrimitiveTypes.IsPrimitiveType(RawTypeName)`\nreturning `true` for the full type spelling. That works for scalar\nTS primitives (`number` -> `double`), but it returns `false` for the\narray fo\n[…]\nsts` (8 cases) and\n`CSharpMethodReturnTypeArrayTests` (11 cases) covering scalar +\nnullable + non-primitive forms. 268 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Map TypeScript primitive arrays to C# arrays in parameter and return …",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:55:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1adaca3077d526200440fe20d0de46fde8e6f408",
          "body": "…nostic and polish messages\n\n`Descriptors.PathFromWindowRequiredDiagnostic` carried a stale name\nfrom an earlier iteration of `JSAutoInteropAttribute` (when the\nproperty was called `PathFromWindow`). It now flags a missing\n`Implementation` value, so the field name was misleading - any future\ncontrib\n[…]\ne\n  controls\n\nThe diagnostics are still tracked as `Unshipped`, so the message\npolish is in-scope. All 249 tests continue to pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Rename PathFromWindowRequiredDiagnostic to ImplementationRequiredDiag…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:50:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3458ec5e679371260a614b6585d7739687302f28",
          "body": "ToObject and ToTopLevelObject classified a property as nullable when\nits raw type string `Contains(\"| null\")`. That returns false positives\nfor shapes where `| null` appears only inside a generic argument or\narray element (e.g. `(number | null)[]`, `Map<string, string | null>`).\nThe reference itself\n[…]\nameterized cases covering the new boundary (including the two\nnested-`| null` regressions that previously failed). 249 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Tighten property-level nullable detection to top-level | null only",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:46:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d8702001e7db546f6dd06eb68d0b95722db6235",
          "body": "CSharpObject.IsActionParameter used to OR shape-based IsCallback with\na name-suffix fallback `TypeName.EndsWith(\"Callback\")`. The latter\nmisclassified any normal DTO whose name happens to end with the\nsubstring, silently dropping it from the generated output (the\npredicate gates AddDependentTypesSou\n[…]\nests with five regression cases\ncovering the previous false-positive and confirming the new\nshape-driven behavior. 242 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Remove brittle Callback suffix fallback in IsActionParameter",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:44:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "42a066be5e76c6252ab1bc198262b1484153dca8",
          "body": "…lable arrays\n\n`CSharpProperty.IsArray` and `TryGetArrayElementTypeName` matched on\n`EndsWith(\"[]\")` (and the `Array<...>` / `ReadonlyArray<...>` generic\nprefixes) against the raw TypeScript type. For nullable arrays the\ntype ends with `null`, not `]` or `>`, so the array shape was never\nrecognized.\n[…]\ndouble[]\"\n\nAdds 13 parameterized regression cases across `IsArray`,\n`MappedTypeName`, and `GetPropertyTypes`.\n\nAll 234 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: recognize `T[] | null` (and Array/ReadonlyArray variants) as nul…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:40:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "47e68bddc64aa0d8f38104b17d8fc6abae2b809e",
          "body": "…le shapes\n\n`CSharpMethod.IsReturnTypeNullable` checked\n`RawReturnTypeName.Contains(\"null\")`, which returns `true` for any\nidentifier whose name happens to contain the substring \"null\" --\nincluding the bundled DOM types `OnBeforeUnloadEventHandlerNonNull`\nand `OnErrorEventHandlerNonNull`, plus any u\n[…]\nssion cases covering both true positives\n(real `| null` clauses) and false positives (identifier substrings).\n\nAll 221 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: tighten `IsReturnTypeNullable` to recognize only TS-level nullab…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:36:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "94fb3f0376c84d91fe81bd71226fc8425b7777a6",
          "body": "`ParseParameters` previously detected nullability only from the\nparameter name's trailing `?`. When a `.d.ts` parameter was instead\nwritten as `x: T | null` (without a `?` on the name), the parser\nkept the literal \"| null\" in the C# type token. For primitives like\n`string | null` this happened to wo\n[…]\ns the parameter's `IsNullable` flag flips and that\n`ToParameterString()` no longer contains the literal `| null`.\n\n210 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: normalize type-level `| null` parameter annotations to nullable C#",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:35:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a37b986430b786027758326e7fbde5a38792f3bc",
          "body": "…ions\n\n`GenericMethodDescriptors`, `PureJavaScriptOverrides`, and\n`TypeDeclarationSources` accept `string[]?`. With C# 12 collection\nexpressions, consumers can write:\n\n    [JSAutoGenericInterop(\n        GenericMethodDescriptors = [\"getItem\", \"setItem:value\"])]\n\n`ReadStringArray` recognized `new[] { \n[…]\ner\n  - [...] collection expression with literal strings\n  - [...] collection expression with const references\n\nAll 207 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "feat: parse string-array attribute args from C# 12 collection express…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:31:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "59131477061f7b7b7aa470e503ed4a5d14017ed9",
          "body": "`ResolveParsers` constructed a fresh `TypeDeclarationParser` (and the\nunderlying `TypeDeclarationReader`) for every matched `.d.ts`\nreference in every target. When multiple `[JSAutoInterop]` targets\nin the same compilation point at the same `AdditionalFile` (the\ncommon case once `TypeDeclarationSour\n[…]\nis GC'd with the parsers\nthemselves; we do not extend their lifetime beyond the source-output\nboundary.\n\nAll 203 tests still pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "perf: share TypeDeclarationParser across targets within an Execute pass",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:29:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "df5dbb76d6942ef3fcf55162f8038815ad1c9ad1",
          "body": "The `Indentation` value type held a `Level` field that was never\nclamped. `Decrease()` computed `Level - 1 - extra`, and `ResetTo(int)`\ncopied the caller's value verbatim. Both could leave `Level` negative.\n`ToString()` then evaluates `new string(' ', Spaces * Level)` which\nthrows `ArgumentOutOfRang\n[…]\n regression tests covering Decrease-from-zero,\nDecrease-with-extra, ResetTo-negative, and the positive paths.\n\nAll 203 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: clamp Indentation Decrease/ResetTo to non-negative levels",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:26:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "685cdd3ed6ae2d523f4a392a2207d64626fb95d7",
          "body": "…ually shrinks\n\nThe previous test only asserted that *some* output was produced when\n'OnlyGeneratePureJS = true' was set, which any non-trivial code path\nwould satisfy. The flag's documented purpose is to *exclude* methods\nthat need JS-callback wiring (e.g. 'Geolocation.watchPosition'/\n'getCurrentPo\n[…]\ned out).\n\nThis catches regressions where the flag silently stops gating output,\nwhich the prior test did not.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test: strengthen OnlyGeneratePureJS coverage to verify method-set act…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:25:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8ce5d2ab50722d9d80064b8780364125e10a3233",
          "body": "…ehavior\n\nTwo internal comments still described TypeDeclarationSources as\n'reserved for future use' even though T5.1 fully wired the property\ninto the generator pipeline. Update both to describe the actual\nbehavior:\n\n* GeneratorOptions.BuildParsers — clarify that this is the fallback\n  path used whe\n[…]\nReader(content) directly,\n  which is what the generator already does for AdditionalFiles.\n\nNo behavior change. All 198 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: refresh stale TypeDeclarationSources comments to reflect T5.1 b…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:23:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7e5ff5b39f17a2b8b10ec2b7b8b5122ed27cd49a",
          "body": "….1 behavior\n\nThe emitted attribute's XML doc for `TypeDeclarationSources` still\nclaimed the property was \"reserved for future use\" and that \"setting\nit has no effect\". The audit's T5.1 work wired this property into the\ngenerator pipeline so the generator now reads matched `.d.ts` files\nfrom `Additi\n[…]\nle doc with the actual behavior, including the\n`AdditionalFiles` MSBuild snippet a consumer needs to wire up.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: align JSAutoInteropAttribute.TypeDeclarationSources doc with T5…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:23:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2a12791de33190827d119fee9c69926287b2c8de",
          "body": "Mark every regex in `SharedRegex` as `RegexOptions.Compiled |\nRegexOptions.CultureInvariant`. The parser evaluates these patterns\nmany times per generator run - once per matched interface, method,\nproperty, and array literal across ~800KB of lib.dom.d.ts plus any\nconsumer-supplied `.d.ts` files in `\n[…]\n removes culture-sensitive case-folding\nfrom the matcher even though none of these patterns use `IgnoreCase`.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "perf: compile shared parser regexes",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:21:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "63f31ff1ba80511890840f9ed14c707f5f31fe15",
          "body": "… interface\n\n`CSharpProperty.MappedTypeName` deliberately returns the *element* type\nfor array-shaped TypeScript types so that primitive-type lookups and\ndependency-graph walks can ignore the array wrapper. `CSharpObject.AppendProperty`\nalready re-attaches `[]` via a separate `IsArray` check, but th\n[…]\ng\nall three TypeScript array forms (`T[]`, `Array<T>`, `ReadonlyArray<T>`)\nagainst both `IsWebAssembly` arms.\n\nAll 198 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: preserve `[]` suffix when emitting array properties on top-level…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:18:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "af4f9eabc7f78beda830d21c12826adeb02474eb",
          "body": "… lookups\n\nTwo small but correct improvements to the generator hot path:\n\n1. `JavaScriptInteropGenerator.Execute` now reads\n   `context.CancellationToken` once and calls\n   `ThrowIfCancellationRequested()` at the top of every outer-target\n   iteration and inside the inner parser loop. Previously the\n[…]\ne across ~800KB of lib.dom.d.ts, so this O(1) lookup\n   replaces what was effectively an O(n) per-check scan.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "perf: thread CancellationToken through Execute and speed up primitive…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:16:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8fd9a5e78231085adcce6ebe7c58f99e63f294c7",
          "body": "`SourceBuilder.AppendConditionalDelegateCallbackMethods` only called\n`ResetIndentationTo(level)` after the entire loop. Each iteration\ncalls `AppendRaw(..., postIncreaseIndentation: true)` (twice through\n`AppendParameters`), so successive callback methods were emitted at\never-deeper indentation. The\n[…]\nInvokable] block starts at the outer indentation level\nregardless of what the previous iteration left behind.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: reset indentation per [JSInvokable] block in callback emit",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:13:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "58fa3cf5c470bf779d1e9ab14d966b123256e88d",
          "body": "Adds five additional [InlineData] cases to GeneratorOutputValidityTests\nthat exercise less-trodden code paths through the generator:\n\n* LocalStorage on Server (generic + non-generic)\n* LocalStorage on WASM (non-generic)\n* Geolocation with OnlyGeneratePureJS = true\n* SessionStorage on WASM (generic)\n\n[…]\nttribute parsing, hosting-model branches,\nand the OnlyGeneratePureJS flag without requiring snapshot updates.\n\nAll 192 tests pass.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test: expand generator output validity sweep with 5 new scenarios",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-16T02:13:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "838a48e900a4e0cee1df345d7d0d3144626bcbbb",
          "body": "Until now `JSAutoInteropAttribute.TypeDeclarationSources` was a\ndocumented option that did nothing - the generator always parsed the\nembedded `lib.dom.d.ts` regardless. Consumers wanting to wire a\nnon-DOM TypeScript declaration file (their own ambient module, a\nthird-party `.d.ts`, or a polyfill typ\n[…]\nes_IsBenignNoOp` E2E test that pinned the old\nno-op behavior. Adds README documentation of the new option.\n\n187/187 tests passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "feat: wire TypeDeclarationSources into AdditionalTexts (T5.1)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T19:12:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3c57b258b0b70b80e34fda60443c16035020edbc",
          "body": "The pre-audit attribute argument parser worked entirely on\n`AttributeArgumentSyntax.Expression.ToString()` and string-replaced\nquotes. That approach failed for:\n\n  - String literals containing escape sequences. The naive\n    `Replace(\"\\\"\", \"\")` mangled escaped quotes (`\"foo\\\"bar\"` became\n    `foo\\ba\n[…]\ns) covering\nescape sequences, const references, nameof, verbatim strings,\nenum members, and bool literals.\n\n184/184 tests passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: parse attribute arguments via SemanticModel (T1.11)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T19:02:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5fcce88ff9ed0ab72f489d17f598fb311a20dad3",
          "body": "Correctness fixes:\n\n  - The \"Note\" about packaging incorrectly claimed Server packages\n    expose a synchronous API. They expose `ValueTask`-based async\n    methods through `IJSRuntime`; the WebAssembly variant uses\n    `IJSInProcessRuntime` which is itself synchronous JS dispatch\n    but still surf\n[…]\ndditions from the audit\n    (previously the generator was silent on missing `partial`,\n    unknown `TypeName`, or parse failures).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "docs: README accuracy pass (post-audit)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:58:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1f4e5c23ff5d55a943b5e2a4f7cb77d4af7da54c",
          "body": "`ToClassString` was a single ~65-line method building DTO source by\nhand with raw interpolated `\\n`-terminated strings inside one giant\n`foreach` over properties. The shape made it hard to spot anything\ndistinct - the special-case DOMTimeStamp / EpochTimeStamp UTC accessor\nwas buried inside the prop\n[…]\nng mode.\n  - Two new snapshot tests pin the DTO output specifically, so any\n    future change to `ToClassString` will fail loudly.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "refactor: split CSharpObject.ToClassString into named helpers (T3.9)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:56:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "217b870cee43e0da70f6c594f8796637b4a17bac",
          "body": "The implementation builder was a 286-line method with three structurally\ndistinct branches nested inside a `foreach (method)` loop:\n\n  1. Pure / non-bi-directional / JS-override invocations\n  2. Generic `TComponent` overload (bi-directional callback shape)\n  3. `Action<T>` callback overload (same ca\n[…]\nweep (`GeneratorOutputValidityTests`) confirms\n    every generated tree still parses without syntax errors.\n\nSnapshot diff: empty.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "refactor: split CSharpTopLevelObject.ToImplementationString (T3.8)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:53:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "687cacbc6e331ffc4504feec10263acfd397a9b9",
          "body": "T5.2 added `void -> void` to `TypeMap.PrimitiveTypes` so the parser\ncan short-circuit on void-returning methods instead of trying to\nrecurse into a non-existent `void` declaration. This (correctly)\nmade `IsPrimitiveType(\"void\")` return true for the first time.\n\nThat flipped a latent ordering bug in\n\n[…]\normalizeWhitespace removal, T3.8\n    `ToImplementationString` refactor) producing malformed C#.\n\nTests: 176/176 (was 173 + 3 new).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: emit `ValueTask` (not `ValueTask<void>`) for void Server methods",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:48:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3b80dc675c58ee775c21bbcb36553d4a83e50e5e",
          "body": "Adds a lightweight string-snapshot helper plus 5 baseline snapshots\ncovering the most-exercised interop scenarios:\n\n  - Geolocation_Wasm:  interface, implementation, DI extension\n  - Geolocation_Server: implementation (proves async ValueTask shape)\n  - LocalStorage_Wasm_Generic: interface (proves JS\n[…]\nanother reference\nasset and disk layout convention isn't worth it for ~50 lines of\nhelper code.\n\nTests: 173/173 (was 168 + 5 new).\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test: add hand-rolled snapshot harness for generator output",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:45:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5572a36f5d0b85a195a0551905cc81fb5709b9d0",
          "body": "Adds primitive mappings for the TypeScript tokens that flow through\n`lib.dom.d.ts` but were previously unhandled by `TypeMap.PrimitiveTypes`.\nAnything not in the map falls through `IsPrimitiveType` to the\ndeclaration-recursion branch, which either emits an empty placeholder\nDTO (for declared interfa\n[…]\nrough a translated parameter type).\n  - Negative cases - real DOM interface names still report `false`.\n\nTotal tests: 168 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "feat: expand TypeMap to cover void/any/bigint/typed-arrays (T5.2)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-15T18:43:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b4356a1ba8ecf0c8ff74e0c40c53ef8b2ce3b2f9",
          "body": "…T1.4)\n\nThe `TypeDeclarationSources` attribute parameter was documented as\naccepting \"URLs or file paths\" but the implementation is a no-op:\n`TypeDeclarationReader.Factory(string)` ignores its argument and\nreturns the default embedded-resource reader, with the URI handling\ncommented out.\n\nThis commi\n[…]\n the no-op contract so any future implementation has to\n    actively change behavior, not just compile.\n\nTotal tests: 120 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "refactor: clarify TypeDeclarationSources as reserved-for-future-use (…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-14T22:35:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "165ef6e8d907f9de2f677043b2a41ba8a229ca22",
          "body": "…T3.10)\n\nPreviously the parser identified TypeScript callback interfaces using a\nbrittle `typeName.EndsWith(\"Callback\")` heuristic in two places:\n\n  - `TypeDeclarationParser.ParseParameters` - to decide whether to call\n    `ToAction(...)` and emit an `Action<T>` parameter, or `ToObject(...)`\n    and\n[…]\negative cases (regular interfaces, properties-only, empty bodies,\n    whitespace, non-interface input).\n\nTotal tests: 119 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "refactor: replace `EndsWith(\"Callback\")` with shape-based detection (…",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-14T22:32:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4aacf1c24785fcf3684f461904420839e94da6d4",
          "body": "Six end-to-end tests covering the actual shape of the generated\noutput across all four artifact kinds the generator emits per\n`[JSAutoInterop]` hit:\n\n- `Geolocation_InterfaceFile_DeclaresExpectedMembers` - the\n  `IGeolocationService` interface file declares `ClearWatch`,\n  `GetCurrentPosition`, `Wat\n[…]\ntic and hosting-model tests added earlier,\nthis closes the Tier 4 \"end-to-end generation\" coverage gap.\n\nTotal tests: 105 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test: add end-to-end snapshot-style generation tests (T4)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-14T22:29:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "279e214545947929f4fad5f44f297d3351ed93a6",
          "body": "Four tests verifying that the `HostingModel = BlazorHostingModel.X`\nattribute argument correctly switches the generator between\nWebAssembly (synchronous, `IJSInProcessRuntime`) and Server\n(asynchronous, `IJSRuntime`) output shapes.\n\n- `Default_GeneratesWebAssemblyExtensions` - default mode emits\n  `\n[…]\nse the interface filename also ends with that\nsuffix - exact filename match is the only safe comparison.\n\nTotal tests: 99 passing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test: add WebAssembly vs Server hosting-model regression tests (T4)",
          "author_name": "David Pine",
          "author_login": "IEvangelist",
          "committed_at": "2026-05-14T22:28:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 43,
      "commits_last_year": 124,
      "latest_release_at": "2026-07-24T18:48:52Z",
      "latest_release_tag": "10.1.0",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 142
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 71,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "Blazor.DOM",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "dotnetcore",
            "csharp",
            "blazor",
            "server",
            "dom",
            "interop",
            "jsinterop"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.DOM",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 1,
          "total_downloads": 0,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:39.883000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.Clipboard",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "blazor",
            "server",
            "dom",
            "interop",
            "clipboard"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.Clipboard",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 1,
          "total_downloads": 0,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:38.400000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.Credentials",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "blazor",
            "server",
            "dom",
            "interop",
            "credentials",
            "webauthn"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.Credentials",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 1,
          "total_downloads": 0,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:39Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.Geolocation",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "dotnetcore",
            "csharp",
            "blazor",
            "server",
            "wasm",
            "generators",
            "sourcegen",
            "roslyn"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.Geolocation",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 19,
          "total_downloads": 94337,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:40.950000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.LocalStorage",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "dotnetcore",
            "csharp",
            "blazor",
            "generators",
            "sourcegen",
            "roslyn"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.LocalStorage",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 19,
          "total_downloads": 84532,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:41.440000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.MediaDevices",
          "exists": true,
          "license": null,
          "keywords": [
            "dotnet",
            "blazor",
            "server",
            "dom",
            "interop",
            "media-devices",
            "get-user-media",
            "display-capture"
          ],
          "ecosystem": "nuget",
          "matches_repo": true,
          "registry_url": "https://www.nuget.org/packages/Blazor.MediaDevices",
          "is_deprecated": false,
          "latest_version": "10.1.0",
          "repository_url": "https://github.com/IEvangelist/blazorators",
          "versions_count": 1,
          "total_downloads": 0,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T18:52:41.963000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        },
        {
          "name": "Blazor.Notifications",
          "exists": true,
          "license": null,
          "keywords": [
            "Blazor",
            "Notifications",
            "C#",
            ".NET",
            "Standard",
            ".NET",
            "Core"
          ],
          "ecosystem": "nuget",
          "matches_repo": false,
          "registry_url": "https://www.nuget.org/packages/Blazor.Notifications",
          "is_deprecated": false,
          "latest_version": "0.2.0",
          "repository_url": "https://github.com/vertonghenb/Blazor.Notifications",
          "versions_count": 2,
          "total_downloads": 3360,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2018-06-19T23:35:33.853000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 2956
        }
      ]
    },
    "popularity": {
      "forks": 32,
      "stars": 392,
      "watchers": 13,
      "fork_history": {
        "days": [
          {
            "date": "2021-10-12",
            "count": 1
          },
          {
            "date": "2022-03-08",
            "count": 1
          },
          {
            "date": "2022-03-25",
            "count": 1
          },
          {
            "date": "2022-04-04",
            "count": 1
          },
          {
            "date": "2022-04-08",
            "count": 1
          },
          {
            "date": "2022-04-12",
            "count": 3
          },
          {
            "date": "2022-04-14",
            "count": 1
          },
          {
            "date": "2022-04-21",
            "count": 1
          },
          {
            "date": "2022-05-11",
            "count": 1
          },
          {
            "date": "2022-10-07",
            "count": 1
          },
          {
            "date": "2022-10-23",
            "count": 1
          },
          {
            "date": "2022-11-04",
            "count": 1
          },
          {
            "date": "2022-12-01",
            "count": 1
          },
          {
            "date": "2023-01-24",
            "count": 1
          },
          {
            "date": "2023-02-02",
            "count": 1
          },
          {
            "date": "2023-02-10",
            "count": 1
          },
          {
            "date": "2023-02-15",
            "count": 1
          },
          {
            "date": "2023-02-16",
            "count": 1
          },
          {
            "date": "2023-02-17",
            "count": 1
          },
          {
            "date": "2023-04-20",
            "count": 1
          },
          {
            "date": "2023-04-22",
            "count": 1
          },
          {
            "date": "2023-06-09",
            "count": 1
          },
          {
            "date": "2023-11-18",
            "count": 1
          },
          {
            "date": "2024-01-01",
            "count": 1
          },
          {
            "date": "2024-01-08",
            "count": 1
          },
          {
            "date": "2024-01-14",
            "count": 1
          },
          {
            "date": "2024-03-19",
            "count": 1
          },
          {
            "date": "2024-07-02",
            "count": 1
          },
          {
            "date": "2025-04-04",
            "count": 1
          },
          {
            "date": "2025-05-17",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 32,
        "total_forks": 32
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "samples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tools/Blazor.DOM.TypeScriptModel/tsconfig.json"
      ],
      "toolchain_manifests": [
        "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj",
        "samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj",
        "src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj",
        "src/Blazor.BrowserCoordination/Blazor.BrowserCoordination.csproj",
        "src/Blazor.Clipboard.WebAssembly/Blazor.Clipboard.WebAssembly.csproj",
        "src/Blazor.Clipboard/Blazor.Clipboard.csproj",
        "src/Blazor.Credentials.WebAssembly/Blazor.Credentials.WebAssembly.csproj",
        "src/Blazor.Credentials/Blazor.Credentials.csproj",
        "src/Blazor.DOM.Generation/Blazor.DOM.Generation.csproj",
        "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
        "src/Blazor.DOM/Blazor.DOM.csproj",
        "src/Blazor.FileSystemAccess.WebAssembly/Blazor.FileSystemAccess.WebAssembly.csproj",
        "src/Blazor.FileSystemAccess/Blazor.FileSystemAccess.csproj",
        "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj",
        "src/Blazor.Geolocation/Blazor.Geolocation.csproj",
        "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
        "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
        "src/Blazor.MediaDevices.WebAssembly/Blazor.MediaDevices.WebAssembly.csproj",
        "src/Blazor.MediaDevices/Blazor.MediaDevices.csproj",
        "src/Blazor.Notifications.WebAssembly/Blazor.Notifications.WebAssembly.csproj",
        "src/Blazor.Notifications/Blazor.Notifications.csproj",
        "src/Blazor.OfflineStorage.WebAssembly/Blazor.OfflineStorage.WebAssembly.csproj",
        "src/Blazor.OfflineStorage/Blazor.OfflineStorage.csproj",
        "src/Blazor.Performance.WebAssembly/Blazor.Performance.WebAssembly.csproj",
        "src/Blazor.Performance/Blazor.Performance.csproj",
        "src/Blazor.Permissions.WebAssembly/Blazor.Permissions.WebAssembly.csproj",
        "src/Blazor.Permissions/Blazor.Permissions.csproj",
        "src/Blazor.Screen.WebAssembly/Blazor.Screen.WebAssembly.csproj",
        "src/Blazor.Screen/Blazor.Screen.csproj",
        "src/Blazor.Serialization/Blazor.Serialization.csproj",
        "src/Blazor.SessionStorage.WebAssembly/Blazor.SessionStorage.WebAssembly.csproj",
        "src/Blazor.SessionStorage/Blazor.SessionStorage.csproj",
        "src/Blazor.Share.WebAssembly/Blazor.Share.WebAssembly.csproj",
        "src/Blazor.Share/Blazor.Share.csproj",
        "src/Blazor.SourceGenerators/Blazor.SourceGenerators.csproj",
        "src/Blazor.SpeechRecognition.WebAssembly/Blazor.SpeechRecognition.WebAssembly.csproj",
        "src/Blazor.SpeechRecognition/Blazor.SpeechRecognition.csproj",
        "src/Blazor.SpeechSynthesis.WebAssembly/Blazor.SpeechSynthesis.WebAssembly.csproj",
        "src/Blazor.SpeechSynthesis/Blazor.SpeechSynthesis.csproj",
        "src/Blazor.StorageManagement.WebAssembly/Blazor.StorageManagement.WebAssembly.csproj",
        "src/Blazor.StorageManagement/Blazor.StorageManagement.csproj",
        "src/Blazor.WakeLock.WebAssembly/Blazor.WakeLock.WebAssembly.csproj",
        "src/Blazor.WakeLock/Blazor.WakeLock.csproj",
        "src/Blazor.WebCrypto.WebAssembly/Blazor.WebCrypto.WebAssembly.csproj",
        "src/Blazor.WebCrypto/Blazor.WebCrypto.csproj",
        "tests/Blazor.BrowserCoordination.Tests/Blazor.BrowserCoordination.Tests.csproj",
        "tests/Blazor.Clipboard.Tests/Blazor.Clipboard.Tests.csproj",
        "tests/Blazor.Credentials.Tests/Blazor.Credentials.Tests.csproj",
        "tests/Blazor.DOM.Accessors.CompilationTests/Blazor.DOM.Accessors.CompilationTests.csproj",
        "tests/Blazor.DOM.AdvancedTypes.CompilationTests/Blazor.DOM.AdvancedTypes.CompilationTests.csproj",
        "tests/Blazor.DOM.CSharpGenerator.Tests/Blazor.DOM.CSharpGenerator.Tests.csproj",
        "tests/Blazor.DOM.Generic.CompilationTests/Blazor.DOM.Generic.CompilationTests.csproj",
        "tests/Blazor.DOM.GlobalNamespace.CompilationTests/Blazor.DOM.GlobalNamespace.CompilationTests.csproj",
        "tests/Blazor.DOM.NonEventDeferrals.CompilationTests/Blazor.DOM.NonEventDeferrals.CompilationTests.csproj",
        "tests/Blazor.DOM.ProfileRuntime/Blazor.DOM.ProfileRuntime.csproj",
        "tests/Blazor.DOM.ResolvedFailures.CompilationTests/Blazor.DOM.ResolvedFailures.CompilationTests.csproj",
        "tests/Blazor.DOM.Server.CompilationTests/Blazor.DOM.Server.CompilationTests.csproj",
        "tests/Blazor.DOM.SupplementalBrowserApis.CompilationTests/Blazor.DOM.SupplementalBrowserApis.CompilationTests.csproj",
        "tests/Blazor.DOM.Tests/Blazor.DOM.Tests.csproj",
        "tests/Blazor.DOM.TypedEvents.CompilationTests/Blazor.DOM.TypedEvents.CompilationTests.csproj",
        "tests/Blazor.DOM.TypedUnions.CompilationTests/Blazor.DOM.TypedUnions.CompilationTests.csproj",
        "tests/Blazor.DOM.WakeLock.CompilationTests/Blazor.DOM.WakeLock.CompilationTests.csproj",
        "tests/Blazor.DOM.WebAssembly.CompilationTests/Blazor.DOM.WebAssembly.CompilationTests.csproj",
        "tests/Blazor.ExampleConsumer.EndToEndTests/Blazor.ExampleConsumer.EndToEndTests.csproj",
        "tests/Blazor.FileSystemAccess.Tests/Blazor.FileSystemAccess.Tests.csproj",
        "tests/Blazor.OfflineStorage.Tests/Blazor.OfflineStorage.Tests.csproj",
        "tests/Blazor.Performance.Tests/Blazor.Performance.Tests.csproj",
        "tests/Blazor.Screen.Tests/Blazor.Screen.Tests.csproj",
        "tests/Blazor.Share.Tests/Blazor.Share.Tests.csproj",
        "tests/Blazor.SourceGenerators.Tests/Blazor.SourceGenerators.Tests.csproj",
        "tests/Blazor.StorageManagement.Tests/Blazor.StorageManagement.Tests.csproj",
        "tests/Blazor.WakeLock.Tests/Blazor.WakeLock.Tests.csproj",
        "tests/Blazor.WebCrypto.Tests/Blazor.WebCrypto.Tests.csproj",
        "tools/Blazor.DOM.CSharpGenerator/Blazor.DOM.CSharpGenerator.csproj"
      ],
      "largest_source_bytes": 816786,
      "source_files_sampled": 429,
      "oversized_source_files": 7,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "fast-uri",
            "direct": false,
            "version": "3.1.3",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-v2hh-gcrm-f6hx"
            ],
            "fixed_version": "4.1.1",
            "advisory_count": 1,
            "oldest_advisory_days": 2
          },
          {
            "name": "ajv",
            "direct": false,
            "version": "8.17.1",
            "severity": "moderate",
            "ecosystem": "npm",
            "cvss_score": 5.3,
            "advisory_ids": [
              "GHSA-2g4f-4pwh-qvx6"
            ],
            "fixed_version": "8.18.0",
            "advisory_count": 1,
            "oldest_advisory_days": 162
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 1,
          "moderate": 1
        },
        "advisory_count": 2,
        "affected_count": 2,
        "assessed_count": 19,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 19,
        "direct_affected_count": 0
      },
      "ecosystems": [],
      "dependencies": [
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.AspNetCore.Components.WebAssembly",
          "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.DependencyInjection",
          "manifest": "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.DOM/Blazor.DOM.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.DOM/Blazor.DOM.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.AspNetCore.Components.Web",
          "manifest": "src/Blazor.DOM/Blazor.DOM.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.DependencyInjection",
          "manifest": "src/Blazor.DOM/Blazor.DOM.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.JSInterop",
          "manifest": "src/Blazor.DOM/Blazor.DOM.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.AspNetCore.Components.Web",
          "manifest": "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.AspNetCore.Components.Web",
          "manifest": "src/Blazor.Geolocation/Blazor.Geolocation.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.DependencyInjection",
          "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.Primitives",
          "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.JSInterop",
          "manifest": "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.SourceLink.GitHub",
          "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "MinVer",
          "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.DependencyInjection",
          "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.Extensions.Primitives",
          "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        },
        {
          "name": "Microsoft.JSInterop",
          "manifest": "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
          "ecosystem": "nuget",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "Microsoft.AspNetCore.Components.Web",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.AspNetCore.Components.WebAssembly",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.Extensions.DependencyInjection",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.Extensions.Primitives",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.JSInterop",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.SourceLink.GitHub",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "MinVer",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "@pagefind/darwin-arm64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/darwin-x64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/freebsd-x64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/linux-arm64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/linux-x64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/windows-arm64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@pagefind/windows-x64",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "26.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@webgpu/types",
            "direct": false,
            "version": "0.1.71",
            "ecosystem": "npm"
          },
          {
            "name": "@webref/idl",
            "direct": false,
            "version": "3.81.3",
            "ecosystem": "npm"
          },
          {
            "name": "ajv",
            "direct": false,
            "version": "8.17.1",
            "ecosystem": "npm"
          },
          {
            "name": "fast-deep-equal",
            "direct": false,
            "version": "3.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "fast-uri",
            "direct": false,
            "version": "3.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "json-schema-traverse",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "pagefind",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "require-from-string",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "5.9.3",
            "ecosystem": "npm"
          },
          {
            "name": "undici-types",
            "direct": false,
            "version": "8.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "webidl2",
            "direct": false,
            "version": "24.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "Basic.Reference.Assemblies",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "coverlet.collector",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Deque.AxeCore.Playwright",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Humanizer.Core",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.AspNetCore.Components.WebAssembly.DevServer",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.CodeAnalysis.Analyzers",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.CodeAnalysis.CSharp",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.NET.Test.Sdk",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.Playwright",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "System.Reactive.Linq",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "xunit",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "xunit.runner.visualstudio",
            "direct": false,
            "version": null,
            "ecosystem": "nuget"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 38,
        "direct_count": 7,
        "indirect_count": 31
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 28,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 32,
        "closed_unmerged_prs": 3
      },
      "bus_factor": 1,
      "bot_contributors": 2,
      "top_contributors": [
        {
          "type": "User",
          "login": "IEvangelist",
          "commits": 300,
          "avatar_url": "https://avatars.githubusercontent.com/u/7679720?v=4"
        },
        {
          "type": "User",
          "login": "WeihanLi",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/7604648?v=4"
        },
        {
          "type": "User",
          "login": "colindembovsky",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/1932561?v=4"
        },
        {
          "type": "User",
          "login": "taori",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/5545184?v=4"
        },
        {
          "type": "User",
          "login": "robertmclaws",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/1657085?v=4"
        },
        {
          "type": "User",
          "login": "TanayParikh",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/14852843?v=4"
        }
      ],
      "contributors_sampled": 6,
      "top_contributor_share": 0.974
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build-validation.yml",
        "pr-validation.yml",
        "publish-nuget.yml",
        "publish-to-gh-pages.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": true,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 7,
            "reason": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/28 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 6 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 1,
            "reason": "dependency not pinned by hash detected -- score normalized to 1",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 8,
            "reason": "2 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "abe9091425dc6bd6126011894642fc370bc2876d",
        "ran_at": "2026-07-24T19:01:55Z",
        "aggregate_score": 5.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T19:01:34Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-23T20:57:01Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/IEvangelist/blazorators",
    "host": "github.com",
    "name": "blazorators",
    "owner": "IEvangelist"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 68,
      "inputs": {
        "security": 63,
        "vitality": 74,
        "community": 64,
        "governance": 66,
        "engineering": 71
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 74,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "commits_last_year": 124,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "124 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 124
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "good",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 84,
            "inputs": {
              "releases_count": 43,
              "latest_release_tag": "10.1.0",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 142
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "43 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 43
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~142 days",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 142
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 64,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "moderate",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "forks": 32,
              "stars": 392,
              "watchers": 13,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "392 stars",
                "points": 42,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 392
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "32 forks",
                "points": 12.4,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 32
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "13 watchers",
                "points": 6,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 68,
            "inputs": {
              "packages": [
                "Blazor.DOM",
                "Blazor.Clipboard",
                "Blazor.Credentials",
                "Blazor.Geolocation",
                "Blazor.LocalStorage",
                "Blazor.MediaDevices"
              ],
              "dependents": null,
              "ecosystems": "nuget",
              "total_downloads": 178869,
              "monthly_downloads": null
            },
            "components": [
              {
                "key": "total_downloads",
                "name": "Total downloads",
                "detail": "178,869 downloads all-time across nuget",
                "points": 54.6,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_total",
                    "params": {
                      "count": 178869,
                      "ecosystems": "nuget"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 66,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 28,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 6,
              "top_contributor_share": 0.974
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 97% of commits",
                "points": 0.6,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 97
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "6 contributors",
                "points": 8.1,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 6 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "merged_prs": 28,
              "open_issues": 0,
              "closed_issues": 32,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 3
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "28/31 decided PRs merged",
                "points": 34.5,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 28,
                      "decided": 31
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/28 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 71,
            "inputs": {
              "followers": 1017,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "IEvangelist",
              "public_repos": 336,
              "account_age_days": 4445
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "1,017 followers of IEvangelist",
                "points": 21.6,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 1017,
                      "login": "IEvangelist"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "336 public repos, account ~12 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 336
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 12
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "Blazor.DOM",
                "Blazor.Clipboard",
                "Blazor.Credentials",
                "Blazor.Geolocation",
                "Blazor.LocalStorage",
                "Blazor.MediaDevices"
              ],
              "ecosystems": "nuget",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "6 package(s) on nuget",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 6,
                      "ecosystems": "nuget"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "19 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 19
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 71,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "4 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7",
                "points": 14,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [
                "blazor",
                "blazor-webassembly",
                "javascript",
                "typescript",
                "javascript-interop",
                "source-generators",
                "hacktoberfest"
              ],
              "has_wiki": true,
              "homepage": "https://ievangelist.github.io/blazorators/",
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://ievangelist.github.io/blazorators/",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "7 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 63,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 54,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.4
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "3 out of 4 merged PRs checked by a CI test -- score normalized to 7",
                "points": 1.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/28 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 6 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 0.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "2 existing vulnerabilities detected",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 19 resolved dependencies against OSV; 19 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 19
                }
              },
              {
                "code": "advisories_unassessed",
                "params": {
                  "count": 19
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 2,
              "assessed_packages": 19,
              "unassessed_packages": 19,
              "affected_by_severity": "high 1, moderate 1",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 19,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 14
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 60,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.92,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "92 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 92,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tools/Blazor.DOM.TypeScriptModel/tsconfig.json"
              ],
              "agent_commit_share": 0.98,
              "toolchain_manifests": [
                "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj",
                "samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj",
                "src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj",
                "src/Blazor.BrowserCoordination/Blazor.BrowserCoordination.csproj",
                "src/Blazor.Clipboard.WebAssembly/Blazor.Clipboard.WebAssembly.csproj",
                "src/Blazor.Clipboard/Blazor.Clipboard.csproj",
                "src/Blazor.Credentials.WebAssembly/Blazor.Credentials.WebAssembly.csproj",
                "src/Blazor.Credentials/Blazor.Credentials.csproj",
                "src/Blazor.DOM.Generation/Blazor.DOM.Generation.csproj",
                "src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj",
                "src/Blazor.DOM/Blazor.DOM.csproj",
                "src/Blazor.FileSystemAccess.WebAssembly/Blazor.FileSystemAccess.WebAssembly.csproj",
                "src/Blazor.FileSystemAccess/Blazor.FileSystemAccess.csproj",
                "src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj",
                "src/Blazor.Geolocation/Blazor.Geolocation.csproj",
                "src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj",
                "src/Blazor.LocalStorage/Blazor.LocalStorage.csproj",
                "src/Blazor.MediaDevices.WebAssembly/Blazor.MediaDevices.WebAssembly.csproj",
                "src/Blazor.MediaDevices/Blazor.MediaDevices.csproj",
                "src/Blazor.Notifications.WebAssembly/Blazor.Notifications.WebAssembly.csproj",
                "src/Blazor.Notifications/Blazor.Notifications.csproj",
                "src/Blazor.OfflineStorage.WebAssembly/Blazor.OfflineStorage.WebAssembly.csproj",
                "src/Blazor.OfflineStorage/Blazor.OfflineStorage.csproj",
                "src/Blazor.Performance.WebAssembly/Blazor.Performance.WebAssembly.csproj",
                "src/Blazor.Performance/Blazor.Performance.csproj",
                "src/Blazor.Permissions.WebAssembly/Blazor.Permissions.WebAssembly.csproj",
                "src/Blazor.Permissions/Blazor.Permissions.csproj",
                "src/Blazor.Screen.WebAssembly/Blazor.Screen.WebAssembly.csproj",
                "src/Blazor.Screen/Blazor.Screen.csproj",
                "src/Blazor.Serialization/Blazor.Serialization.csproj",
                "src/Blazor.SessionStorage.WebAssembly/Blazor.SessionStorage.WebAssembly.csproj",
                "src/Blazor.SessionStorage/Blazor.SessionStorage.csproj",
                "src/Blazor.Share.WebAssembly/Blazor.Share.WebAssembly.csproj",
                "src/Blazor.Share/Blazor.Share.csproj",
                "src/Blazor.SourceGenerators/Blazor.SourceGenerators.csproj",
                "src/Blazor.SpeechRecognition.WebAssembly/Blazor.SpeechRecognition.WebAssembly.csproj",
                "src/Blazor.SpeechRecognition/Blazor.SpeechRecognition.csproj",
                "src/Blazor.SpeechSynthesis.WebAssembly/Blazor.SpeechSynthesis.WebAssembly.csproj",
                "src/Blazor.SpeechSynthesis/Blazor.SpeechSynthesis.csproj",
                "src/Blazor.StorageManagement.WebAssembly/Blazor.StorageManagement.WebAssembly.csproj",
                "src/Blazor.StorageManagement/Blazor.StorageManagement.csproj",
                "src/Blazor.WakeLock.WebAssembly/Blazor.WakeLock.WebAssembly.csproj",
                "src/Blazor.WakeLock/Blazor.WakeLock.csproj",
                "src/Blazor.WebCrypto.WebAssembly/Blazor.WebCrypto.WebAssembly.csproj",
                "src/Blazor.WebCrypto/Blazor.WebCrypto.csproj",
                "tests/Blazor.BrowserCoordination.Tests/Blazor.BrowserCoordination.Tests.csproj",
                "tests/Blazor.Clipboard.Tests/Blazor.Clipboard.Tests.csproj",
                "tests/Blazor.Credentials.Tests/Blazor.Credentials.Tests.csproj",
                "tests/Blazor.DOM.Accessors.CompilationTests/Blazor.DOM.Accessors.CompilationTests.csproj",
                "tests/Blazor.DOM.AdvancedTypes.CompilationTests/Blazor.DOM.AdvancedTypes.CompilationTests.csproj",
                "tests/Blazor.DOM.CSharpGenerator.Tests/Blazor.DOM.CSharpGenerator.Tests.csproj",
                "tests/Blazor.DOM.Generic.CompilationTests/Blazor.DOM.Generic.CompilationTests.csproj",
                "tests/Blazor.DOM.GlobalNamespace.CompilationTests/Blazor.DOM.GlobalNamespace.CompilationTests.csproj",
                "tests/Blazor.DOM.NonEventDeferrals.CompilationTests/Blazor.DOM.NonEventDeferrals.CompilationTests.csproj",
                "tests/Blazor.DOM.ProfileRuntime/Blazor.DOM.ProfileRuntime.csproj",
                "tests/Blazor.DOM.ResolvedFailures.CompilationTests/Blazor.DOM.ResolvedFailures.CompilationTests.csproj",
                "tests/Blazor.DOM.Server.CompilationTests/Blazor.DOM.Server.CompilationTests.csproj",
                "tests/Blazor.DOM.SupplementalBrowserApis.CompilationTests/Blazor.DOM.SupplementalBrowserApis.CompilationTests.csproj",
                "tests/Blazor.DOM.Tests/Blazor.DOM.Tests.csproj",
                "tests/Blazor.DOM.TypedEvents.CompilationTests/Blazor.DOM.TypedEvents.CompilationTests.csproj",
                "tests/Blazor.DOM.TypedUnions.CompilationTests/Blazor.DOM.TypedUnions.CompilationTests.csproj",
                "tests/Blazor.DOM.WakeLock.CompilationTests/Blazor.DOM.WakeLock.CompilationTests.csproj",
                "tests/Blazor.DOM.WebAssembly.CompilationTests/Blazor.DOM.WebAssembly.CompilationTests.csproj",
                "tests/Blazor.ExampleConsumer.EndToEndTests/Blazor.ExampleConsumer.EndToEndTests.csproj",
                "tests/Blazor.FileSystemAccess.Tests/Blazor.FileSystemAccess.Tests.csproj",
                "tests/Blazor.OfflineStorage.Tests/Blazor.OfflineStorage.Tests.csproj",
                "tests/Blazor.Performance.Tests/Blazor.Performance.Tests.csproj",
                "tests/Blazor.Screen.Tests/Blazor.Screen.Tests.csproj",
                "tests/Blazor.Share.Tests/Blazor.Share.Tests.csproj",
                "tests/Blazor.SourceGenerators.Tests/Blazor.SourceGenerators.Tests.csproj",
                "tests/Blazor.StorageManagement.Tests/Blazor.StorageManagement.Tests.csproj",
                "tests/Blazor.WakeLock.Tests/Blazor.WakeLock.Tests.csproj",
                "tests/Blazor.WebCrypto.Tests/Blazor.WebCrypto.Tests.csproj",
                "tools/Blazor.DOM.CSharpGenerator/Blazor.DOM.CSharpGenerator.csproj"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tools/Blazor.DOM.TypeScriptModel/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tools/Blazor.DOM.TypeScriptModel/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "98 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 98,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "C#",
              "largest_source_bytes": 816786,
              "source_files_sampled": 429,
              "oversized_source_files": 7
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "C# (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "C#"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "7/429 source files over 60KB",
                "points": 54.1,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 429,
                      "oversized": 7
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "samples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "samples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "samples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "nuget package 'Blazor.Notifications' points at a different repository (https://github.com/vertonghenb/Blazor.Notifications); excluded from ecosystem scoring",
    "Could not fetch nuget package 'Blazor.DOM.WebAssembly' from its registry"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-24T19:02:09.211042Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/i/IEvangelist/blazorators.svg",
  "full_name": "IEvangelist/blazorators",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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