Fission-AI/OpenSpec · error
getSkillTemplates() returns ${unpinned.length} skill(s) with
Error message
getSkillTemplates() returns ${unpinned.length} skill(s) with no pinned hash in ${sourceLabel}:
${unpinned.map((key) => ` ${key}`).join('\n')}
Add each to EXPECTED_GENERATED_SKILL_CONTENT_HASHES and GENERATED_SKILL_FACTORIES.
Until then the skill ships with no parity coverage, so this run would have reported success while leaving it unguarded. What it means
Error "getSkillTemplates() returns ${unpinned.length} skill(s) with no pinned hash in ${sourceLabel}: ${unpinned.map((key) => ` ${key}`).join('\n')} Add each to EXPECTED_GENERATED_SKILL_CONTENT_HASHES and GENERATED_SKILL_FACTORIES. Until then the skill ships with no parity coverage, so this run would have reported success while leaving it unguarded." thrown in Fission-AI/OpenSpec.
Source
Thrown at scripts/parity-hash-shared.mjs:100
if (seen !== totalHexLiterals) {
throw new Error(
`Rewrote ${seen} of ${totalHexLiterals} 64-hex literals in ${sourceLabel}.\n` +
'Every one is assumed to be a pinned hash, so the two counts must agree. Either:\n' +
' - a pinned hash is formatted in a way the patterns here do not match, and ' +
'would have been left stale without warning: widen them; or\n' +
' - the file gained a 64-hex literal that is not a pin: narrow the count above ' +
'so it stops being mistaken for one.'
);
}
// The checks above only see pins that exist. A workflow added to the registry
// but never pinned is invisible to them AND to the parity test, which compares
// only the entries it already lists - so it would ship with no golden hash at
// all while this reported success. Compare the other direction too.
const unpinned = [...knownContentKeys].filter((key) => !seenContentKeys.has(key));
if (unpinned.length > 0) {
throw new Error(
`getSkillTemplates() returns ${unpinned.length} skill(s) with no pinned hash in ${sourceLabel}:\n` +
unpinned.map((key) => ` ${key}`).join('\n') +
'\nAdd each to EXPECTED_GENERATED_SKILL_CONTENT_HASHES and GENERATED_SKILL_FACTORIES.\n' +
'Until then the skill ships with no parity coverage, so this run would have ' +
'reported success while leaving it unguarded.'
);
}
return { source: rewritten, moved };
}
/**
* Stable, key-sorted serialisation used to hash a template's payload.
*
* Must stay byte-compatible with the copy in
* `test/core/templates/skill-templates-parity.test.ts`. A divergence cannot pass
* unnoticed: that test recomputes the hashes independently and compares.
*/View on GitHub (pinned to 6926ccb18a)
When it happens
Trigger: Thrown at scripts/parity-hash-shared.mjs:100 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Fission-AI/OpenSpec@6926ccb18a (2026-08-25).
Data as JSON: /api/errors/7e54457a21d62910.
Report an issue: GitHub.