Problem
The current SHA/fingerprint approach is insufficient for composed templates with nesting. A content-only SHA treats identical files at different paths as identical, and it does not change when a transitive nested include changes.
An array of child SHAs would help with auditability, but it should not be the primary identity: consumers need one stable value to compare the complete composed template.
This matters for SkillRx-style consumers and any sc-compose workflow that treats nested templates/includes as one logical artifact.
Recommended solution
Introduce a versioned Merkle-style composition fingerprint.
For each template node:
node_sha = SHA256(
"skillrx-node-v2\\0" +
canonical_relative_path +
"\\0" +
exact_file_bytes
)
For the composed root:
composition_sha = SHA256(
"skillrx-composition-v2\\0" +
root_relative_path +
"\\0" +
root_node_sha +
"\\0" +
ordered_include_edges
)
Represent each include edge in the canonical manifest as:
{
"include_path": "shared/header.md",
"child_sha": "...",
"occurrence": 0
}
The dependency edge list must preserve include order and repeated includes. If the rendered output depends on profile, pass, or other render options, include a canonical hash of those options in the composition identity as well.
The implementation should expose the full dependency manifest/tree and node SHAs for diagnostics, while consumers compare the single composition_sha.
Required invariants
- Canonical relative paths with normalized separators.
- Deterministic serialization.
- Exact source bytes, or an explicitly documented normalization rule.
- Nested/transitive dependencies included recursively.
- Include order and repeated occurrences preserved.
- Cycles and missing dependencies produce stable diagnostics.
- Algorithm/version identifier included so future changes do not silently collide.
- Separate
source_composition_sha and rendered_output_sha if output verification is required.
- No dependence on mtime, filesystem traversal order, or absolute machine-specific paths.
Acceptance criteria
- Identical content at different canonical paths produces different node fingerprints.
- Changing only a nested include changes the root
composition_sha.
- Adding, removing, reordering, or repeating an include changes the root fingerprint.
- A nested dependency manifest is reproducible across machines.
- Equivalent source trees produce the same fingerprint regardless of traversal order.
- Cyclic and missing includes fail deterministically.
- Existing non-nested templates retain a documented compatibility path or migration behavior.
- Tests cover one-level nesting, multi-level nesting, repeated includes, path collisions, changed child content, and render-context changes.
Non-goal
Do not use an unordered array of independent file SHAs as the sole identity. Keep the array/tree as inspectable evidence, but derive one root composition fingerprint from the ordered dependency graph.
Problem
The current SHA/fingerprint approach is insufficient for composed templates with nesting. A content-only SHA treats identical files at different paths as identical, and it does not change when a transitive nested include changes.
An array of child SHAs would help with auditability, but it should not be the primary identity: consumers need one stable value to compare the complete composed template.
This matters for SkillRx-style consumers and any sc-compose workflow that treats nested templates/includes as one logical artifact.
Recommended solution
Introduce a versioned Merkle-style composition fingerprint.
For each template node:
For the composed root:
Represent each include edge in the canonical manifest as:
{ "include_path": "shared/header.md", "child_sha": "...", "occurrence": 0 }The dependency edge list must preserve include order and repeated includes. If the rendered output depends on profile, pass, or other render options, include a canonical hash of those options in the composition identity as well.
The implementation should expose the full dependency manifest/tree and node SHAs for diagnostics, while consumers compare the single
composition_sha.Required invariants
source_composition_shaandrendered_output_shaif output verification is required.Acceptance criteria
composition_sha.Non-goal
Do not use an unordered array of independent file SHAs as the sole identity. Keep the array/tree as inspectable evidence, but derive one root composition fingerprint from the ordered dependency graph.