Merge upstream/main; adopt articles[] eval override, add sample-link READ convention

- Resolve conflicts in al-data-modeling-review.md by keeping both sides'
  additions (folder-path support, InitRecord/Round cues from upstream;
  the 9 document-distribution/pricing/barcode cues from this branch).
- Switch the data-modeling evaluation override from an ad-hoc
  additionalArticles field to upstream's now-established articles[]
  convention (used elsewhere for finance/scm/query/reporting/style),
  removing the redundant parallel code path from Test-ReviewFixtures.ps1.
- Fix all 9 new articles' sample references to the markdown-link READ
  convention required by Knowledge-Retrieval.ps1's Assert-SampleLink
  (plain backticks satisfy validate_frontmatter.py's regex alone but not
  this stricter check - both validators must pass).

Validators: frontmatter 0/0, review-fixtures 126 cases/20 domains PASSED,
knowledge-index 342 articles/575 samples PASSED, skill-index 19 review
leaves PASSED.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michael Dieringer 2026-09-24 06:41:24 +02:00
commit e22352b248
504 changed files with 9501 additions and 1969 deletions

View file

@ -195,12 +195,42 @@ foreach ($domain in $leafDomains) {
}
$override = if ($overrides.ContainsKey($domain)) { $overrides[$domain] } else { $null }
$selectedArticle = $null
if ($override -and ($override.PSObject.Properties.Name -contains 'article')) {
$articleName = [string]$override.article
$hasArticleOverride = $override -and ($override.PSObject.Properties.Name -contains 'article')
$hasArticlesOverride = $override -and ($override.PSObject.Properties.Name -contains 'articles')
if ($hasArticleOverride -and $hasArticlesOverride) {
$problems.Add("${domain}: override must specify either 'article' or 'articles', not both.") | Out-Null
continue
}
$articleNames = @()
if ($hasArticlesOverride) {
$articleNames = @($override.articles)
if (-not $articleNames.Count) {
$problems.Add("${domain}: override 'articles' must contain at least one article.") | Out-Null
continue
}
} elseif ($hasArticleOverride) {
$articleNames = @($override.article)
} else {
$articleNames = @($articles | Select-Object -First 1 | ForEach-Object BaseName)
}
$selectedArticles = [System.Collections.Generic.List[object]]::new()
$seenArticleNames = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
foreach ($articleNameValue in $articleNames) {
if ($articleNameValue -isnot [string] -or [string]::IsNullOrWhiteSpace([string]$articleNameValue)) {
$problems.Add("${domain}: override article names must be non-empty strings.") | Out-Null
continue
}
$articleName = [string]$articleNameValue
if ($articleName.EndsWith('.md')) {
$articleName = [System.IO.Path]::GetFileNameWithoutExtension($articleName)
}
if (-not $seenArticleNames.Add($articleName)) {
$problems.Add("${domain}: override contains duplicate article: $articleName.md") | Out-Null
continue
}
$selectedArticle = $articles | Where-Object BaseName -eq $articleName | Select-Object -First 1
if (-not $selectedArticle) {
$articleExists = @(
@ -218,74 +248,43 @@ foreach ($domain in $leafDomains) {
}
continue
}
} else {
$selectedArticle = $articles | Select-Object -First 1
$selectedArticles.Add($selectedArticle) | Out-Null
}
if (-not $selectedArticle) {
$problems.Add("${domain}: no article has both .good.al and .bad.al companion samples.") | Out-Null
if (-not $selectedArticles.Count) {
if (-not $articleNames.Count) {
$problems.Add("${domain}: no article has both .good.al and .bad.al companion samples.") | Out-Null
}
continue
}
$articlePath = [string]$selectedArticle.ArticlePath
$sampleDirectory = (Split-Path -Parent $articlePath).Replace('\', '/')
$context = if ($override -and ($override.PSObject.Properties.Name -contains 'context')) {
[string]$override.context
} else {
$null
}
foreach ($kind in 'bad', 'good') {
$case = [pscustomobject]@{
id = "$domain-$kind"
domain = $domain
input = "$sampleDirectory/$($selectedArticle.BaseName).$kind.al"
expected = if ($kind -eq 'bad') { @($articlePath) } else { @() }
for ($articleIndex = 0; $articleIndex -lt $selectedArticles.Count; $articleIndex++) {
$selectedArticle = $selectedArticles[$articleIndex]
$articlePath = [string]$selectedArticle.ArticlePath
$sampleDirectory = (Split-Path -Parent $articlePath).Replace('\', '/')
foreach ($kind in 'bad', 'good') {
$caseId = if ($articleIndex -eq 0) {
"$domain-$kind"
} else {
"$domain-$($selectedArticle.BaseName)-$kind"
}
$case = [pscustomobject]@{
id = $caseId
domain = $domain
input = "$sampleDirectory/$($selectedArticle.BaseName).$kind.al"
expected = if ($kind -eq 'bad') { @($articlePath) } else { @() }
}
if ($context) {
$case | Add-Member -NotePropertyName context -NotePropertyValue $context
}
$caseList.Add($case) | Out-Null
}
if ($context) {
$case | Add-Member -NotePropertyName context -NotePropertyValue $context
}
$caseList.Add($case) | Out-Null
}
if ($override -and ($override.PSObject.Properties.Name -contains 'additionalArticles')) {
foreach ($additionalArticleName in @($override.additionalArticles)) {
$additionalName = [string]$additionalArticleName
if ($additionalName.EndsWith('.md')) {
$additionalName = [System.IO.Path]::GetFileNameWithoutExtension($additionalName)
}
$additionalArticle = $articles | Where-Object BaseName -eq $additionalName | Select-Object -First 1
if (-not $additionalArticle) {
$articleExists = @(
foreach ($layer in $layers) {
$articleFile = Join-Path $Root "$($layer.Name)/knowledge/$domain/$additionalName.md"
if (Test-Path -LiteralPath $articleFile -PathType Leaf) {
$articleFile
}
}
).Count -gt 0
if ($articleExists) {
$problems.Add("${domain}: additionalArticles entry does not have both .good.al and .bad.al companion samples: $additionalName.md") | Out-Null
} else {
$problems.Add("${domain}: additionalArticles entry does not exist: $additionalName.md") | Out-Null
}
continue
}
if ($additionalArticle.BaseName -eq $selectedArticle.BaseName) {
$problems.Add("${domain}: additionalArticles entry duplicates the selected article: $additionalName") | Out-Null
continue
}
$additionalArticlePath = [string]$additionalArticle.ArticlePath
$additionalSampleDirectory = (Split-Path -Parent $additionalArticlePath).Replace('\', '/')
foreach ($kind in 'bad', 'good') {
$additionalCase = [pscustomobject]@{
id = "$domain-$kind-$($additionalArticle.BaseName)"
domain = $domain
input = "$additionalSampleDirectory/$($additionalArticle.BaseName).$kind.al"
expected = if ($kind -eq 'bad') { @($additionalArticlePath) } else { @() }
}
$caseList.Add($additionalCase) | Out-Null
}
}
}
}
$cases = @($caseList)
@ -475,6 +474,7 @@ if ($PrepareDirectory) {
}
if (-not $ResultsPath -and -not $ResultsDirectory) {
& (Join-Path $PSScriptRoot 'Test-ReviewContract.ps1') -Root $Root
Write-Host "Review fixture validation PASSED: $($cases.Count) cases cover $($leafDomains.Count) leaf domains." -ForegroundColor Green
exit 0
}