Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ library never sees.
`{}` as "nothing to override with" would be the per-field merge this design
rejects. Both halves are pinned:
`FrontmatterTests.EffectiveUsageWindow_falls_back_to_shared_when_the_entrys_override_is_not_a_mapping`
and `…_present_and_empty_entry_window_is_not_absent_and_does_not_fall_back`.
and `FrontmatterTests.EffectiveUsageWindow_present_and_empty_entry_window_is_not_absent_and_does_not_fall_back`.

## 4. Model

Expand Down Expand Up @@ -141,7 +141,7 @@ Checked one at a time on `d6b778d`, **before** writing any implementation.
| **C2** | Every `Source` construction site takes six arguments, positional or named | ✅ seven sites (`git grep -n "new Source(" d6b778d -- src tests`): three in `src/` (`OkfDocument.cs:212`, `OkfDocumentBuilder.cs:94`, `Provenance.cs:32`) and four in `ProvenanceTests.cs` (`:81`, `:95`, `:106`, `:115`) — an optional seventh member keeps all seven compiling |
| **C3** | `usage_window` is consumed nowhere outside `Frontmatter`/`Validate` | ✅ no resolver, agent, viewer or CLI path reads it |
| **C4** | The known-key list governs top-level keys only | ✅ `Frontmatter.cs:27-35` is a top-level list; a nested key inside a `sources` entry is not matched against it |
| **C5** | `ToYaml`'s round-trip is already exercised | ✅ `ProvenanceTests.ToYaml_round_trips_through_ParseSources_in_order` and `…_uses_canonical_per_entry_key_order` |
| **C5** | `ToYaml`'s round-trip is already exercised | ✅ `ProvenanceTests.ToYaml_round_trips_through_ParseSources_in_order` and `ProvenanceTests.ToYaml_uses_canonical_per_entry_key_order` |
| **C6** | *(added by verification)* the producer-side write path covers the new field | ❌ **false** — see below |
| **C7** | *(added by verification)* `Source(…, UsageWindow? UsageWindow = null)` compiles despite the member sharing its type's name, and every existing call site still builds | ✅ probed by actually adding the member and building: `OKF4net.sln` at 0 errors, 0 warnings, then reverted |
| **C8** | *(added by verification)* nothing deconstructs `Source` positionally, so the arity change breaks no in-repo caller | ✅ no `is Source(…)`, no `Deconstruct` call anywhere in `src/`, `tests/`, `producers/`, `samples/` |
Expand Down
4 changes: 2 additions & 2 deletions producers/src/OkfProducer.Core/Generation/BundleWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -903,13 +903,13 @@ private static void RemoveEmptyDirectories(string outPath, string ownedPrefix, I
/// <c>Directory.Delete(recursive: true)</c> and the bundle root. It is the most destructive
/// statement on this branch, and until
/// <c>PruningTests.The_directory_ladder_stops_at_the_owned_prefix_root_and_not_above_it</c> it was
/// on no test's critical path -- every other fixture left a sibling that broke the loop one rung in.
/// on no test's critical path -- every other fixture left a sibling that broke the loop one rung in.</para>
///
/// <para>This comment used to describe a different scenario: a sibling directory whose name merely
/// starts with the prefix (<c>code2/</c> beside <c>code/</c>) being walked into and deleted. That
/// cannot happen and never could -- the walk only ever goes upward, so it never reaches a sibling
/// at all. The component comparison is still the right implementation; it just was not defending
/// against the thing the comment named.</para></para>
/// against the thing the comment named.</para>
/// </summary>
private static bool IsWithinPrefixRoot(string directory, string prefixRoot) =>
string.Equals(directory, prefixRoot, PathComparison)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,6 @@ public void The_golden_bundle_holds_one_occurrence_of_each_shape()

// The local function inside `Render` is Private too, so it is not a concept either.
Assert.DoesNotContain(concepts, id => id.Contains("compose", StringComparison.Ordinal));
Assert.DoesNotContain("code/csharp/n/scanner/cache", concepts);

var register = File.ReadAllText(Path.Combine(ProducerFixture.GoldenBundle, "code/csharp/n/registry/register.md"));
var count = File.ReadAllText(Path.Combine(ProducerFixture.GoldenBundle, "code/csharp/n/registry/count.md"));
Expand Down
2 changes: 2 additions & 0 deletions src/OKF4net/ConceptSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ private static int ScoreConcept(Concept concept, IReadOnlyList<string> terms)
/// <returns>At most <paramref name="count"/> results, in the order they should be shown.</returns>
public static IReadOnlyList<ScoredConcept> TopDiversified(IReadOnlyList<ScoredConcept> scored, int count)
{
ArgumentNullException.ThrowIfNull(scored);

if (count <= 0 || scored.Count == 0)
{
return [];
Expand Down
9 changes: 9 additions & 0 deletions tests/OKF4net.Tests/ConceptSearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,15 @@ public void TopDiversifiedBy_returns_empty_for_an_empty_input_or_a_non_positive_
Assert.Empty(ConceptSearch.TopDiversifiedBy(["code/a"], FamilyOf, 0));
}

[Fact]
public void TopDiversified_rejects_a_null_list()
{
// Same contract as TopDiversifiedBy below: a null list is a caller
// mistake worth naming. Without the guard it fell through to
// scored.Count and surfaced as a NullReferenceException instead.
Assert.Throws<ArgumentNullException>(() => ConceptSearch.TopDiversified(null!, 1));
}

[Fact]
public void TopDiversifiedBy_rejects_null_arguments()
{
Expand Down