@@ -428,7 +428,7 @@ registered = {}
428428registry = root / '.registry'
429429if registry.is_file():
430430 try:
431- data = json.loads(registry.read_text())
431+ data = json.loads(registry.read_text(encoding='utf-8' ))
432432 value = data.get('extensions', {}) if isinstance(data, dict) else {}
433433 registered = value if isinstance(value, dict) else {}
434434 except Exception:
@@ -503,7 +503,7 @@ resolve_template() {
503503 if sorted_presets=$( SPECKIT_REGISTRY=" $registry_file " " ${python_cmd[@]} " -c "
504504import json, re, sys, os
505505try:
506- with open(os.environ['SPECKIT_REGISTRY']) as f:
506+ with open(os.environ['SPECKIT_REGISTRY'], encoding='utf-8' ) as f:
507507 data = json.load(f)
508508 presets = data.get('presets', {})
509509 def priority(meta):
@@ -622,7 +622,7 @@ resolve_template_content() {
622622 if sorted_presets=$( SPECKIT_REGISTRY=" $registry_file " " ${python_cmd[@]} " -c "
623623import json, re, sys, os
624624try:
625- with open(os.environ['SPECKIT_REGISTRY']) as f:
625+ with open(os.environ['SPECKIT_REGISTRY'], encoding='utf-8' ) as f:
626626 data = json.load(f)
627627 presets = data.get('presets', {})
628628 def priority(meta):
@@ -675,7 +675,7 @@ except ImportError:
675675 print('yaml_missing', file=sys.stderr)
676676 sys.exit(2)
677677try:
678- with open(os.environ['SPECKIT_MANIFEST']) as f:
678+ with open(os.environ['SPECKIT_MANIFEST'], encoding='utf-8' ) as f:
679679 data = yaml.safe_load(f)
680680 if not isinstance(data, dict):
681681 raise ValueError('manifest root must be a mapping')
@@ -685,15 +685,26 @@ try:
685685 templates = provides.get('templates', [])
686686 if not isinstance(templates, list):
687687 raise ValueError('manifest templates must be a list')
688+ valid_types = ('template', 'command', 'script')
689+ valid_strategies = ('replace', 'prepend', 'append', 'wrap')
688690 for t in templates:
689691 if not isinstance(t, dict):
690692 raise ValueError('manifest template entries must be mappings')
691- file_value = t.get('file', '')
693+ if 'type' not in t or 'name' not in t or 'file' not in t:
694+ raise ValueError('manifest template entry missing type, name, or file')
695+ for field in ('type', 'name', 'file'):
696+ if not isinstance(t[field], str):
697+ raise ValueError('manifest template ' + field + ' must be a string')
698+ if t['type'] not in valid_types:
699+ raise ValueError('invalid manifest template type')
692700 strategy = t.get('strategy', 'replace')
693- if not isinstance(file_value, str):
694- raise ValueError('manifest template file must be a string')
695701 if not isinstance(strategy, str):
696702 raise ValueError('manifest template strategy must be a string')
703+ strategy = strategy.lower()
704+ if strategy not in valid_strategies:
705+ raise ValueError('invalid manifest template strategy')
706+ if t['type'] == 'script' and strategy not in ('replace', 'wrap'):
707+ raise ValueError('invalid manifest script strategy')
697708 for t in templates:
698709 if t.get('name') == os.environ['SPECKIT_TMPL'] and t.get('type', 'template') == 'template':
699710 file_value = t.get('file', '')
0 commit comments