Skip to content

Advertise typed workflow safe-output tools - #54817

Merged
pelikhan merged 13 commits into
mainfrom
copilot/dispatch-workflow-fix-typed-tool
Aug 23, 2026
Merged

Advertise typed workflow safe-output tools#54817
pelikhan merged 13 commits into
mainfrom
copilot/dispatch-workflow-fix-typed-tool

Conversation

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

dispatch-workflow, dispatch-repository, and call-workflow registered typed per-target MCP tools but advertised generic tool names in the agent prompt. This could steer agents to an untyped dispatch_workflow call and let an invalid output displace a corrected typed call.

  • Typed prompt manifest

    • List configured workflow and repository tool identifiers instead of generic names.
    • Preserve generic entries only for empty configurations.
    Tools: my_fixer, send_event, my_worker
    

    replaces:

    Tools: dispatch_workflow, dispatch_repository, call_workflow
    
  • Regression coverage

    • Extend dynamic-tool consistency checks across jobs, scripts, actions, dispatch workflows, repository dispatches, and reusable workflows.
    • Assert generic workflow tool names are absent whenever typed tools are configured.

Copilot AI and others added 6 commits August 22, 2026 14:05
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix dispatch-workflow to respect typed per-workflow tool Advertise typed workflow safe-output tools Aug 22, 2026
Copilot AI requested a review from pelikhan August 22, 2026 14:22
@pelikhan
pelikhan marked this pull request as ready for review August 22, 2026 14:27
Copilot AI balanced review requested due to automatic review settings August 22, 2026 14:27
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR does not have the implementation label and has 79 new lines of code in business logic directories (threshold: 100).

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship. Ponytail over-engineering review found nothing to cut: the typed/generic if-else branches for DispatchWorkflow, DispatchRepository, and CallWorkflow are minimal and non-redundant (each operates on a distinct config type), test additions are real regression coverage, and the schema.json change is a no-op key reorder.

Generated by Ponytail Reviewer for #54817

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-22T14:31:00Z
review_event: COMMENT
top_themes:
  - no actionable blocking issues found
  - typed safe-output tool names now match configured dispatch/call targets
files_reviewed:
  - .github/workflows/agentic_commands.yml
  - pkg/workflow/safe_outputs_prompt_tools_test.go
  - pkg/workflow/schemas/github-workflow.json
  - pkg/workflow/unified_prompt_step.go
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 9.7 AIC · ⌖ 6.77 AIC · ⊞ 7K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

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.

Verdict

Non-blocking change overall: the prompt now advertises typed safe-output tool identifiers and the regression tests cover the drift that caused the bug.

Highlights
  • buildSafeOutputsSections now lists configured dispatch/call tool identifiers instead of steering agents toward generic names.
  • The fallback to generic dispatch_workflow, dispatch_repository, and call_workflow when no typed targets are configured preserves backward compatibility.
  • The added tests cover jobs, scripts, actions, dispatch-workflow targets, dispatch-repository targets, and reusable workflow targets, which is the right regression surface for this fix.

I did not find a changed-line correctness or performance issue worth blocking this PR on.

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 9.7 AIC · ⌖ 6.77 AIC · ⊞ 7K
Comment /review to run again

Copilot AI left a comment

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.

Pull request overview

Updates agent prompts to advertise typed safe-output tools instead of generic workflow dispatch names.

Changes:

  • Lists normalized per-target workflow and repository tools.
  • Adds regression coverage for typed tool manifests.
  • Refreshes schema ordering and generated command routing.
Show a summary per file
File Description
pkg/workflow/unified_prompt_step.go Builds typed safe-output prompt entries.
pkg/workflow/safe_outputs_prompt_tools_test.go Tests typed tool advertisement.
pkg/workflow/schemas/github-workflow.json Reorders the drives permission schema.
.github/workflows/agentic_commands.yml Adds generated smoke-drive routing.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

pkg/workflow/unified_prompt_step.go:619

  • CallWorkflow.Max is enforced globally across all reusable-workflow targets by one handler counter (actions/setup/js/call_workflow.cjs:28,36,49). Annotating each typed target with the same (max:N) incorrectly presents that limit as per-target, so an agent can emit calls that the handler rejects once the shared budget is exhausted. Please represent the limit as shared across this tool family.
			for _, workflowName := range safeOutputs.CallWorkflow.Workflows {
				tools = append(tools, toolWithMaxBudget(stringutil.NormalizeSafeOutputIdentifier(workflowName), safeOutputs.CallWorkflow.Max))
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread pkg/workflow/unified_prompt_step.go Outdated
Comment on lines +600 to +601
for _, workflowName := range safeOutputs.DispatchWorkflow.Workflows {
tools = append(tools, toolWithMaxBudget(stringutil.NormalizeSafeOutputIdentifier(workflowName), safeOutputs.DispatchWorkflow.Max))

@github-actions github-actions Bot left a comment

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.

The logic for advertising typed workflow safe-output tool names is clean and correct:

  • When DispatchWorkflow.Workflows, CallWorkflow.Workflows, or DispatchRepository.Tools are non-empty, specific normalized tool names replace the generic dispatch_workflow/call_workflow/dispatch_repository in the prompt — exactly the right behaviour.
  • sliceutil.SortedKeys is correctly used for the map-keyed DispatchRepository.Tools to ensure deterministic output; slice-based Workflows preserve their natural declaration order, which is intentional.
  • Tests cover both the substitution behaviour and the consistency invariant (generic name must not appear when typed names are present).
  • The drives permission reordering in the JSON schema is a harmless alphabetical fix.

No blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 32.6 AIC · ⌖ 9 AIC · ⊞ 6.2K

@github-actions github-actions Bot left a comment

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.

Skills-Based Review 🧠

Applied /tdd and /codebase-design — requesting changes on two actionable issues.

📋 Key Themes & Highlights

Key Themes

  • Missing fallback tests: The backward-compat empty-Workflows/empty-Tools branches (which preserve the generic tool names) have no test coverage — a future regression would be silent.
  • Ordering inconsistency: DispatchRepository tools use sliceutil.SortedKeys (deterministic), but DispatchWorkflow and CallWorkflow iterate the slice in declaration order. Consider documenting or standardising.
  • Schema reorder side effect: The drives permission entry has been moved out of alphabetical position as a side effect of the schema fix.

Positive Highlights

  • ✅ Core fix is clean and well-scoped: typed tool names are only substituted when typed targets are present, preserving backward compat.
  • ✅ Consistency assertions in the test clearly specify the absence contract (assert.NotContains), which is exactly the right guard.
  • ✅ Using sliceutil.SortedKeys for the map case is a good defensive choice.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 41.7 AIC · ⌖ 11.2 AIC · ⊞ 7.6K
Comment /matt to run again

},
}

