Skip to content

SpecKit-style preset composition: layered template resolution with prepend/append/wrap strategies #291

Description

@azalio

Summary

map-framework has Jinja-based template rendering (single-source, golden tests, make check-render) which is cleaner than competitors. But it lacks preset composition — the ability to layer organizational customizations without forking. SpecKit's 4-tier resolution stack with prepend/append/wrap/replace strategies enables team-specific modifications while keeping upstream updatable.

What SpecKit does

4-tier template resolution stack

  1. Project overrides: .specify/templates/overrides/{name}.md — highest priority
  2. Installed presets: .specify/presets/{preset-id}/templates/{name}.md (sorted by priority)
  3. Extensions: .specify/extensions/{ext-id}/templates/{name}.md
  4. Core templates: .specify/templates/{name}.md — base

Composition strategies

  • replace — highest-priority wins, lower layers irrelevant (fork)
  • prepend — layer content inserted ABOVE base content
  • append — layer content inserted BELOW base content
  • wrap — layer wraps base via {CORE_TEMPLATE} placeholder (most flexible)

Extension ecosystem

  • Pluggable extensions (git, bug-tracker, agent-context, selftest)
  • Declarative hook registration: before_command / after_command
  • Mandatory/optional hooks, condition-based execution
  • Extension registry + catalog for discovery

Preset management

  • specify preset add <id> — install from URL or local path
  • specify preset remove <id> — uninstall
  • specify preset enable/disable — toggle without uninstalling
  • specify preset set-priority <id> <N> — reorder stack
  • specify preset resolve <template> — show which layer wins for a template

Current map-framework state

  • Jinja-based rendering from templates_src/**/*.jinja → templates/, .claude/, .codex/
  • Single-source-of-truth, no composition layers
  • Customization requires editing .jinja source or generated files
  • No extension system with hooks
  • No preset catalog or registry

Proposed design

Layered resolution for .jinja templates

Config section in .map/config.yaml:

presets:
  resolution_order:
    - my-org-conventions    # priority: 100
    - security-hardening    # priority: 50
  strategies:
    my-org-conventions:
      "workflows/map-efficient.md.jinja": "prepend"   # Add org header
      "agents/actor.md.jinja": "append"               # Add org conventions
    security-hardening:
      "agents/monitor.md.jinja": "wrap"               # CORE_TEMPLATE in security wrapper

Composition engine

  • render-template <name> resolves through layers, applies strategies
  • render-template --resolve <name> shows which layers contribute (debug)
  • make check-render verifies all layers compose without conflicts

Preset management (mapify preset)

mapify preset add <name> --from <url|path>
mapify preset remove <name>
mapify preset enable/disable <name>
mapify preset set-priority <name> <N>
mapify preset resolve <template-name>
mapify preset list

Extension hooks

  • .map/extensions/{name}/hooks.yaml with before/after lifecycle hooks, mandatory/optional, condition-based execution

Preset catalog

  • mapify preset catalog — list available presets from registry
  • mapify preset catalog add <url> — add community registry
  • Shipped presets: lean (simplified workflow), enterprise (full gates), security (additional checks)

References

  • SpecKit: src/specify_cli/presets.py, scripts/bash/common.sh (lines 279-582), templates/
  • SpecKit preset resolution: specify preset resolve command

    Acceptance criteria

    • .map/presets/ directory structure
    • 4-tier resolution: project → preset → extension → core
    • Composition strategies: replace, prepend, append, wrap
    • mapify preset add/remove/enable/disable/list/resolve commands
    • Extension hooks: before/after lifecycle, mandatory/optional, conditions
    • Preset catalog with remote registry support
    • make check-render validates all layers compose correctly

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions