Skip to content

update_pull_request cannot use replace-island, but update_issue can — shared helper, asymmetric enums #54906

Description

@blavity-machine-user

Summary

replace-island is reachable for update_issue but not for update_pull_request, even though the island-splicing logic lives in the shared body-update helper. The result is that a PR-body write can only be replace, append, or prepend — so any workflow that needs to update a section in place has to have the model regenerate the entire body, and a model that regenerates prose silently rewrites the parts it was not asked to touch.

Verified against main (latest release at time of writing: v0.86.2). Originally found on v0.81.6, and the gap is unchanged.

The asymmetry

pkg/workflow/js/safe_outputs_tools.jsonoperation enums:

Tool operation enum
update_issue replace, append, prepend, replace-island
update_pull_request replace, append, prepend
update_release replace, append, prepend

pkg/parser/schemas/main_workflow_schema.json agrees on the workflow-config side: update-pull-request.operation is ['append','prepend','replace'], so a caller cannot set it as a default either.

Meanwhile replace-island is implemented and exercised — it appears in pkg/workflow/safe_outputs_validation_config.go, in actions/setup/js/fuzz_update_body_harness.cjs, and in the compiled lock files of several workflows in this repo. So this reads as an enum that was extended for issues and not for pull requests, rather than a deliberate restriction.

Why it matters

Marker-delimited splicing is the only operation in that set that is deterministic. replace hands the model the job of reproducing everything it is not changing, and that is not a job models do reliably.

Concretely, with update-pull-request + replace, across 23 successful writes by one workflow:

  • 6 of 9 PRs lost human-authored content. Worst case: a 194-line description reduced to 74 — 167 lines gone.
  • The destructive writes correlated with splicing into an existing section (7 of 7), not with body length. Pure appends were harmless (0 lines removed).
  • Even non-lossy writes corrupted prose: bold markers moved so a sentence changed meaning, and hard-wrapped lines were reflowed.
  • Length-based detection would not catch it — one body kept every heading and near-identical character count while paraphrasing paragraphs away.

There is no prompt-level fix for this. "Echo the body back verbatim" is an instruction to the same component that is failing, and a deterministic splice is the only thing that removes the model from the copy path.

Ask

Expose replace-island for update_pull_request — in both safe_outputs_tools.json and main_workflow_schema.json — matching update_issue. If the omission is deliberate for pull requests, saying so in the docs would help, since the helper's presence suggests otherwise.

Happy to open a PR if a maintainer confirms the direction.

Related

#19347 was the same shape on a different surface: the handler and validation schema supported a field that the compiled tool schema never exposed, so the agent could not set it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions