_parse_model_experience stripped a bare string and returned it, so
`model_experience: " "` parsed as {"what_model_sees": ""} and every
model-visible surface rendered a "Model experience:" label with nothing after
it. The mapping form has always refused exactly that, with a fix_hint. Two
shapes of the same authoring mistake, one of them silent.
The fix is a subtraction: the string form IS the one-key mapping form, so it
now routes through the mapping branch instead of carrying its own return.
That is what makes the two refusals identical by construction rather than by
a copied message, and it removes a line rather than adding a branch.
Red-first: the two new parametrized cases (" " and "\n\t \n") DID NOT RAISE
before the change; green after, with test_skill_manifest_v11, test_contracts
and test_skill_loader.
The skill manifest gains an optional model_experience prose section
(what_model_sees / token_effect; a bare string is shorthand for
what_model_sees). The prose travels to both model-visible skill surfaces:
summarize_skills rows (list_skills JSON) and the installed-skills context
section, bounded like every other manifest field. A manifest without the
section keeps the exact prior behavior (pinned).
Registration refusals now teach: SkillManifestError carries a typed
fix_hint rendered into the message (— fix: ...), and every refusal site in
the manifest parser explains how to repair the manifest. The clawhub
adapter preserves an author's section across adaptation (frontmatter dict,
render order, translated front).
Bundled skills (telegram, unix_computer_use) declare the section.
Docs: CREATING_SKILLS authoring guidance + ARCHITECTURE contracts blurb
and §13 same-commit.