Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions docs/public/editor/autocomplete-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,6 @@
}
}
},
"disable-model-invocation": {
"type": "boolean",
"desc": "Controls whether the custom agent should disable model invocation.",
"enum": [true, false],
"leaf": true
},
"secrets": {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bundled CLI template files still use disable-model-invocation: true — will fail schema validation: Two embedded data files compiled into the CLI binary are not updated by this PR:

  • pkg/cli/data/agentic_workflow_designer_skill.md:4disable-model-invocation: true
  • pkg/cli/data/agentic_workflows_agent.md:4disable-model-invocation: true
💡 Details

Removing disable-model-invocation from the schema without updating these embedded files means any code path that parses or validates these bundled templates will produce a schema error at runtime. Since these files are embedded in the binary via //go:embed or similar, they will silently break scaffolding/agent-creation flows that depend on them.

Both lines must be removed (or the field must be replaced with its functional equivalent) before this PR is safe to merge.

"type": "object",
"desc": "Secret values passed to workflow execution."
Expand Down Expand Up @@ -1364,7 +1358,7 @@
},
"mode": {
"type": "string",
"desc": "Integration mode: 'cli' (recommended) installs @playwright/cli via npm for token-efficient CLI invocations use play...",
"desc": "Integration mode: 'cli' (recommended) installs @playwright/cli via npm for token-efficient CLI invocations \u2014 use play...",
"enum": ["cli", "mcp"],
"leaf": true
}
Expand Down Expand Up @@ -2648,7 +2642,6 @@
"steps",
"post-steps",
"features",
"disable-model-invocation",
"secrets",
"secret-masking",
"bots",
Expand Down
2 changes: 1 addition & 1 deletion docs/scripts/generate-autocomplete-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const ROOT_SORT_ORDER = [
'labels', 'metadata', 'tracker-id', 'source', 'run-name', 'runs-on',
'timeout-minutes', 'concurrency', 'environment', 'container', 'services',
'network', 'sandbox', 'plugins', 'if', 'steps', 'post-steps',
'features', 'disable-model-invocation', 'secrets',
'features', 'secrets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codemod infer-to-disable-model-invocation now produces invalid frontmatter: pkg/cli/codemod_infer_field.go is untouched by this PR and still rewrites infer: <bool>disable-model-invocation: <!bool>. Since disable-model-invocation is removed from the schema here, running gh aw fix --write on any workflow that contains infer: will inject an unknown field that immediately fails schema validation.

💡 Details

getInferToDisableModelInvocationCodemod() (line 86 of codemod_infer_field.go) unconditionally writes:

newLine := fmt.Sprintf("%sdisable-model-invocation: %v", indent, disableValue)

After this PR that field is gone from the schema, so the post-codemod file will fail ValidateMainWorkflowFrontmatterWithSchemaAndLocation. The codemod either needs to be:

  1. Updated to delete the infer field without producing a replacement (if the concept is gone entirely), or
  2. Retargeted at whatever the new canonical field is.

The ADR at docs/adr/33808-remove-deprecated-infer-field.md also documents disable-model-invocation as the permanent canonical form; that ADR needs to be superseded or noted as obsolete.

'secret-masking', 'bots', 'user-rate-limit', 'strict', 'safe-inputs',
'runtimes', 'jobs',
];
Expand Down
2 changes: 1 addition & 1 deletion pkg/constants/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ constants.PriorityJobFields // []string{"name","runs-on","needs","if","per
constants.PriorityWorkflowFields // []string{"on","permissions","if","network","imports",...}

// Fields silently ignored during frontmatter validation
constants.IgnoredFrontmatterFields // []string{"user-invokable"}
constants.IgnoredFrontmatterFields // []string{}

// Fields forbidden in shared/imported workflows (only valid in main workflows)
constants.SharedWorkflowForbiddenFields // []string{"on","concurrency","container",...}
Expand Down
3 changes: 1 addition & 2 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,7 @@ var PriorityJobFields = []string{"name", "runs-on", "needs", "if", "permissions"
var PriorityWorkflowFields = []string{"on", "permissions", "if", "network", "imports", "safe-outputs", "steps"}

// IgnoredFrontmatterFields are fields that should be silently ignored during frontmatter validation
// NOTE: user-invokable is a GitHub Copilot custom agent field that is not part of the gh-aw schema
var IgnoredFrontmatterFields = []string{"user-invokable"}
var IgnoredFrontmatterFields = []string{}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaks validation for contribution-checker.agent.md: removing user-invokable from IgnoredFrontmatterFields means the field is no longer silently stripped before schema validation, but .github/agents/contribution-checker.agent.md still declares user-invokable: false in its frontmatter.

💡 Details

Schema validation runs filterIgnoredFields(frontmatter) before passing the map to the JSON schema validator. The schema uses additionalProperties: false, so any key that is not explicitly defined will produce a validation error. Until contribution-checker.agent.md is updated (or until user-invokable is added to the schema as a valid field), any compile/validate run against that file will fail.

Either:

  1. Remove user-invokable: false from .github/agents/contribution-checker.agent.md in this PR, or
  2. Keep user-invokable in IgnoredFrontmatterFields until all in-repo consumers are cleaned up.
# Confirms the affected file
grep -r "user-invokable" .github/ --include="*.md"
# .github/agents/contribution-checker.agent.md:3:user-invokable: false


// SharedWorkflowForbiddenFields lists fields that cannot be used in shared/included workflows.
// These fields are only allowed in main workflows (workflows with an 'on' trigger field).
Expand Down
24 changes: 24 additions & 0 deletions pkg/parser/schema_location_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,27 @@ func TestValidateMainWorkflowFrontmatterWithSchemaAndLocation_RejectsTopLevelCom
t.Fatalf("expected unknown property error for command, got: %v", err)
}
}

func TestValidateIncludedFileFrontmatterWithSchemaAndLocation_SkipsCustomAgentFiles(t *testing.T) {
// Custom agent files may contain Copilot-specific fields that are not in the
// gh-aw main workflow schema (e.g. user-invokable, disable-model-invocation,
// tools as an array). Schema validation must be skipped for these files.
agentFrontmatter := map[string]any{
"description": "My custom agent",
"user-invokable": true,
"disable-model-invocation": false,
}

agentPaths := []string{
"/repo/.github/agents/my-agent.md",
".github/agents/my-agent.md",
"/some/path/.github/agents/sub/helper.md",
}

for _, path := range agentPaths {
err := ValidateIncludedFileFrontmatterWithSchemaAndLocation(agentFrontmatter, path)
if err != nil {
t.Errorf("expected custom agent file %q to pass validation without errors, got: %v", path, err)
}
}
}
12 changes: 0 additions & 12 deletions pkg/parser/schema_utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,6 @@ func TestFilterIgnoredFields(t *testing.T) {
"engine": "claude",
},
},
{
name: "frontmatter with user-invokable - should be filtered",
frontmatter: map[string]any{
"user-invokable": true,
"on": "push",
"engine": "claude",
},
expected: map[string]any{
"on": "push",
"engine": "claude",
},
},
}

for _, tt := range tests {
Expand Down
8 changes: 8 additions & 0 deletions pkg/parser/schema_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ func ValidateMainWorkflowFrontmatterWithSchemaAndLocation(frontmatter map[string
// ValidateIncludedFileFrontmatterWithSchemaAndLocation validates included file frontmatter with file location info
func ValidateIncludedFileFrontmatterWithSchemaAndLocation(frontmatter map[string]any, filePath string) error {
schemaValidationLog.Printf("Validating included file frontmatter: file=%s, fields=%d", filePath, len(frontmatter))

// Custom agent files (.github/agents/*.md) follow the Copilot agent format,
// which differs from the gh-aw workflow schema. Skip schema validation for them.
if isCustomAgentFile(filePath) {
schemaValidationLog.Printf("Skipping schema validation for custom agent file: %s", filePath)
return nil
}

// Filter out ignored fields before validation
filtered := filterIgnoredFields(frontmatter)

Expand Down
Loading