Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
2033 commits
Select commit Hold shift + click to select a range
3fe174e
Round-trip 42 constructor arguments that clones were silently reverting
ooples Aug 11, 2026
9a574bc
chore: restore materializes lazy layers before filtering them out by …
franklinic Aug 11, 2026
2e0881c
chore: phase 0: a real deletion gate — proven to fail without the fix
franklinic Aug 11, 2026
2118ab0
fix(layers): a deferred layer parks its restore instead of rejecting it
Aug 11, 2026
ec75ae5
refactor(layers): move deferred sub-layer construction into the base …
franklinic Aug 11, 2026
9bab6b6
refactor(layers): timeMoEBlockLayer declares its sub-layer shapes ins…
franklinic Aug 11, 2026
24dcacf
fix(nn): getNamedLayerActivations answers for models that are not a s…
franklinic Aug 11, 2026
3a5e8e7
fix(nn): an empty activation map is a failure to answer, not an answer
franklinic Aug 11, 2026
7b43cb2
refactor(layers): layerBase owns the restored-parameter rule, not eac…
franklinic Aug 11, 2026
39c1cdf
feat(generator): declare parameter shapes on the attribute, emit the …
franklinic Aug 11, 2026
0219914
fix(layers): rank-0 placeholders are not supplied parameters; annotat…
franklinic Aug 11, 2026
8962100
feat(layers): annotate the last two lazy layers, completing restore p…
franklinic Aug 11, 2026
e38c49a
fix(layers): carry the parameter layout through the layer round trip
Aug 11, 2026
8b6b992
fix(ci): make model shape conformance deterministic
Aug 11, 2026
eb585d7
fix(ci): harden automated parameter and gradient contracts
Aug 11, 2026
dacaf40
fix(layers): keep composites out of the wholesale restore path
Aug 11, 2026
5afb334
fix(layers): a lazy layer no longer initializes over its own restored…
Aug 12, 2026
eba1211
fix(layers): save values before describing them, and hold a composite…
Aug 12, 2026
0bf1b38
Separate "the harness could not drive the original" from "the copy is…
ooples Aug 12, 2026
c1e7d9e
fix(layers): replay a held restore after initialization, not before it
Aug 12, 2026
424328b
revert(layers): let an unresolved composite throw instead of holding …
Aug 12, 2026
0a82985
feat(clone): refuse the CloneOptions this path does not implement; re…
Aug 12, 2026
8752f91
fix(layers): revive the per-child restore replay in 15 lazy composites
Aug 12, 2026
612cc4b
Copy clone weights tensor-wise, not through a flat vector: 11x on bil…
ooples Aug 12, 2026
346b11a
Record the measurement that rules out shortening the probe
ooples Aug 12, 2026
26f5671
feat(generator): sub-layer input shapes declared on the field, emitte…
franklinic Aug 12, 2026
16124ac
fix(ci): repair generated model behavioral contracts
Aug 12, 2026
1192581
fix(generator): preserve the base-type traversal root
Aug 12, 2026
f76acf7
chore: merge latest master into PR 1789
Aug 12, 2026
2f5d4f1
fix(ci): consume tensor ownership release
Aug 12, 2026
5ee4a2a
fix(parameters): stabilize lazy component restores
Aug 12, 2026
60bb81a
fix(ci): keep segmentation scaffold net471 compatible
Aug 12, 2026
e43cda8
fix(parameters): restore exact lazy layouts
Aug 12, 2026
dc491c2
Merge remote-tracking branch 'origin/fix/green-generated-modelfamily-…
Aug 12, 2026
5e0eef6
fix(parameters): keep lazy layouts allocation free
Aug 12, 2026
6dbd2f2
fix(parameters): complete lazy adapter and layout contracts
Aug 12, 2026
a1b7d65
fix(clone): let copy-on-write materialize any lazy layer, not just th…
Aug 12, 2026
ddb58d0
fix: complete inherited and lazy parameter manifests
Aug 12, 2026
17ae8b3
merge: bring #2004's newer clone work into the branch
Aug 12, 2026
8371de7
fix(merge): keep #1789's CRNN compliance and #2004's materialize change
Aug 12, 2026
67774bd
test: shard the parameter-count sweep for timeout headroom (#118)
franklinic Aug 12, 2026
ec8df23
The clone plan records a model's constructor, so the base can rebuild it
ooples Aug 12, 2026
8a81dca
fix: fastText uses one word+subword input matrix, per the paper (#121)
franklinic Aug 12, 2026
7f61e07
Delete 336 clone overrides the base class reproduces, and gate the re…
ooples Aug 12, 2026
a4a658c
ADN0058 must not fire on an override that is mandatory
ooples Aug 12, 2026
c37a265
perf(adam): copy previousM/previousV in place instead of per-step all…
franklinic Aug 12, 2026
0eb359c
perf(optimizers): fuse the Adam and AdamW updates into one in-place pass
franklinic Aug 12, 2026
4df02de
perf(optimizers): fuse Adagrad, Lion and Nadam updates into one in-pl…
franklinic Aug 12, 2026
a6f7f5e
feat: add generated tensor domain contracts
Aug 12, 2026
e2b43e7
fix: automate model tensor domain contracts
Aug 12, 2026
bb83061
feat: diagnose invalid tensor contract geometry
Aug 12, 2026
322ca74
test: generate bounded FastText conformance fixture
Aug 12, 2026
0957183
perf(optimizers): fuse AdaMax and AdaDelta updates into one in-place …
franklinic Aug 12, 2026
63cdd2a
ci: split generated layers g-i into two shards
Aug 12, 2026
a7d3d0f
perf(gradients): assemble the gradient vector in one allocation
Aug 12, 2026
85e0d36
fix(gradients): enumerate parameter chunks once when assembling gradi…
Aug 12, 2026
cd37b74
perf(optimizers): finish fused adaptive vector updates
franklinic Aug 12, 2026
0c54a62
perf(optimizers): fuse remaining vector updates
franklinic Aug 12, 2026
9d6336c
Choose the constructor from what the instance holds, not from what is…
ooples Aug 12, 2026
e6233fa
fix(optimizers): support Adam8Bit on net471
franklinic Aug 12, 2026
37b56c5
fix(gan): resolve generator lazy shapes from the generator's own arch…
Aug 12, 2026
72bd4d4
fix(seaco): size the bias embedding for the appended no-bias slot
Aug 12, 2026
88e4a53
Source a constructor argument by unique type, and default what nothin…
ooples Aug 12, 2026
45c39d6
test: route the two remaining timing-out vlm scaffolds to the heavy lane
Aug 12, 2026
86bc6c2
Source a constructor argument by name suffix, preferring the most-der…
ooples Aug 12, 2026
33d27c6
test(tools): add the allocation probe used to locate the backward all…
Aug 12, 2026
6516561
fix(parameters): automate explicit parameter state semantics
Aug 12, 2026
8f33458
fix(generators): remove dead parameter discovery remnants
Aug 12, 2026
7320074
fix(tests): restore valid UTF-8 in VAE aliasing test
Aug 13, 2026
9d2e713
Automate model input contracts
Aug 13, 2026
cd3a20c
fix(diffusion): preserve U-Net clone state
Aug 13, 2026
7feb22e
Make ReinforcementLearningTestBase generic so its 51 suites can run a…
franklinic Aug 12, 2026
f870642
Make tabular parameter surfaces complete before forward
franklinic Aug 12, 2026
d201860
Restore checkpoints into extra trainable layers
franklinic Aug 12, 2026
f7690b7
Test anomaly scores through their continuous API
franklinic Aug 12, 2026
4f72ac8
Make float scaffold exclusions override every opt-in
franklinic Aug 12, 2026
8eede5c
Run single-input layer scaffolds at float precision
franklinic Aug 12, 2026
77aea60
Run generated activation tests at float precision
franklinic Aug 12, 2026
f3e45c9
Run pointwise loss scaffolds at float precision
franklinic Aug 12, 2026
00fa99d
Run specialized loss scaffolds at float precision
franklinic Aug 12, 2026
2e75857
Run graph layer scaffolds at float precision
franklinic Aug 12, 2026
7eb9615
Run multi-input layer scaffolds at float precision
franklinic Aug 12, 2026
5237721
Run distillation strategy scaffolds at float precision
franklinic Aug 12, 2026
67cd7b1
Run active learning scaffolds at float precision
franklinic Aug 12, 2026
31fb650
Run continual learning scaffolds at float precision
franklinic Aug 12, 2026
30c1889
Run causal model scaffolds at float precision
franklinic Aug 12, 2026
2400522
Run survival and multi-label scaffolds at float precision
franklinic Aug 12, 2026
17322d6
Run sequence labeling NER scaffold at float precision
franklinic Aug 12, 2026
6854dc5
Run regression scaffolds at float precision
franklinic Aug 12, 2026
b41173a
Run classification scaffolds at float precision
franklinic Aug 12, 2026
6a3ee44
Run causal discovery scaffolds at float precision
franklinic Aug 12, 2026
9f00b7a
Integrate generic layer tests with current parameter checks
franklinic Aug 13, 2026
707a6bb
TabPFN gets a parameter surface at all, and it immediately caught two…
franklinic Aug 11, 2026
ad9f0a2
Size TabPFN's sub-layers from dimensions the model already knew
franklinic Aug 11, 2026
51e4624
Seven Tabular families could report a parameter count and nothing cou…
franklinic Aug 12, 2026
e6640c9
Reading a count rebuilt the entire layout, and TabR had no restore pa…
franklinic Aug 12, 2026
59283c1
Fix registry integration after parameter surface transplant
franklinic Aug 13, 2026
2d5edbb
Use canonical stable IDs for tabular parameter surfaces
franklinic Aug 13, 2026
af5839f
Merge #1789 into the clone-automation branch
ooples Aug 13, 2026
64f7dcb
Port the all-layers clone sweep onto the surviving Clone, drop one re…
ooples Aug 13, 2026
b695b62
Keep copy-on-write layer cloning working against the generated factory
ooples Aug 13, 2026
26d1183
Fix 85 models that stack-overflowed on Clone()
ooples Aug 13, 2026
e60369e
Carry the resolved shape in the layer payload so a restore survives i…
ooples Aug 13, 2026
7e8ef1c
Let the analyzer own the forwarder class instead of a one-off script
ooples Aug 13, 2026
9a08552
Persist registered buffers from the base, so layers stop hand-writing…
ooples Aug 13, 2026
da8ad42
ADN0060: hand-written serialization is a build error
ooples Aug 13, 2026
513b166
ModelBase serializes declared state; first slice of the ADN0060 backlog
ooples Aug 13, 2026
d1677f1
ModelStateRegistry: the declared home for state that is not a paramet…
ooples Aug 13, 2026
6e092cb
Give all 24 remaining model bases the declared-state registry
ooples Aug 13, 2026
930ef6f
Call the state envelope from every model base's own Serialize/Deseria…
ooples Aug 13, 2026
35c3217
Fix a clone-registry race that silently downgraded verified plans, an…
ooples Aug 13, 2026
1d6f964
Declare the naive Bayes family's state; ADN0060 282 -> 272
ooples Aug 13, 2026
cbc833f
Declare the tree-ensemble family; undo 17 Regression deletions the ea…
ooples Aug 13, 2026
8c6c72a
Match a recorded constructor by arity, not by re-deriving names the p…
ooples Aug 14, 2026
728e3e2
Let a model declare a node graph, and declare the decision tree with it
ooples Aug 14, 2026
57571cf
Delete 30 Classification overrides the base now covers; ADN0060 302 -…
ooples Aug 14, 2026
189b9fe
Correct the record: the decision tree's hand-written serializer was n…
ooples Aug 14, 2026
ad400e2
ModelStateGenerator: the model declares nothing, the generator writes it
ooples Aug 14, 2026
f11d9c2
Revert "ModelStateGenerator: the model declares nothing, the generato…
ooples Aug 14, 2026
c4ff778
Revert "Revert "ModelStateGenerator: the model declares nothing, the …
ooples Aug 14, 2026
40fdc4b
Land ModelStateGenerator: 150 models get their state declarations wri…
ooples Aug 14, 2026
fc4fe23
LOESS: use the paper's span, not one global bandwidth
ooples Aug 14, 2026
921ad2f
NonLinearRegressionBase.DeepCopy goes through the payload instead of …
ooples Aug 14, 2026
7793daa
ADN0058 recognises the clone override shapes that actually exist, not…
ooples Aug 14, 2026
e4827b4
Delete 607 clone overrides the base reproduces, and close the three b…
ooples Aug 14, 2026
422d692
A clone stops sharing its sub-modules with the model it was copied fr…
ooples Aug 14, 2026
24a98aa
Delete the 120 clone overrides that only construct and then move para…
ooples Aug 14, 2026
09bcf94
Model state is persisted by default; a member now has to say why it s…
ooples Aug 14, 2026
82697e8
The state generator handles nested models, and ADN0061 names the type…
ooples Aug 14, 2026
9ad7b32
Decision trees and ensembles declare their state, so 42 hand-written …
ooples Aug 14, 2026
6845c7f
LocallyWeighted carries its span and bandwidth as model state, per th…
ooples Aug 14, 2026
8a88b7e
A restored child list grows to fit the payload instead of dropping it
ooples Aug 14, 2026
01a7282
Delete the ADN0060 pairs across Diffusion, NeuralNetworks and Optimiz…
ooples Aug 15, 2026
803de93
DeferredRestoreGateTests and its fixture are partial, so the test pro…
ooples Aug 15, 2026
e218753
A resolved output shape matches a flat OutputSize when its dimensions…
ooples Aug 15, 2026
03d92e1
WanVideoModel keeps its clone, because a fresh TemporalVAE has nothin…
ooples Aug 15, 2026
054121e
merge: bring latest master into #2004
Aug 16, 2026
36cf1b0
fix(clone): repair the master merge and finish the ADN0060 backlog
Aug 16, 2026
c4021ba
fix(serialization): consult the factory registry when deserializing a…
Aug 16, 2026
b306e13
fix(layers): derive ParametersAreConstructionSized instead of writing…
Aug 16, 2026
6864ce4
feat(generator): infer layer construction state instead of requiring …
Aug 17, 2026
950381d
refactor(serialization): remove the null-forgiving operator from the …
Aug 17, 2026
d67111f
refactor(serialization): annotate LayerStateBag.TryRaw instead of sup…
Aug 17, 2026
0746e3c
fix(generator): do not infer Component parameters as construction state
Aug 17, 2026
12c2d1c
fix(layers): a composite defers its restore while its children are pl…
Aug 17, 2026
8dbb5f5
fix(layers): key the child check on allocation, not on IsShapeResolved
Aug 17, 2026
33eab85
Revert "a composite defers its restore while its children are placeho…
Aug 17, 2026
65709fb
fix(generators): preserve nullable symbol contracts
Aug 17, 2026
bab7e36
merge: bring the collaborator's nullable-contract fix into the clone …
Aug 17, 2026
f5a7503
fix(parameters): infer fit availability for buffers with no construct…
Aug 17, 2026
24d141c
fix(layers): finish a shape-only resolution before reading the parame…
Aug 17, 2026
6c05092
fix(clone): capture activation functions in inferred layer state
Aug 17, 2026
6cccdf6
fix(serialization): restore a layer from its saved shape in the rank …
Aug 17, 2026
ead9fbe
fix(diffusion): copy weights chunk-by-chunk instead of through a 2 GB…
Aug 17, 2026
3739ab7
fix: restore parameter state chunks through a writable state surface
Aug 17, 2026
2109df6
refactor: delete sixteen redundant diffusion model clone overrides
Aug 17, 2026
e809991
fix: make adn0058 catch the clone override shape that drops state
Aug 17, 2026
8864185
refactor: delete the remaining diffusion clone overrides
Aug 17, 2026
ab5619e
fix: stop the clone plan refusing a property and its own backing field
Aug 17, 2026
b6c2cbe
fix: source a constructor argument stored under a trailing qualifier
Aug 17, 2026
ea8eb07
fix: let the clone plan read inputtype back off the architecture
Aug 17, 2026
0b77710
fix: source an argument a member holds more generally
Aug 17, 2026
4458136
fix: stop the type fallback counting a property and its field twice
Aug 17, 2026
59d736b
fix: resolve a constructor as a whole instead of parameter by parameter
Aug 17, 2026
6830383
fix: store the last constructor arguments three models were dropping
Aug 17, 2026
4ff1c69
fix: rebuild the last two models from their own state
Aug 17, 2026
0e6b5eb
fix: build a restore child through its all-optional constructor
Aug 17, 2026
4eb7b63
fix: let the clone fallback see an all-optional constructor too
Aug 17, 2026
df11eac
feat: carry a model's scalar settings in its serialized state
Aug 17, 2026
33c34a4
Merge branch 'master' into feat/1993-automated-clone
ooples Aug 17, 2026
09d68e4
fix: persist the settings a model predicts with
Aug 17, 2026
90c2655
fix: let the state generator reach the class that declares its hook
Aug 17, 2026
dc5836c
feat: carry a decision tree as declared state
Aug 18, 2026
20a9146
fix: stop the async tree base overwriting its restored tree
Aug 18, 2026
b6d608c
Merge remote-tracking branch 'origin/feat/1993-automated-clone' into …
Aug 18, 2026
27ec074
fix: stream weights when saving state instead of flattening them
Aug 18, 2026
e716f56
fix: report layers that fail to load instead of dropping them
Aug 18, 2026
6d30222
fix: rebuild layers through the constructor that restores the most state
Aug 18, 2026
e479048
fix: omit construction state a lazily-shaped layer has not resolved yet
Aug 18, 2026
b6095ce
fix: carry set-abstraction branch weights in the parameter surface
Aug 18, 2026
d9c5a05
feat: let time series models declare their state instead of serializi…
Aug 18, 2026
6cfb1b1
merge: bring in origin/master (#2006) and delete the clone overrides …
Aug 18, 2026
b0ecca4
feat: stop forcing every neural network to hand-write its serialization
Aug 18, 2026
7f3a332
refactor: delete hand-written serialization from 11 networks
Aug 18, 2026
1d274e2
refactor: delete the hand-written serialization the base already perf…
Aug 18, 2026
44a9dca
refactor: classify the tensor fields that are not parameters
Aug 18, 2026
cf943c9
refactor: declare the recomputed and cross-step tensor fields
Aug 18, 2026
3879976
refactor: declare the state that fitting produces
Aug 18, 2026
c1baf81
refactor: declare the remaining recomputed, cross-step and fitted fields
Aug 18, 2026
8819e7b
refactor: declare the weights that were never declared
Aug 18, 2026
685cbac
refactor: split the held-back fields by what they actually hold
Aug 18, 2026
69709af
refactor: complete the half-declared weight groups
Aug 18, 2026
1903705
refactor: declare layer gradients, caches and optimizer moments
Aug 18, 2026
528e808
refactor: declare fused weight caches and recurrent sequence state
Aug 18, 2026
7c58aa0
feat: persist the graph a graph layer was given
Aug 18, 2026
f5cffb6
refactor: let the generator own DuelingCombinationLayer's weights
Aug 18, 2026
e86c8fd
refactor: let the generator own NoisyDenseLayer's weights
Aug 18, 2026
598fc8a
refactor: let the generator own BayesianDenseLayer's weights
Aug 18, 2026
d451642
test: prove a restored parameter vector reproduces the prediction
Aug 18, 2026
5de90fc
refactor: let the generator own three more layers' parameters
Aug 18, 2026
2fa1ad1
fix: stop five tabular regression heads resolving to relu
Aug 18, 2026
53e1439
fix: stop two composites counting their children twice
Aug 18, 2026
4e1e933
fix: stop two more composites counting their children twice
Aug 19, 2026
f0b21ab
fix: declare cloze attention's projection widths so the count sees them
Aug 19, 2026
4ffabf9
test: measure the layers that declare their own constructor widths
Aug 19, 2026
fecedae
test: replay the whole declaration language, not just numeric arguments
Aug 19, 2026
0d2747d
fix(layers): make the declared sub-layer width reach the parameter su…
Aug 19, 2026
fd9e33c
fix(layers): declare child widths for three more composites
Aug 19, 2026
2b278c3
fix(layers): count the children a composite holds in a collection
Aug 19, 2026
7cacdb5
fix(generators): let a layer with buffers infer its deferred input width
Aug 19, 2026
6ff2b99
test: drive each layer before comparing its parameter surfaces
Aug 19, 2026
022f97b
fix(layers): size the temporal module and reconnect the generator's i…
Aug 19, 2026
b814cb5
test: reach the layers the scaffold generator never generated
Aug 19, 2026
198a8b9
feat(generators): report the layers the scaffold cannot generate (AID…
Aug 19, 2026
671661a
test(layers): declare scaffold arguments for nine unscaffoldable layers
Aug 19, 2026
50b3e3f
Merge remote-tracking branch 'origin/master' into land
Aug 19, 2026
1051272
fix(optimizers): rebuild the proximal operator when its options move
Aug 19, 2026
d73bbc2
fix(generators): let a declared width reach children held in a collec…
Aug 19, 2026
2b2383d
fix: restore blocks whose input declares a free axis, and green the c…
Aug 19, 2026
7cf5279
fix(layers): let a partial declaration coexist with chained sizing
Aug 19, 2026
6564dfb
fix(autodiff): stop an identity function adding its gradient to itself
Aug 19, 2026
5256577
fix(layers): scaffold six more layers and fix what that exposed
Aug 20, 2026
a721700
fix(layers): do not chain children while a declaration is still being…
Aug 20, 2026
b2f4f11
fix(layers): keep spectral normalization's own weights and iteration …
Aug 20, 2026
8aeb3d3
refactor(layers): normalize spectral weights on the tape, not by muta…
Aug 20, 2026
2c5931f
fix(layers): seed spectral iteration so sigma means something before …
Aug 20, 2026
8cd7097
fix(layers): use the implicit-broadcast divide and correct a wrong at…
Aug 20, 2026
9aa2b9a
fix(vad): put the audio into the frame tensor the model scores
franklinic Aug 20, 2026
58fa3f3
ci: cover rowparallellinear with a shard filter
Aug 20, 2026
3246fec
fix(audio): give silerovad's frame tensors their samples, and dispose…
Aug 20, 2026
efdde6c
feat(params): persist input-sized fitted state without counting it
Aug 20, 2026
79bd50b
fix(graph): mark the graph tensors input-sized, and stop training one
Aug 20, 2026
2d7ef8f
fix(params): append the new slot role, and classify link prediction's…
Aug 20, 2026
72824b7
Merge remote-tracking branch 'origin/feat/1993-automated-clone' into …
Aug 20, 2026
e258d28
Merge remote-tracking branch 'origin/master' into codex/pr2004-update
franklinic Aug 20, 2026
20da139
fix: restore generated clone and parameter lifecycle
Aug 20, 2026
bf0d326
fix: close PR 2004 clone and serialization regressions
Aug 21, 2026
1a85906
fix(clone): complete automated clone acceptance criteria
Aug 22, 2026
4a1d022
fix(clone): close generated lifecycle regressions with CI proof
Aug 22, 2026
c032ddd
Merge remote-tracking branch 'origin/master' into agent/pr2004-analysis
Aug 22, 2026
de55b75
refactor(clone): enforce generated model lifecycle
Aug 22, 2026
72eaff9
chore(merge): update PR 2004 from master
Aug 23, 2026
7c2c3db
Fix generated clone and serialization regressions
Aug 23, 2026
e8fc8ef
Merge master and resolve PR #2004 conflicts
Aug 23, 2026
feab62b
fix: centralize clone topology restoration
Aug 24, 2026
52fed43
Merge remote-tracking branch 'origin/master' into fix2004
franklinic Aug 24, 2026
b1e767f
chore: merge master into feat/1993-automated-clone
Aug 24, 2026
2cc7afa
chore: integrate concurrent PR update
Aug 24, 2026
e11b664
fix(generators): eliminate repeated semantic scans
Aug 24, 2026
8eeffc7
Merge branch 'master' into feat/1993-automated-clone
ooples Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,23 @@ csharp_space_between_square_brackets = false
# License header
file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.

# ADN0057 is informational for NuGet consumers, whose custom initialization-only constructor
# arguments may be intentional. In this repository it is an acceptance gate: every shipped layer
# must either preserve the value or classify its entropy semantics explicitly.
dotnet_diagnostic.ADN0057.severity = error

# Concrete models and layers in the shipped source must use generated/base lifecycle plumbing.
# The analyzer remains informational for external consumers, whose own base contracts may require
# an override; this repository raises it to an acceptance error.
dotnet_diagnostic.ADN0063.severity = error

# Dedicated test doubles deliberately override parameter surfaces to simulate malformed,
# throwing, or streaming implementations. Production descriptors remain compiler errors; this
# explicit path-scoped policy keeps those fixtures buildable without an assembly-name heuristic.
[tests/AiDotNet.Tests/**/*.cs]
dotnet_diagnostic.AIDN081.severity = warning
dotnet_diagnostic.AIDN082.severity = warning
dotnet_diagnostic.ADN0063.severity = warning

[src/libraries/System.Net.Http/src/System/Net/Http/{SocketsHttpHandler/Http3RequestStream.cs,BrowserHttpHandler/BrowserHttpHandler.cs}]
# disable CA2025, the analyzer throws a NullReferenceException when processing this file: https://github.com/dotnet/roslyn-analyzers/issues/7652
Expand Down
108 changes: 108 additions & 0 deletions .github/scripts/find-pr-new-failures.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<#
.SYNOPSIS
Builds a VSTest filter for failures present in a PR shard but absent from the exact master baseline.

.DESCRIPTION
This is deliberately a retry selector, not a verdict engine. It reads the initial shard TRX and
either the compact baseline ledger or the legacy baseline TRX, writes the candidate inventory, and
publishes rerun_count/filter outputs. The aggregate analyzer consumes both the original and retry
TRX and owns the final policy decision.
#>

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string] $CurrentResultsPath,
[string] $BaselineResultsPath,
[string] $BaselineLedgerPath,
[Parameter(Mandatory = $true)]
[string] $OutputFile
)

$ErrorActionPreference = 'Stop'

function Get-TrxResults {
param([string] $Root)

$results = New-Object System.Collections.Generic.List[object]
foreach ($trx in @(Get-ChildItem -LiteralPath $Root -Recurse -Filter '*.trx' -File -ErrorAction SilentlyContinue)) {
[xml] $document = Get-Content -LiteralPath $trx.FullName -Raw
$definitions = @{}
foreach ($unitTest in @($document.SelectNodes('//*[local-name()="UnitTest"]'))) {
$method = $unitTest.SelectSingleNode('./*[local-name()="TestMethod"]')
if ($method -and $unitTest.id) {
$className = [string] $method.className
$methodName = [string] $method.name
$definitions[[string] $unitTest.id] = if ($className) {
"$className.$methodName"
} else { $methodName }
}
}

foreach ($result in @($document.SelectNodes('//*[local-name()="UnitTestResult"]'))) {
$display = [string] $result.testName
$fullyQualified = $definitions[[string] $result.testId]
if ([string]::IsNullOrWhiteSpace($fullyQualified)) { $fullyQualified = $display }
$identity = if ($display -and $display -ne $fullyQualified) {
"$fullyQualified::$display"
} else { $fullyQualified }
if (-not [string]::IsNullOrWhiteSpace($identity)) {
$results.Add([PSCustomObject]@{
identity = $identity
fullyQualifiedName = $fullyQualified
displayName = $display
outcome = [string] $result.outcome
})
}
}
}
return $results.ToArray()
}

function Set-ActionOutput {
param([string] $Name, [string] $Value)
Write-Host "$Name=$Value"
if ($env:GITHUB_OUTPUT) { Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "$Name=$Value" }
}

if (-not (Test-Path -LiteralPath $CurrentResultsPath)) {
throw "Current result directory not found: $CurrentResultsPath"
}

$current = @(Get-TrxResults $CurrentResultsPath)
$baseline = if ($BaselineLedgerPath) {
if (-not (Test-Path -LiteralPath $BaselineLedgerPath)) {
throw "Baseline ledger not found: $BaselineLedgerPath"
}
@((Get-Content -LiteralPath $BaselineLedgerPath -Raw | ConvertFrom-Json).tests)
} elseif ($BaselineResultsPath) {
if (-not (Test-Path -LiteralPath $BaselineResultsPath)) {
throw "Baseline result directory not found: $BaselineResultsPath"
}
@(Get-TrxResults $BaselineResultsPath)
} else {
throw 'BaselineLedgerPath or BaselineResultsPath is required.'
}

$baselineFailures = New-Object System.Collections.Generic.HashSet[string]([StringComparer]::Ordinal)
foreach ($failure in @($baseline | Where-Object outcome -eq 'Failed')) {
[void] $baselineFailures.Add([string] $failure.identity)
}

$candidates = @($current |
Where-Object { $_.outcome -eq 'Failed' -and -not $baselineFailures.Contains([string] $_.identity) } |
Sort-Object identity -Unique)
$methods = @($candidates.fullyQualifiedName | Where-Object { $_ } | Sort-Object -Unique)
$filterParts = @($methods | ForEach-Object { "FullyQualifiedName=$_" })
$filter = $filterParts -join '|'

$outputParent = Split-Path -Parent $OutputFile
if ($outputParent) { New-Item -Path $outputParent -ItemType Directory -Force | Out-Null }
[PSCustomObject]@{
candidateCount = $candidates.Count
methodCount = $methods.Count
candidates = $candidates
} | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $OutputFile -Encoding utf8

Set-ActionOutput 'rerun_count' ([string] $methods.Count)
Set-ActionOutput 'filter' $filter
73 changes: 73 additions & 0 deletions .github/scripts/find-test-baseline.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<#
.SYNOPSIS
Finds the exact Actions run/artifact that represents a pull request's base SHA.

.DESCRIPTION
Prefers the compact TRX ledger emitted by the aggregate job. For the first run
after this feature is introduced, falls back to the legacy coverage/TRX artifacts
from the exact master SHA so the rollout does not require a manual baseline.
#>

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string] $BaseSha,
[string] $Repository = $env:GITHUB_REPOSITORY,
[string] $Workflow = 'sonarcloud.yml',
[string] $ShardSlug
)

