Write or modify CyanPrint resolver code in Python. Use when the user asks to change conflict resolution logic, modify merge strategies, handle file origins, or change resolution behavior. Covers entry point (start_resolver_with_fn), ResolverInput/ResolverOutput, ResolvedFile, and FileOrigin. Must ensure commutativity and associativity (sort, unique, deterministic ordering).
Install
npx skillscat add atomicloud/ketone-new-cyanprint/writing-resolver-python Install via the SkillsCat registry.
SKILL.md
Writing this Resolver (Python)
Entry Point
from cyanprintsdk import start_resolver_with_fn
def resolver_fn(input):
config = input.config
files = input.files
# Resolve conflict
return {"path": path, "content": content}
start_resolver_with_fn(resolver_fn)ResolverInput
class ResolverInput:
config: dict # { str: unknown }
files: list[ResolvedFile]ResolvedFile
All files entries have the same path -- that is the conflict being resolved:
class ResolvedFile:
path: str
content: str
origin: FileOriginFileOrigin
class FileOrigin:
template: str # Which template produced this file
layer: int # Layer number -- IMPORTANT: int, NOT strCritical: layer is an int, not a string. Compare numerically, never as string.
ResolverOutput
Return a single resolved file:
{"path": str, "content": str}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
sorted_files = sorted(files, key=lambda f: (f.origin.layer, f.origin.template))Pattern 2: Deduplicate after merge
all_items = []
for f in sorted_files:
all_items.extend(json.loads(f.content)["items"])
unique = sorted(set(all_items))Pattern 3: Deterministic priority
# Highest layer number wins -- deterministic regardless of input order
winner = max(files, key=lambda f: f.origin.layer)Resolution Strategies
Last-Write Wins (by layer)
sorted_files = sorted(files, key=lambda f: f.origin.layer)
last = sorted_files[-1]
return {"path": last.path, "content": last.content}Deep Merge (JSON)
sorted_files = sorted(files, key=lambda f: f.origin.layer)
merged = {}
for f in sorted_files:
merged = deep_merge(merged, json.loads(f.content))
return {"path": files[0].path, "content": json.dumps(merged, indent=2)}Entry Point Skeleton
from cyanprintsdk import start_resolver_with_fn
def resolver_fn(input):
config = input.config
files = input.files
if len(files) == 0:
raise ValueError("Resolver received no files — at least 1 file is required")
unique_paths = set(f["path"] for f in files)
if len(unique_paths) > 1:
raise ValueError(f"Resolver received files with different paths: {', '.join(unique_paths)} — all files must have the same path")
path = files[0].path
# Sort for commutativity (layer ascending, then template name)
sorted_files = sorted(files, key=lambda f: (f.origin.layer, f.origin.template))
# TODO: Implement resolution logic
content = sorted_files[-1].content
return {"path": path, "content": content}
start_resolver_with_fn(resolver_fn)Key Rules
- All
filesentries have the samepath-- that is the conflict being resolved FileOrigin.layeris anint-- compare numerically, never as string- Return a single
{"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