{"record":{"id":"2a639a3f6db5098c","repo":"github/spec-kit","slug":"wrap-strategy-in-layer-source-is-missing-th","errorCode":null,"errorMessage":"Wrap strategy in '{layer['source']}' is missing the {placeholder} placeholder. The wrapper must contain {placeholder} to indicate where the lower-priority content should be inserted.","messagePattern":"Wrap strategy in '(.+?)' is missing the (.+?) placeholder\\. The wrapper must contain (.+?) to indicate where the lower-priority content should be inserted\\.","errorType":"validation","errorClass":"PresetValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/presets/__init__.py","lineNumber":5851,"sourceCode":"                if strategy == \"replace\":\n                    top_frontmatter_text = fm\n                    base_frontmatter_text = fm\n                elif fm:\n                    top_frontmatter_text = fm\n\n            if strategy == \"replace\":\n                content = layer_content\n            elif strategy == \"prepend\":\n                content = layer_content + \"\\n\\n\" + content\n            elif strategy == \"append\":\n                content = content + \"\\n\\n\" + layer_content\n            elif strategy == \"wrap\":\n                if template_type == \"script\":\n                    placeholder = \"$CORE_SCRIPT\"\n                else:\n                    placeholder = \"{CORE_TEMPLATE}\"\n                if placeholder not in layer_content:\n                    raise PresetValidationError(\n                        f\"Wrap strategy in '{layer['source']}' is missing \"\n                        f\"the {placeholder} placeholder. The wrapper must \"\n                        f\"contain {placeholder} to indicate where the \"\n                        f\"lower-priority content should be inserted.\"\n                    )\n                content = layer_content.replace(placeholder, content)\n\n        # Reattach the highest-priority frontmatter for commands,\n        # inheriting scripts/agent_scripts from the base if missing\n        # and stripping the strategy key (internal-only, not for agent output).\n        if is_command and top_frontmatter_text:\n            def _parse_fm_yaml(fm_block: str) -> dict:\n                \"\"\"Parse YAML from a frontmatter block (with --- fences).\"\"\"\n                lines = fm_block.splitlines()\n                # Parse only interior lines (between --- fences)\n                if len(lines) >= 2:\n                    yaml_lines = lines[1:-1]\n                else:","sourceCodeStart":5833,"sourceCodeEnd":5869,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/presets/__init__.py#L5833-L5869","documentation":"A preset layer using the 'wrap' merge strategy does not contain the required placeholder marking where lower-priority content goes: '$CORE_SCRIPT' for script templates, '{CORE_TEMPLATE}' for others. Without the placeholder the substitution target is undefined, so layer composition raises PresetValidationError instead of guessing.","triggerScenarios":"Authoring a preset overlay/extension template with strategy: wrap whose wrapper content omits $CORE_SCRIPT (scripts) or {CORE_TEMPLATE} (markdown/command templates); encountered during template layer merging.","commonSituations":"Copy-pasting a non-wrap template into a wrap layer; renaming or removing the placeholder while restyling a wrapper; using {CORE_TEMPLATE} in a script file (or $CORE_SCRIPT in markdown) so the type-specific placeholder is missing.","solutions":["Add the correct placeholder to the wrapper: $CORE_SCRIPT in script layers, {CORE_TEMPLATE} in markdown/command layers","Check placeholder spelling and braces exactly — {CORE_TEMPLATE} uses braces, $CORE_SCRIPT uses a dollar prefix","If you intended full replacement rather than wrapping, change the layer strategy to 'replace'"],"exampleFix":"# before (markdown wrap layer)\nstrategy: wrap\n---\n# My wrapper header\n<!-- no placeholder -->\n\n# after\nstrategy: wrap\n---\n# My wrapper header\n{CORE_TEMPLATE}","handlingStrategy":"validation","validationCode":"placeholder = \"$CORE_SCRIPT\" if template_type == \"script\" else \"{CORE_TEMPLATE}\"\nif layer[\"strategy\"] == \"wrap\" and placeholder not in layer_content:\n    raise ValueError(f\"wrap layer '{source}' missing {placeholder}\")","typeGuard":"def wrap_layer_is_valid(layer_content: str, template_type: str) -> bool:\n    ph = \"$CORE_SCRIPT\" if template_type == \"script\" else \"{CORE_TEMPLATE}\"\n    return ph in layer_content","tryCatchPattern":"except PresetValidationError as e:\n    if \"missing the\" in str(e) and \"placeholder\" in str(e):\n        # report the layer source and expected placeholder to the author\n        raise PresetAuthoringError(layer_source, str(e)) from e\n    raise","preventionTips":["When authoring wrap layers, always include $CORE_SCRIPT (scripts) or {CORE_TEMPLATE} (other templates) exactly once","Lint preset layers before publishing: wrap strategy requires the type-correct placeholder","Use 'replace' strategy when the wrapper genuinely should discard lower-priority content"],"tags":["presets","templates","layering","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}