Writes or modifies CyanPrint resolver code in C# to handle conflict resolution between files with the same path from multiple templates. Covers the entry point, input/output types, FileOrigin, and ensures deterministic output regardless of input ordering.
Install
npx skillscat add atomicloud/ketone-new-cyanprint/writing-resolver-dotnet Install via the SkillsCat registry.
Writes or modifies CyanPrint resolver code in C# to handle conflict resolution between files with the same path from multiple templates. Covers the entry point, input/output types, FileOrigin, and ensures deterministic output regardless of input ordering.
Writing this Resolver (C# / .NET)
Entry Point
using sulfone_helium;
ResolverOutput ResolverFn(ResolverInput input)
{
// Resolve conflict
return new ResolverOutput { Path = path, Content = content };
}
CyanEngine.StartResolver(ResolverFn);ResolverInput
public class ResolverInput
{
public Dictionary<string, object> Config { get; set; }
public List<ResolvedFile> Files { get; set; }
}ResolvedFile
All Files entries have the same Path -- that is the conflict being resolved:
public class ResolvedFile
{
public string Path { get; set; }
public string Content { get; set; }
public FileOrigin Origin { get; set; }
}FileOrigin
public class FileOrigin
{
public string Template { get; set; } // Which template produced this file
public int Layer { get; set; } // Layer number -- IMPORTANT: int, NOT string
}Critical: Layer is an int, not a string. Compare numerically, never as string.
ResolverOutput
Return a single resolved file:
public class ResolverOutput
{
public string Path { get; set; }
public string Content { get; set; }
}Commutativity and Associativity
CyanPrint may call the resolver with files in any order. Your result must be identical regardless of input ordering.
Pattern 1: Sort before processing
var sorted = input.Files
.OrderBy(f => f.Origin.Layer)
.ThenBy(f => f.Origin.Template)
.ToList();Pattern 2: Deduplicate after merge
var allItems = sorted
.SelectMany(f => JsonSerializer.Deserialize<List<string>>(f.Content))
.Distinct()
.OrderBy(x => x)
.ToList();Pattern 3: Deterministic priority
// Highest layer number wins -- deterministic regardless of input order
var winner = input.Files.OrderByDescending(f => f.Origin.Layer).First();Resolution Strategies
Last-Write Wins (by layer)
var sorted = input.Files
.OrderBy(f => f.Origin.Layer)
.ThenBy(f => f.Origin.Template)
.ToList();
var last = sorted.Last();
return new ResolverOutput { Path = last.Path, Content = last.Content };Deep Merge (JSON)
var sorted = input.Files
.OrderBy(f => f.Origin.Layer)
.ThenBy(f => f.Origin.Template)
.ToList();
var merged = new Dictionary<string, object>();
foreach (var file in sorted)
{
merged = DeepMerge(merged, JsonSerializer.Deserialize<Dictionary<string, object>>(file.Content));
}
return new ResolverOutput
{
Path = input.Files[0].Path,
Content = JsonSerializer.Serialize(merged, new JsonSerializerOptions { WriteIndented = true })
};Entry Point Skeleton
using sulfone_helium;
ResolverOutput ResolverFn(ResolverInput input)
{
var files = input.Files;
if (files.Count == 0) throw new Exception("Resolver received no files — at least 1 file is required");
var uniquePaths = files.Select(f => f.Path).Distinct().ToList();
if (uniquePaths.Count > 1) throw new Exception($"Resolver received files with different paths: {string.Join(", ", uniquePaths)} — all files must have the same path");
var path = files[0].Path;
// Sort for commutativity (layer ascending, then template name)
var sorted = files
.OrderBy(f => f.Origin.Layer)
.ThenBy(f => f.Origin.Template)
.ToList();
// TODO: Implement resolution logic
var content = sorted.Last().Content;
return new ResolverOutput { Path = path, Content = content };
}
CyanEngine.StartResolver(ResolverFn);Key Rules
- All
Filesentries have the samePath-- that is the conflict being resolved FileOrigin.Layeris anint-- compare numerically, never as string- Return a single
new ResolverOutput { Path = ..., Content = ... }-- the resolved file - Ensure commutativity -- sort inputs before processing, deduplicate outputs
- Ensure associativity -- result must be same whether resolved all-at-once or in pairs
- Validate input -- reject empty files list and mismatched paths with an error