$ErrorActionPreference = 'Stop'
if (-not $Repository) { throw 'Repository is required (owner/name).' }
if (-not $env:GITHUB_STEP_SUMMARY -and -not $env:GITHUB_OUTPUT) {
Write-Verbose 'Running outside Actions; outputs will be written to the console only.'
}

function Invoke-GhJson {
param([string] $Endpoint)
$raw = & gh api $Endpoint
if ($LASTEXITCODE -ne 0) { throw "gh api failed for '$Endpoint'." }
return $raw | ConvertFrom-Json
}

function Set-ActionOutput {
param([string] $Name, [string] $Value)
Write-Host "$Name=$Value"
if ($env:GITHUB_OUTPUT) { Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "$Name=$Value" }
}

$artifactName = "test-outcome-ledger-$BaseSha"
$encodedName = [Uri]::EscapeDataString($artifactName)
$artifactResponse = Invoke-GhJson "repos/$Repository/actions/artifacts?name=$encodedName&per_page=100"
$ledgerArtifact = @($artifactResponse.artifacts |
Where-Object {
-not $_.expired -and $_.name -eq $artifactName -and
$_.workflow_run -and $_.workflow_run.head_sha -eq $BaseSha
} |
Sort-Object created_at -Descending | Select-Object -First 1)

if ($ledgerArtifact.Count -gt 0) {
Set-ActionOutput 'baseline_mode' 'ledger'
Set-ActionOutput 'baseline_run_id' ([string] $ledgerArtifact[0].workflow_run.id)
Set-ActionOutput 'baseline_sha' $BaseSha
if ($ShardSlug) { Set-ActionOutput 'baseline_artifact_name' $artifactName }
exit 0
}

# Bootstrap path: this base SHA predates compact ledgers. Locate the exact push
# run and let download-artifact fetch its coverage-<sha>-* artifacts. Conclusion
# is intentionally unrestricted: master workflows can be cancelled by CodeQL
# after every test shard has already uploaded a valid TRX.
$encodedWorkflow = [Uri]::EscapeDataString($Workflow)
$runs = Invoke-GhJson "repos/$Repository/actions/workflows/$encodedWorkflow/runs?head_sha=$BaseSha&event=push&per_page=100"
$run = @($runs.workflow_runs |
Where-Object { $_.head_sha -eq $BaseSha -and $_.status -eq 'completed' } |
Sort-Object run_attempt, created_at -Descending | Select-Object -First 1)
if ($run.Count -eq 0) {
throw "No completed '$Workflow' push run exists for exact baseline SHA $BaseSha."
}

Set-ActionOutput 'baseline_mode' 'trx'
Set-ActionOutput 'baseline_run_id' ([string] $run[0].id)
Set-ActionOutput 'baseline_sha' $BaseSha
if ($ShardSlug) { Set-ActionOutput 'baseline_artifact_name' "coverage-$BaseSha-$ShardSlug" }
158 changes: 158 additions & 0 deletions .github/scripts/report-test-totals.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Report aggregate test totals across every shard artifact downloaded by CI.
#
# This is a reporter, not a gate. It always exits zero and writes stable outputs for the CI Gate.
# Counts are explicitly labelled as a floor when a TRX is missing/unreadable, a blame-hang sequence
# is present, or the TRX counters show that not every discovered test executed.

