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": 18382, "full_name": "unoplatform/uno", "url": "https://github.com/unoplatform/uno", "description": "Open-source platform for building cross-platform native Mobile, Web, Desktop, and Embedded apps from a single C#/XAML codebase. Work from any IDE/CLI with Hot Reload, Visual Designer, MCPs, and Skills built for modern .NET workflows. 200M+ NuGet downloads.", "ecosystem": "npm", "ecosystems": [ "npm", "nuget" ], "primary_language": "C#", "languages": [ "C#" ], "topics": [ "uno", "uwp", "android", "uno-platform", "roslyn", "xamarin", "webassembly", "windows", "mvvm", "wasm", "mono", "xaml", "cross-platform", "csharp", "macos", "c-sharp", "winui", "linux", "dotnet", "hacktoberfest" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 9982, "forks": 868, "watchers": 188, "monthly_downloads": null, "latest_score": 84, "latest_band": "good", "latest_scanned_at": "2026-07-17T20:26:20.591766Z", "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": 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": 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": 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": "" } ] } }
This project converts TypeScript type declarations into C# representations, and use C# source generators to expose automatic JavaScript interop functionality.
IEvangelist/blazorators 的健康指数为 100 分中的 68 分,处于「中等」区间。 其得分最高的类别是Vitality(74/100),最低的是AI Readiness(60/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。
指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。
每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。
| 注册表 | 软件包 | 版本 | 月下载量 | 版本数 | 最近发布 | 标签 |
|---|---|---|---|---|---|---|
| NuGet | Blazor.DOM | 10.1.0 | - | 1 | 0 天前 | dotnetdotnetcorecsharpblazorserverdominteropjsinterop |
| NuGet | Blazor.Clipboard | 10.1.0 | - | 1 | 0 天前 | dotnetblazorserverdominteropclipboard |
| NuGet | Blazor.Credentials | 10.1.0 | - | 1 | 0 天前 | dotnetblazorserverdominteropcredentialswebauthn |
| NuGet | Blazor.Geolocation | 10.1.0 | - | 19 | 0 天前 | dotnetdotnetcorecsharpblazorserverwasmgeneratorssourcegenroslyn |
| NuGet | Blazor.LocalStorage | 10.1.0 | - | 19 | 0 天前 | dotnetdotnetcorecsharpblazorgeneratorssourcegenroslyn |
| NuGet | Blazor.MediaDevices | 10.1.0 | - | 1 | 0 天前 | dotnetblazorserverdominteropmedia-devicesget-user-mediadisplay-capture |
| NuGet | Blazor.Notifications指向其他仓库——不计分 | 0.2.0 | - | 2 | 2956 天前 | blazornotificationsc#standardcore |
项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?
| 36/36 | 推送新近度 — 最近一次推送于 0 天前 |
| 3.5/36 | 提交节奏 — 52 周中有 5 周有提交 |
| 18/18 | 提交量 — 最近一年 124 次提交 |
| 10/10 | OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10 |
| commits_last_year | 124 |
| human_commit_share | 1 |
| days_since_last_push | 0 |
| active_weeks_last_year | 5 |
| 27/27 | 有发布版本 — 已发布 43 个发布版本 |
| 36/36 | 发布时效 — 最近一次发布版本于 0 天前 |
| 12.6/27 | 发布节奏 — 约每 142 天发布一次 |
| 0/10 | OpenSSF Scorecard:Signed-Releases — 无数据 |
| releases_count | 43 |
| latest_release_tag | 10.1.0 |
| releases_from_tags | 否 |
| days_since_latest_release | 0 |
| mean_days_between_releases | 142 |
项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?
| 42/60 | 星标 — 392 个星标 |
| 12.4/25 | 复刻 — 32 个复刻 |
| 6/15 | 关注者 — 13 位关注者 |
| forks | 32 |
| stars | 392 |
| watchers | 13 |
| growth_state | unverified |
| growth_factor_pct | 100 |
| growth_unverified_reason | no_history |
| 22.5/22.5 | README |
| 22.5/22.5 | 许可证 — 可识别的许可证(MIT) |
| 0/18 | CONTRIBUTING 指南 |
| 13.5/13.5 | 行为准则 |
| 0/7.2 | 议题模板 |
| 0/6.3 | PR 模板 |
| has_readme | 是 |
| has_license | 是 |
| has_contributing | 否 |
| has_issue_template | 否 |
| has_code_of_conduct | 是 |
| has_pull_request_template | 否 |
| 54.6/80 | 累计下载量 — nuget 合计历史 178,869 次下载 |
| 0/20 | 注册表被依赖数 — 该生态系统不报告此项 |
| packages | Blazor.DOM, Blazor.Clipboard, Blazor.Credentials, Blazor.Geolocation, Blazor.LocalStorage, Blazor.MediaDevices |
| dependents | — |
| ecosystems | nuget |
| total_downloads | 178,869 |
| monthly_downloads | — |
项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?
| 9/54 | 巴士系数 — 1 位贡献者贡献了半数提交 |
| 0.6/22.5 | 提交分布 — 头号贡献者编写了 97% 的提交 |
| 8.1/13.5 | 贡献者广度 — 6 位贡献者 |
| 10/10 | OpenSSF Scorecard:Contributors — project has 6 contributing companies or organizations |
| bus_factor | 1 |
| contributors_sampled | 6 |
| top_contributor_share | 0.974 |
| 46.8/46.8 | 议题解决 — 100% 的议题已关闭 |
| 34.5/38.3 | PR 接受 — 已裁定的 PR 中 28/31 已合并 |
| 0/15 | OpenSSF Scorecard:Code-Review — Found 0/28 approved changesets -- score normalized to 0 |
| merged_prs | 28 |
| open_issues | 0 |
| closed_issues | 32 |
| issue_closed_ratio | 1 |
| closed_unmerged_prs | 3 |
| 10/30 | 所有权背书 — 个人(用户)账户 |
| 0/20 | 已验证域名 — 不适用于个人账户 |
| 21.6/25 | 所有者影响力 — IEvangelist 有 1,017 位关注者 |
| 25/25 | 既往记录 — 336 个公开仓库,账户约 12 年 |
| followers | 1,017 |
| owner_type | User |
| is_verified | — |
| owner_login | IEvangelist |
| public_repos | 336 |
| account_age_days | 4,445 |
| 25/25 | 已发布且可解析 — nuget 上有 6 个软件包 |
| 35/35 | 发布时效 — 最近一次发布于 0 天前 |
| 20/20 | 版本历史 — 19 个已发布版本 |
| 20/20 | 未被弃用 — 活跃,未被弃用或撤回 |
| packages | Blazor.DOM, Blazor.Clipboard, Blazor.Credentials, Blazor.Geolocation, Blazor.LocalStorage, Blazor.MediaDevices |
| ecosystems | nuget |
| any_deprecated | 否 |
| min_days_since_publish | 0 |
基础的工程与文档实践是否到位?
| 24/24 | CI 工作流 — 4 个工作流 |
| 24/24 | 存在测试 |
| 0/16 | Linter 配置 |
| 0/9.6 | Pre-commit 钩子 |
| 6.4/6.4 | .editorconfig |
| 14/20 | OpenSSF Scorecard:CI-Tests — 3 out of 4 merged PRs checked by a CI test -- score normalized to 7 |
| has_ci | 是 |
| has_tests | 是 |
| has_editorconfig | 是 |
| has_linter_config | 否 |
| has_precommit_config | 否 |
| 30/30 | README |
| 0/25 | 文档目录 |
| 15/15 | 文档 / 主页站点 — https://ievangelist.github.io/blazorators/ |
| 10/10 | 仓库描述 |
| 10/10 | 主题标签 — 7 个主题标签 |
| 10/10 | Wiki |
| topics | blazor, blazor-webassembly, javascript, typescript, javascript-interop, source-generators, hacktoberfest |
| has_wiki | 是 |
| homepage | https://ievangelist.github.io/blazorators/ |
| has_readme | 是 |
| has_docs_dir | 否 |
| has_description | 是 |
可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?
| 7.5/7.5 | Binary-Artifacts — no binaries found in the repo |
| 0/7.5 | Branch-Protection — 无数据 |
| 1.8/2.5 | CI-Tests — 3 out of 4 merged PRs checked by a CI test -- score normalized to 7 |
| 0/2.5 | CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected |
| 0/7.5 | Code-Review — Found 0/28 approved changesets -- score normalized to 0 |
| 2.5/2.5 | Contributors — project has 6 contributing companies or organizations |
| 10/10 | Dangerous-Workflow — no dangerous workflow patterns detected |
| 0/7.5 | Dependency-Update-Tool — no update tool detected |
| 0/5 | Fuzzing — project is not fuzzed |
| 2.5/2.5 | 许可证 — license file detected |
| 7.5/7.5 | Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10 |
| 5/5 | Packaging — packaging workflow detected |
| 0.5/5 | Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1 |
| 0/5 | SAST — SAST tool is not run on all commits -- score normalized to 0 |
| 5/5 | Security-Policy — security policy file detected |
| 0/7.5 | Signed-Releases — 无数据 |
| 0/7.5 | Token-Permissions — detected GitHub workflow tokens with excessive permissions |
| 6/7.5 | Vulnerabilities — 2 existing vulnerabilities detected |
| source | openssf_scorecard |
| checks_evaluated | 16 |
| scorecard_version | v5.5.0 |
| checks_inconclusive | 2 |
| scorecard_aggregate | 5.4 |
| 35/35 | 直接依赖不含已知公告 — 没有直接依赖携带已知公告 |
| 0/25 | 间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分 |
| 0/40 | 没有长期未处理的公告 — 没有公告带有发布日期 |
| source | osv |
| advisories | 2 |
| affected_packages | 2 |
| assessed_packages | 19 |
| unassessed_packages | 19 |
| affected_by_severity | high 1, moderate 1 |
| direct_affected_packages | 0 |
该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。
| 0/45 | 代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则 |
| 0/15 | 机器可读文档(llms.txt) |
| 40/40 | 可读的提交历史 — 100 次人类提交中有 92 次说明了意图(结构化标题或解释性正文) |
| has_llms_txt | 否 |
| legible_history_share | 0.92 |
| agent_instruction_files | — |
| agent_instruction_max_bytes | — |
| 12.6/18 | 一条命令的引导启动 — samples/Blazor.ExampleConsumer/Blazor.ExampleConsumer.csproj, samples/BlazorServer.ExampleConsumer/BlazorServer.ExampleConsumer.csproj, src/Blazor.BrowserCoordination.WebAssembly/Blazor.BrowserCoordination.WebAssembly.csproj(工具链约定,无任务运行器) |
| 22/22 | 自动化测试 |
| 0/11 | Lint / 格式化配置 |
| 11/11 | 静态类型检查 — tools/Blazor.DOM.TypeScriptModel/tsconfig.json |
| 10/10 | 可复现环境 — lockfile |
| 10/10 | 已体现的代理实践 — 最近 100 次提交中有 98 次由代理编写或署名代理 |
| 0/8 | 自动化维护 — 未观察到自动依赖更新 |
| 1/10 | OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1 |
| has_nix | 否 |
| has_tests | 是 |
| lockfiles | package-lock.json |
| has_dockerfile | 否 |
| typed_language | 是 |
| bootstrap_files | — |
| has_devcontainer | 否 |
| has_linter_config | 否 |
| 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 |
| 45/45 | 可类型检查的代码 — C#(静态类型) |
| 54.1/55 | 可控的文件大小 — 采样的 429 个源文件中有 7 个超过 60KB |
| primary_language | C# |
| largest_source_bytes | 816,786 |
| source_files_sampled | 429 |
| oversized_source_files | 7 |
| 0/40 | API 模式(OpenAPI/GraphQL/proto) |
| 0/20 | MCP 服务器 |
| 40/40 | 可运行示例 — samples |
| example_dirs | samples |
| has_mcp_signal | 否 |
| api_schema_files | — |
每颗 star 和每个 fork 的添加时间,来自 GitHub 并按天汇总。累计增长位于其构成来源——每日新增——的正上方,二者可相互对照:稳定的自然增长与短暂的突增形态截然不同。当这一差别可被衡量时,它会作为增长真实性予以报告。
每个点涵盖 4 天。
来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。
| 10 | Binary-Artifacts | no binaries found in the repo |
| 不适用 | Branch-Protection | 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 |
| 7 | CI-Tests | 3 out of 4 merged PRs checked by a CI test -- score normalized to 7 |
| 0 | CII-Best-Practices | no effort to earn an OpenSSF best practices badge detected |
| 0 | Code-Review | Found 0/28 approved changesets -- score normalized to 0 |
| 10 | Contributors | project has 6 contributing companies or organizations |
| 10 | Dangerous-Workflow | no dangerous workflow patterns detected |
| 0 | Dependency-Update-Tool | no update tool detected |
| 0 | Fuzzing | project is not fuzzed |
| 10 | License | license file detected |
| 10 | Maintained | 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10 |
| 10 | Packaging | packaging workflow detected |
| 1 | Pinned-Dependencies | dependency not pinned by hash detected -- score normalized to 1 |
| 0 | SAST | SAST tool is not run on all commits -- score normalized to 0 |
| 10 | Security-Policy | security policy file detected |
| 不适用 | Signed-Releases | no releases found |
| 0 | Token-Permissions | detected GitHub workflow tokens with excessive permissions |
| 8 | Vulnerabilities | 2 existing vulnerabilities detected |
| 注册表 | 软件包 | 版本约束 | 清单文件 |
|---|---|---|---|
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj |
| NuGet | MinVer | — | src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj |
| NuGet | Microsoft.AspNetCore.Components.WebAssembly | — | src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj |
| NuGet | Microsoft.Extensions.DependencyInjection | — | src/Blazor.DOM.WebAssembly/Blazor.DOM.WebAssembly.csproj |
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.DOM/Blazor.DOM.csproj |
| NuGet | MinVer | — | src/Blazor.DOM/Blazor.DOM.csproj |
| NuGet | Microsoft.AspNetCore.Components.Web | — | src/Blazor.DOM/Blazor.DOM.csproj |
| NuGet | Microsoft.Extensions.DependencyInjection | — | src/Blazor.DOM/Blazor.DOM.csproj |
| NuGet | Microsoft.JSInterop | — | src/Blazor.DOM/Blazor.DOM.csproj |
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj |
| NuGet | MinVer | — | src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj |
| NuGet | Microsoft.AspNetCore.Components.Web | — | src/Blazor.Geolocation.WebAssembly/Blazor.Geolocation.WebAssembly.csproj |
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.Geolocation/Blazor.Geolocation.csproj |
| NuGet | MinVer | — | src/Blazor.Geolocation/Blazor.Geolocation.csproj |
| NuGet | Microsoft.AspNetCore.Components.Web | — | src/Blazor.Geolocation/Blazor.Geolocation.csproj |
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj |
| NuGet | MinVer | — | src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj |
| NuGet | Microsoft.Extensions.DependencyInjection | — | src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj |
| NuGet | Microsoft.Extensions.Primitives | — | src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj |
| NuGet | Microsoft.JSInterop | — | src/Blazor.LocalStorage.WebAssembly/Blazor.LocalStorage.WebAssembly.csproj |
| NuGet | Microsoft.SourceLink.GitHub | — | src/Blazor.LocalStorage/Blazor.LocalStorage.csproj |
| NuGet | MinVer | — | src/Blazor.LocalStorage/Blazor.LocalStorage.csproj |
| NuGet | Microsoft.Extensions.DependencyInjection | — | src/Blazor.LocalStorage/Blazor.LocalStorage.csproj |
| NuGet | Microsoft.Extensions.Primitives | — | src/Blazor.LocalStorage/Blazor.LocalStorage.csproj |
| NuGet | Microsoft.JSInterop | — | src/Blazor.LocalStorage/Blazor.LocalStorage.csproj |
来自 GitHub 依赖图的完整解析依赖集合:7 个直接依赖与 31 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。
| 注册表 | 软件包 | 版本 | 关系 |
|---|---|---|---|
| NuGet | Microsoft.AspNetCore.Components.Web | — | 直接 |
| NuGet | Microsoft.AspNetCore.Components.WebAssembly | — | 直接 |
| NuGet | Microsoft.Extensions.DependencyInjection | — | 直接 |
| NuGet | Microsoft.Extensions.Primitives | — | 直接 |
| NuGet | Microsoft.JSInterop | — | 直接 |
| NuGet | Microsoft.SourceLink.GitHub | — | 直接 |
| NuGet | MinVer | — | 直接 |
| npm | @pagefind/darwin-arm64 | 1.5.0 | 间接 |
| npm | @pagefind/darwin-x64 | 1.5.0 | 间接 |
| npm | @pagefind/freebsd-x64 | 1.5.0 | 间接 |
| npm | @pagefind/linux-arm64 | 1.5.0 | 间接 |
| npm | @pagefind/linux-x64 | 1.5.0 | 间接 |
| npm | @pagefind/windows-arm64 | 1.5.0 | 间接 |
| npm | @pagefind/windows-x64 | 1.5.0 | 间接 |
| npm | @types/node | 26.1.1 | 间接 |
| npm | @webgpu/types | 0.1.71 | 间接 |
| npm | @webref/idl | 3.81.3 | 间接 |
| npm | ajv | 8.17.1 | 间接 |
| npm | fast-deep-equal | 3.1.3 | 间接 |
| npm | fast-uri | 3.1.3 | 间接 |
| npm | json-schema-traverse | 1.0.0 | 间接 |
| npm | pagefind | 1.5.0 | 间接 |
| npm | require-from-string | 2.0.2 | 间接 |
| npm | typescript | 5.9.3 | 间接 |
| npm | undici-types | 8.3.0 | 间接 |
| npm | webidl2 | 24.5.0 | 间接 |
| NuGet | Basic.Reference.Assemblies | — | 间接 |
| NuGet | coverlet.collector | — | 间接 |
| NuGet | Deque.AxeCore.Playwright | — | 间接 |
| NuGet | Humanizer.Core | — | 间接 |
| NuGet | Microsoft.AspNetCore.Components.WebAssembly.DevServer | — | 间接 |
| NuGet | Microsoft.CodeAnalysis.Analyzers | — | 间接 |
| NuGet | Microsoft.CodeAnalysis.CSharp | — | 间接 |
| NuGet | Microsoft.NET.Test.Sdk | — | 间接 |
| NuGet | Microsoft.Playwright | — | 间接 |
| NuGet | System.Reactive.Linq | — | 间接 |
| NuGet | xunit | — | 间接 |
| NuGet | xunit.runner.visualstudio | — | 间接 |
该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 19 个包,其中也包含从不交付的开发与测试版本固定:2 个存在已知公告,0 个为直接依赖。 有 19 个无法评估——没有已解析的版本、生态系统不受支持,或不在所列包清单之内。
| 软件包 | 版本 | 关系 | 严重程度 | 公告数 | 修复版本 |
|---|---|---|---|---|---|
| fast-uri | 3.1.3 | 间接 | 高 | 1 | 4.1.1 |
| ajv | 8.17.1 | 间接 | 中 | 1 | 8.18.0 |
公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。
{
"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"
}