Repository navigation
Closed
Labels
Description
The problem:
close_issue offers state_reason to the agent, but the safe-output validator strips it. Every close falls back to the first configured reason. Native duplicate marking only runs when duplicate is listed first.
Root cause:
computePropertyInjectionsinpkg/workflow/safe_outputs_tools_generation.goaddsstate_reasonto theclose_issuetool schema. This came from Allow close_issue agents to choose state-reason at runtime #47045.ValidationConfig["close_issue"]inpkg/workflow/safe_outputs_validation_config.godoesn't declarestate_reason.- Since Harden safe-output field validation #51133,
validateIteminactions/setup/js/safe_output_type_validator.cjskeeps only declared fields. Sostate_reasonis gone beforeclose_issue.cjsruns. close_issue.cjsthen usesallowed_state_reason[0]. If that isn'tduplicate, it logsduplicate_of is set but state_reason is completed (not DUPLICATE); native duplicate marking will be skipped.TestValidationConfigCoversToolInputSchemasmissed it. It checks the staticsafe_outputs_tools.json, not injected properties.
Impact:
state-reason: [duplicate, completed]closes every issue as duplicate.state-reason: [completed, duplicate]never closes an issue as duplicate.- The agent's choice is ignored either way.
Evidence:
We tested an issue triage workflow in a test repository:
- v0.85.4 (before Harden safe-output field validation #51133): about 25 duplicates closed as duplicate.
- v0.89.21 with
[duplicate, completed]: an issue that was already fixed closed as duplicate. The run loggedClosing issue #N with state_reason=duplicate, though the agent asked forcompleted. - v0.89.21 with
[completed, duplicate]: two real duplicates closed as completed. The run loggedClosing issue #N with state_reason=completed.
Local repro on main (86f7afc): calling validateItem on {type: "close_issue", issue_number: 2, duplicate_of: 1, state_reason: "duplicate"} returns no state_reason. Declaring the field returns state_reason: "duplicate".
Agentic plan:
- In
pkg/workflow/safe_outputs_validation_config.go, add this field toclose_issue:"state_reason": {Type: "string", Enum: closeIssueStateReasonValues}. Keep the values lowercase. The validator returns the declared casing, andwork_queue_delivery.cjscomparesstate_reasonto the GitHub API value with strict equality. - In
pkg/workflow/safe_output_validation_config_test.go, add a test that callscomputePropertyInjectionsforclose_issue(omitted and liststate-reason) andsubmit_pull_request_review(withallowed-events). Assert every injected property exists inValidationConfig[tool].Fields. - In
actions/setup/js/safe_output_type_validator.test.cjs, assert aclose_issueitem withstate_reason: "DUPLICATE"keepsstate_reason: "duplicate"aftervalidateItem. - Recompile lock files and run
make agent-finish.
Acceptance criteria:
- An agent-selected
state_reasonreachesclose_issue.cjs. - With
state-reason: [completed, duplicate], an agent that picksduplicatewithduplicate_ofgets a native duplicate mark. - The new test fails if any injected property lacks a validation entry.
Other handlers checked:
close_discussion.reason: declared.close_pull_request: no reason field.submit_pull_request_review.event: declared.
Only close_issue.state_reason has the gap.
Reacted by Copilot
Activity