[CmdletBinding()]
param(
[string]$ResultsPath = 'TestResults',
[string]$WorkflowPath = '.github/workflows/sonarcloud.yml',
[int]$ExpectedShardCount = 0
)

$ErrorActionPreference = 'Stop'

function Add-Summary {
param([string]$Line)
Write-Host $Line
if ($env:GITHUB_STEP_SUMMARY) {
try { Add-Content -LiteralPath $env:GITHUB_STEP_SUMMARY -Value $Line -ErrorAction Stop }
catch { Write-Host "::warning::Could not append aggregate test totals to the step summary: $($_.Exception.Message)" }
}
}

function Set-CiOutput {
param([string]$Name, [string]$Value)
if ($env:GITHUB_OUTPUT) {
try { Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "$Name=$Value" -ErrorAction Stop }
catch { Write-Host "::warning::Could not write aggregate output '$Name': $($_.Exception.Message)" }
}
}

$body = {
$expectedShards = $ExpectedShardCount
if ($expectedShards -le 0 -and (Test-Path -LiteralPath $WorkflowPath)) {
# Keep this self-updating with the matrix instead of hard-coding 110. Job keys are indented
# two spaces and shard entries ten, so the next job key closes the section unambiguously.
$insideShardedJob = $false
foreach ($line in Get-Content -LiteralPath $WorkflowPath) {
if ($line -match '^ test-net10-sharded:\s*$') {
$insideShardedJob = $true
continue
}
if ($insideShardedJob -and $line -match '^ [A-Za-z0-9_-]+:\s*$') { break }
if ($insideShardedJob -and $line -match '^ - name:\s+') { $expectedShards++ }
}
}

$trxFiles = @(Get-ChildItem -LiteralPath $ResultsPath -Recurse -Filter '*.trx' -ErrorAction SilentlyContinue)
$sequenceFiles = @(Get-ChildItem -LiteralPath $ResultsPath -Recurse -Filter 'Sequence_*.xml' -ErrorAction SilentlyContinue)
$failedOccurrences = 0
$failedNames = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
$hangVictims = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
$unparseableTrx = [System.Collections.Generic.List[string]]::new()
$unparseableSequence = [System.Collections.Generic.List[string]]::new()
$executed = 0
$discovered = 0
$missingCounters = 0

foreach ($trx in $trxFiles) {
try {
[xml]$document = Get-Content -LiteralPath $trx.FullName -Raw
$failures = @($document.SelectNodes("//*[local-name()='UnitTestResult' and @outcome='Failed']"))
$failedOccurrences += $failures.Count
foreach ($failure in $failures) {
$name = [string]$failure.testName
if (-not [string]::IsNullOrWhiteSpace($name)) { [void]$failedNames.Add($name) }
}

$counters = $document.SelectSingleNode("//*[local-name()='Counters']")
if ($counters) {
$executed += [int]$counters.executed
$discovered += [int]$counters.total
} else {
$missingCounters++
}
} catch {
$unparseableTrx.Add("$($trx.FullName): $($_.Exception.Message)")
}
}

foreach ($sequence in $sequenceFiles) {
try {
[xml]$document = Get-Content -LiteralPath $sequence.FullName -Raw
$elements = @($document.SelectNodes("//*[local-name()='UnitTestElement']"))
if ($elements.Count -eq 0) { continue }
$last = $elements[$elements.Count - 1]
$name = [string]$last.FullyQualifiedName
if ([string]::IsNullOrWhiteSpace($name)) { $name = [string]$last.InnerText }
if (-not [string]::IsNullOrWhiteSpace($name)) { [void]$hangVictims.Add($name.Trim()) }
} catch {
$unparseableSequence.Add("$($sequence.FullName): $($_.Exception.Message)")
}
}

# A blame-hang victim normally has no failed TRX row because the host was killed while it ran.
# Count only victims not already present so the aggregate matches the normalized baseline logic.
$additionalHangFailures = 0
foreach ($victim in $hangVictims) {
if ($failedNames.Add($victim)) { $additionalHangFailures++ }
}

$knownFailures = $failedOccurrences + $additionalHangFailures
$incomplete = $trxFiles.Count -eq 0 -or $expectedShards -le 0 -or
$trxFiles.Count -ne $expectedShards -or $unparseableTrx.Count -gt 0 -or
$unparseableSequence.Count -gt 0 -or
$missingCounters -gt 0 -or $hangVictims.Count -gt 0 -or
($discovered -gt 0 -and $executed -lt $discovered)

$failureOutput = if ($trxFiles.Count -eq 0) { 'unknown' } else { [string]$knownFailures }
$distinctOutput = if ($trxFiles.Count -eq 0) { 'unknown' } else { [string]$failedNames.Count }
$expectedShardOutput = if ($expectedShards -gt 0) { [string]$expectedShards } else { 'unknown' }
Set-CiOutput 'failed_test_occurrences' $failureOutput
Set-CiOutput 'distinct_failing_tests' $distinctOutput
Set-CiOutput 'executed_tests' ([string]$executed)
Set-CiOutput 'discovered_tests' ([string]$discovered)
Set-CiOutput 'reported_shards' ([string]$trxFiles.Count)
Set-CiOutput 'expected_shards' $expectedShardOutput
Set-CiOutput 'test_totals_incomplete' $incomplete.ToString().ToLowerInvariant()

Add-Summary '## Aggregate test totals'
Add-Summary ''
Add-Summary '| Metric | Total |'
Add-Summary '|---|---:|'
Add-Summary "| Failed test occurrences (including unique hang victims) | $failureOutput |"
Add-Summary "| Distinct failing tests | $distinctOutput |"
Add-Summary "| Executed tests | $executed |"
Add-Summary "| Discovered tests | $discovered |"
Add-Summary "| Parsed TRX files | $($trxFiles.Count - $unparseableTrx.Count) / $($trxFiles.Count) |"
Add-Summary "| Reported shards | $($trxFiles.Count) / $expectedShardOutput |"
Add-Summary "| Blame-hang victims | $($hangVictims.Count) |"

if ($incomplete) {
Add-Summary ''
Add-Summary ':warning: **These failure totals are incomplete or unknown.** Treat numeric values as a floor.'
}
if ($unparseableTrx.Count -gt 0) {
foreach ($errorText in $unparseableTrx) { Add-Summary (' ' + $errorText) }
}
if ($unparseableSequence.Count -gt 0) {
foreach ($errorText in $unparseableSequence) { Add-Summary (' ' + $errorText) }
}
}

try {
& $body
} catch {
Write-Host "::warning::report-test-totals.ps1 could not complete: $($_.Exception.Message)"
Set-CiOutput 'failed_test_occurrences' 'unknown'
Set-CiOutput 'distinct_failing_tests' 'unknown'
Set-CiOutput 'executed_tests' 'unknown'
Set-CiOutput 'discovered_tests' 'unknown'
Set-CiOutput 'reported_shards' 'unknown'
Set-CiOutput 'expected_shards' 'unknown'
Set-CiOutput 'test_totals_incomplete' 'true'
}

exit 0
Loading
Loading