Skip to content

Commit f6b5341

Browse files
committed
fix: address Copilot review round 5 findings
- Add 'Required Extensions' and 'Number of Scripts' fields to preset issue template and wire through label mapping, validation, and builder so new submissions can express requires.extensions and provides.scripts - Make 'Templates Provided' optional in preset validation — require at least one of templates or commands (supports command-only presets) - Fix bot comment matching: use marker-only search instead of c.user.type === 'Bot' since RELEASE_PAT creates comments as a User - Preserve provides.scripts on preset updates
1 parent 606eb9a commit f6b5341

3 files changed

Lines changed: 56 additions & 15 deletions

File tree

.github/ISSUE_TEMPLATE/preset_submission.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,22 @@ body:
9595
validations:
9696
required: true
9797

98+
- type: input
99+
id: required-extensions
100+
attributes:
101+
label: Required Extensions (optional)
102+
description: Comma-separated list of required extension IDs (e.g., aide)
103+
placeholder: "e.g., aide, canon"
104+
98105
- type: textarea
99106
id: templates-provided
100107
attributes:
101108
label: Templates Provided
102-
description: List the template overrides your preset provides
109+
description: List the template overrides your preset provides (leave empty for command-only presets)
103110
placeholder: |
104111
- spec-template.md — adds compliance section
105112
- plan-template.md — includes audit checkpoints
106113
- checklist-template.md — HIPAA compliance checklist
107-
validations:
108-
required: true
109114
110115
- type: textarea
111116
id: commands-provided
@@ -115,6 +120,13 @@ body:
115120
placeholder: |
116121
- speckit.specify.md — customized for compliance workflows
117122
123+
- type: input
124+
id: scripts-count
125+
attributes:
126+
label: Number of Scripts (optional)
127+
description: How many scripts does your preset provide? (leave empty if none)
128+
placeholder: "e.g., 1"
129+
118130
- type: textarea
119131
id: tags
120132
attributes:

.github/scripts/catalog-validate.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ def parse_issue_body(body: str) -> dict[str, str]:
100100
"Download URL": "download_url",
101101
"License": "license",
102102
"Required Spec Kit Version": "speckit_version",
103+
"Required Extensions (optional)": "required_extensions",
103104
"Templates Provided": "templates_provided",
104105
"Commands Provided (optional)": "commands_provided",
106+
"Number of Scripts (optional)": "scripts_count",
105107
"Tags": "tags",
106108
"Key Features": "features",
107109
"Testing Checklist": "testing_checklist",
@@ -503,10 +505,13 @@ def _add(field: str, ok: bool, msg: str, *, severity: str = "error") -> None:
503505
ok, msg = validate_hooks_count(fields.get("hooks_count", ""))
504506
_add("Number of Hooks", ok, msg)
505507
elif catalog_type == "preset":
506-
ok, msg = validate_required_text(
507-
fields.get("templates_provided", ""), "Templates Provided",
508-
)
509-
_add("Templates Provided", ok, msg)
508+
templates_provided = fields.get("templates_provided", "").strip()
509+
commands_provided = fields.get("commands_provided", "").strip()
510+
if templates_provided or commands_provided:
511+
_add("Preset Provides", True, "Templates and/or commands provided.")
512+
else:
513+
_add("Preset Provides", False,
514+
"At least one of Templates Provided or Commands Provided is required.")
510515
# Commands Provided is optional for presets
511516

512517
# --- Tags ---
@@ -702,11 +707,23 @@ def _build_preset_entry(
702707
if is_update and catalog:
703708
existing = catalog.get("presets", {}).get(item_id, {})
704709

705-
# Build requires — preserve existing extensions on updates
710+
# Build requires — include extensions from form or preserve on updates
706711
requires: dict = {
707712
"speckit_version": fields["speckit_version"].strip(),
708713
}
709-
if is_update and "extensions" in existing.get("requires", {}):
714+
extensions_raw = _clean(fields.get("required_extensions", ""))
715+
if extensions_raw:
716+
# Parse comma-separated or bullet-list extension IDs
717+
ext_list = []
718+
for line in extensions_raw.splitlines():
719+
line = line.strip().lstrip("-*").strip()
720+
for part in line.split(","):
721+
part = part.strip()
722+
if part:
723+
ext_list.append(part)
724+
if ext_list:
725+
requires["extensions"] = ext_list
726+
elif is_update and "extensions" in existing.get("requires", {}):
710727
requires["extensions"] = existing["requires"]["extensions"]
711728

712729
# Documentation URL: use existing on update, fall back to repo/blob/main/README.md
@@ -716,6 +733,21 @@ def _build_preset_entry(
716733
if not documentation:
717734
documentation = repo + "/blob/main/README.md"
718735

736+
# Scripts count from form or preserve on updates
737+
scripts_count = 0
738+
scripts_raw = _clean(fields.get("scripts_count", ""))
739+
if scripts_raw and scripts_raw.isdigit():
740+
scripts_count = int(scripts_raw)
741+
elif is_update:
742+
scripts_count = existing.get("provides", {}).get("scripts", 0)
743+
744+
provides: dict = {
745+
"templates": templates_count,
746+
"commands": commands_count,
747+
}
748+
if scripts_count:
749+
provides["scripts"] = scripts_count
750+
719751
return {
720752
"name": _clean(fields.get("item_name")),
721753
"id": item_id,
@@ -728,10 +760,7 @@ def _build_preset_entry(
728760
"documentation": documentation,
729761
"license": fields["license"].strip(),
730762
"requires": requires,
731-
"provides": {
732-
"templates": templates_count,
733-
"commands": commands_count,
734-
},
763+
"provides": provides,
735764
"tags": parse_tags(fields["tags"]),
736765
"created_at": existing.get("created_at", now),
737766
"updated_at": now,

.github/workflows/catalog-validate.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
);
5454
const marker = '<!-- catalog-submission-bot -->';
5555
const botComment = allComments.find(c =>
56-
c.user.type === 'Bot' && c.body.includes(marker)
56+
c.body && c.body.includes(marker)
5757
);
5858
5959
const body = marker + '\n\n' + report;
@@ -157,7 +157,7 @@ jobs:
157157
);
158158
const marker = '<!-- catalog-submission-bot -->';
159159
const botComment = allComments.find(c =>
160-
c.user.type === 'Bot' && c.body.includes(marker)
160+
c.body && c.body.includes(marker)
161161
);
162162
163163
const body = marker + '\n\n' + report;

0 commit comments

Comments
 (0)