for _, tt := range tests {

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.

[/tdd] The empty-Workflows backward-compat fallback is not tested — if DispatchWorkflow is configured without any Workflows entries, the code falls back to the generic dispatch_workflow tool, but no test case exercises this path.

💡 Suggested test cases
{
    name: "empty Workflows falls back to generic dispatch_workflow",
    safeOutputs: &SafeOutputsConfig{
        DispatchWorkflow: &DispatchWorkflowConfig{Workflows: []string{}},
        NoOp: &NoOpConfig{},
    },
    expectedTools: []string{"dispatch_workflow", "noop"},
},
{
    name: "empty Tools falls back to generic dispatch_repository",
    safeOutputs: &SafeOutputsConfig{
        DispatchRepository: &DispatchRepositoryConfig{Tools: map[string]*DispatchRepositoryToolConfig{}},
        NoOp: &NoOpConfig{},
    },
    expectedTools: []string{"dispatch_repository", "noop"},
},
{
    name: "empty Workflows falls back to generic call_workflow",
    safeOutputs: &SafeOutputsConfig{
        CallWorkflow: &CallWorkflowConfig{Workflows: []string{}},
        NoOp: &NoOpConfig{},
    },
    expectedTools: []string{"call_workflow", "noop"},
},

Without these, a future refactor could accidentally drop the fallback branches with no test failure.

@copilot please address this.

if len(safeOutputs.DispatchWorkflow.Workflows) == 0 {
tools = append(tools, toolWithMaxBudget("dispatch_workflow", safeOutputs.DispatchWorkflow.Max))
} else {
for _, workflowName := range safeOutputs.DispatchWorkflow.Workflows {

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.

[/codebase-design] The DispatchWorkflow and CallWorkflow branches both iterate safeOutputs.X.Workflows with identical structure, but the DispatchRepository branch uses sliceutil.SortedKeys (deterministic) while the workflow loops use range order (non-deterministic map-equivalent for slices, but still not sorted). This inconsistency means the prompt tool list order for dispatch/call workflows can vary between Go versions or map iterations — and tools are order-sensitive in some downstream parsers.

Consider wrapping the slice loops in a sort or documenting why order is intentionally preserved (e.g., user-defined priority).

@copilot please address this.

"type": "string",
"enum": ["write", "none"]
},
"drives": {

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.

[/codebase-design] The drives permission entry has been moved out of alphabetical order — it now sits between vulnerability-alerts and watches instead of between discussions and id-token. This breaks the consistent alphabetical ordering of the rest of the permissions definitions and will make future diffs harder to read.

💡 Suggestion

If this move is intentional (e.g., drives is a non-standard permission that should be grouped at the end), add a brief comment explaining why. If unintentional, move drives back between discussions and id-token to restore alphabetical order.

@copilot please address this.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

@pelikhan Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub.

You can ask me to try again later by mentioning me in a new comment.

If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: 61d6d038-e12f-42d5-918c-5b3ad4466a5d

Sorry for the inconvenience!

Copilot AI and others added 2 commits August 22, 2026 22:04
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Completed the PR-finisher pass in 7e75071: shared workflow-family budgets are now advertised accurately, fallback coverage was added, generated workflows were refreshed, and local tests pass.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot this PR still needs forward progress.

Run: https://github.com/github/gh-aw/actions/runs/32605456597

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 12.2 AIC · ⌖ 8.33 AIC · ⊞ 9.5K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

@copilot this PR still needs forward progress.

  • Please address the failing checks on the current HEAD, refresh the branch if needed, and leave a concise maintainer handoff with commands and outcomes...

Fixed in ad32688. The failures came from tests still assuming the default AWF version was v0.28.5 after main intentionally reverted it to v0.28.4. Updated the default expectation and pinned v0.28.5 in filesystem emission cases.

Validation: targeted go test passed; make fmt, make lint, make test, and make recompile passed. make agent-report-progress passed build/schema/impacted tests but its package-wide custom-linter phase surfaced unrelated existing pkg/workflow lint debt. Code review and secret/CodeQL checks found no issues. CI needs a maintainer re-trigger on ad32688.

Copilot AI requested a review from gh-aw-bot August 22, 2026 23:52
@pelikhan
pelikhan merged commit 4e7ab73 into main Aug 23, 2026
32 checks passed
@pelikhan
pelikhan deleted the copilot/dispatch-workflow-fix-typed-tool branch August 23, 2026 00:06
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.87.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dispatch-workflow: untyped dispatch_workflow tool accepts empty args and displaces the typed per-workflow tool

4 participants