From c3a478fa12117cc8b95e24f248650ef1024ba0e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:41:45 +0000 Subject: [PATCH 1/7] Initial plan From 3bc6a325e3df60f07209c8cd2e3f58140bce6130 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:48:18 +0000 Subject: [PATCH 2/7] Allow target property for create-check-run in frontmatter schema Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/parser/schema_safe_outputs_target_test.go | 9 +++++++++ pkg/parser/schemas/main_workflow_schema.json | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/pkg/parser/schema_safe_outputs_target_test.go b/pkg/parser/schema_safe_outputs_target_test.go index a9fbee9488a..53d782cf3c4 100644 --- a/pkg/parser/schema_safe_outputs_target_test.go +++ b/pkg/parser/schema_safe_outputs_target_test.go @@ -305,6 +305,15 @@ func TestMainWorkflowSchema_SafeOutputsTargetProperties(t *testing.T) { }, }, }, + { + name: "create-check-run with target", + safeOutputs: map[string]any{ + "create-check-run": map[string]any{ + "name": "Test Check", + "target": "*", + }, + }, + }, { name: "issue-intent toggle accepted for close and assignment tools", safeOutputs: map[string]any{ diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 41ad23f21da..8c4b061a2ad 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -8203,6 +8203,10 @@ "type": "string", "description": "Check run name shown in the GitHub Checks UI (e.g., 'Security Analysis'). If omitted, defaults to the workflow name." }, + "target": { + "type": "string", + "description": "Target pull request for check run attachment: 'triggering' (default), '*' (any PR), or explicit PR number" + }, "max": { "description": "Maximum number of check runs to create per workflow run (default: 1). Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", "oneOf": [ From df02c517b304cf9cb473226c13775c4a6af3e3fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:13:25 +0000 Subject: [PATCH 3/7] Check safe output schema config coverage Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- scripts/check-safe-outputs-conformance.sh | 81 +++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/scripts/check-safe-outputs-conformance.sh b/scripts/check-safe-outputs-conformance.sh index 307e6af8ff3..010c695c933 100755 --- a/scripts/check-safe-outputs-conformance.sh +++ b/scripts/check-safe-outputs-conformance.sh @@ -422,6 +422,87 @@ check_schema_consistency() { } check_schema_consistency +# IMP-004: Safe Output Config Schema Coverage +echo "Running IMP-004: Safe Output Config Schema Coverage..." +check_safe_output_config_schema_coverage() { + local missing_properties + + missing_properties=$(python3 - <<'PY' +import json +import re +from pathlib import Path + +schema = json.loads(Path("pkg/parser/schemas/main_workflow_schema.json").read_text()) +structs = {} +handler_fields = {} + +for path in Path("pkg/workflow").glob("*.go"): + if path.name.endswith("_test.go"): + continue + content = path.read_text() + for match in re.finditer(r"(?ms)^type\s+(\w+)\s+struct\s*\{(.*?)^\}", content): + structs[match.group(1)] = match.group(2) + +handlers = Path("pkg/workflow/safe_output_handlers.go").read_text() +for match in re.finditer(r'Key:\s*"([^"]+)"(?:(?!Key:).){0,500}?StructField:\s*"([^"]+)"', handlers, re.S): + handler_fields[match.group(2)] = match.group(1) + + +def yaml_fields(struct_name): + for line in structs.get(struct_name, "").splitlines(): + match = re.match(r'\s*(.*?)\s+`yaml:"([^"]+)"', line) + if not match: + continue + tag = match.group(2).split(",", 1)[0] + if tag == "-": + continue + yield tag, ",inline" in match.group(2) + + +def properties(node): + result = node.get("properties", {}) + for alternative in ("allOf", "anyOf", "oneOf"): + for child in node.get(alternative, []): + result = {**result, **properties(child)} + return result + + +missing = [] + + +safe_outputs = properties(schema["properties"]["safe-outputs"]) +for line in structs["SafeOutputsConfig"].splitlines(): + match = re.match(r'\s*(\w+)\s+\*?(\w+)\s+`yaml:"([^"]+)"', line) + if not match: + continue + struct_field, config_type, output_name = match.groups() + if struct_field not in handler_fields: + continue + output_name = output_name.split(",", 1)[0] + output_schema = safe_outputs.get(output_name) + if output_schema is None: + missing.append(f"safe-outputs.{output_name}") + continue + + output_properties = properties(output_schema) + for tag, inline in yaml_fields(config_type): + if not inline and tag not in output_properties: + missing.append(f"safe-outputs.{output_name}.{tag}") + +print("\n".join(sorted(set(missing)))) +PY +) + + if [ -n "$missing_properties" ]; then + while IFS= read -r property; do + log_high "IMP-004: Safe output config property is missing from schema: $property" + done <<< "$missing_properties" + else + log_pass "IMP-004: All safe output config properties are declared in the schema" + fi +} +check_safe_output_config_schema_coverage + # MCE-001: Tool Description Constraint Disclosure (Section 8.3 MCE2) echo "Running MCE-001: Tool Description Constraint Disclosure..." check_mce_constraint_disclosure() { From f976200d49381fee89539122b8e1bd9a7eec29bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:14:52 +0000 Subject: [PATCH 4/7] Harden safe output schema coverage check Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- scripts/check-safe-outputs-conformance.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/check-safe-outputs-conformance.sh b/scripts/check-safe-outputs-conformance.sh index 010c695c933..5e66c13d744 100755 --- a/scripts/check-safe-outputs-conformance.sh +++ b/scripts/check-safe-outputs-conformance.sh @@ -444,7 +444,7 @@ for path in Path("pkg/workflow").glob("*.go"): structs[match.group(1)] = match.group(2) handlers = Path("pkg/workflow/safe_output_handlers.go").read_text() -for match in re.finditer(r'Key:\s*"([^"]+)"(?:(?!Key:).){0,500}?StructField:\s*"([^"]+)"', handlers, re.S): +for match in re.finditer(r'Key:\s*"([^"]+)".*?StructField:\s*"([^"]+)"', handlers, re.S): handler_fields[match.group(2)] = match.group(1) @@ -460,10 +460,13 @@ def yaml_fields(struct_name): def properties(node): - result = node.get("properties", {}) + result = dict(node.get("properties", {})) for alternative in ("allOf", "anyOf", "oneOf"): for child in node.get(alternative, []): - result = {**result, **properties(child)} + for name, definition in properties(child).items(): + if name in result and result[name] != definition: + raise ValueError(f"conflicting schema definitions for property: {name}") + result[name] = definition return result From 7a201ede21ba2d915f336b36156f92aae251eb4c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:16:20 +0000 Subject: [PATCH 5/7] Scope safe output handler schema checks Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- scripts/check-safe-outputs-conformance.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/check-safe-outputs-conformance.sh b/scripts/check-safe-outputs-conformance.sh index 5e66c13d744..948aeb83f2f 100755 --- a/scripts/check-safe-outputs-conformance.sh +++ b/scripts/check-safe-outputs-conformance.sh @@ -423,7 +423,6 @@ check_schema_consistency() { check_schema_consistency # IMP-004: Safe Output Config Schema Coverage -echo "Running IMP-004: Safe Output Config Schema Coverage..." check_safe_output_config_schema_coverage() { local missing_properties @@ -444,7 +443,7 @@ for path in Path("pkg/workflow").glob("*.go"): structs[match.group(1)] = match.group(2) handlers = Path("pkg/workflow/safe_output_handlers.go").read_text() -for match in re.finditer(r'Key:\s*"([^"]+)".*?StructField:\s*"([^"]+)"', handlers, re.S): +for match in re.finditer(r'Key:\s*"([^"]+)"[^}]*?StructField:\s*"([^"]+)"', handlers): handler_fields[match.group(2)] = match.group(1) @@ -504,6 +503,7 @@ PY log_pass "IMP-004: All safe output config properties are declared in the schema" fi } +echo "Running IMP-004: Safe Output Config Schema Coverage..." check_safe_output_config_schema_coverage # MCE-001: Tool Description Constraint Disclosure (Section 8.3 MCE2) From 4f1327bb8f5d46bf33ba48eb29afc6a971861621 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:17:10 +0000 Subject: [PATCH 6/7] Robustly discover safe output handlers Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- scripts/check-safe-outputs-conformance.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/check-safe-outputs-conformance.sh b/scripts/check-safe-outputs-conformance.sh index 948aeb83f2f..23859db3f5d 100755 --- a/scripts/check-safe-outputs-conformance.sh +++ b/scripts/check-safe-outputs-conformance.sh @@ -426,6 +426,8 @@ check_schema_consistency check_safe_output_config_schema_coverage() { local missing_properties + echo "Running IMP-004: Safe Output Config Schema Coverage..." + missing_properties=$(python3 - <<'PY' import json import re @@ -443,8 +445,14 @@ for path in Path("pkg/workflow").glob("*.go"): structs[match.group(1)] = match.group(2) handlers = Path("pkg/workflow/safe_output_handlers.go").read_text() -for match in re.finditer(r'Key:\s*"([^"]+)"[^}]*?StructField:\s*"([^"]+)"', handlers): - handler_fields[match.group(2)] = match.group(1) +handler_key = None +for line in handlers.splitlines(): + key_match = re.search(r'Key:\s*"([^"]+)"', line) + if key_match: + handler_key = key_match.group(1) + field_match = re.search(r'StructField:\s*"([^"]+)"', line) + if field_match and handler_key: + handler_fields[field_match.group(1)] = handler_key def yaml_fields(struct_name): @@ -503,7 +511,6 @@ PY log_pass "IMP-004: All safe output config properties are declared in the schema" fi } -echo "Running IMP-004: Safe Output Config Schema Coverage..." check_safe_output_config_schema_coverage # MCE-001: Tool Description Constraint Disclosure (Section 8.3 MCE2) From bc4ad18043f9ed6fe3afb605d36a5e362fd7691e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:35:29 +0000 Subject: [PATCH 7/7] Clarify create check run target semantics Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- pkg/parser/schemas/main_workflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 8c4b061a2ad..8a1fb5c0279 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -8205,7 +8205,7 @@ }, "target": { "type": "string", - "description": "Target pull request for check run attachment: 'triggering' (default), '*' (any PR), or explicit PR number" + "description": "Target pull request for check run attachment: 'triggering', '*' (any PR), or explicit PR number" }, "max": { "description": "Maximum number of check runs to create per workflow run (default: 1). Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').",