Skip to content

fix: escape Rich markup in workflow resolve output - #3879

Merged
mnriem merged 1 commit into
github:mainfrom
Noor-ul-ain001:fix/overlay-rich-markup
Jul 31, 2026
Merged

fix: escape Rich markup in workflow resolve output#3879
mnriem merged 1 commit into
github:mainfrom
Noor-ul-ain001:fix/overlay-rich-markup

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Problem

specify workflow resolve <id> prints its two summary sections through console.print, which has Rich markup enabled. Neither line escaped its interpolated fields.

1. The tier label never rendered — on every invocation.

f"  • [{layer.tier}] {layer.source} (priority={priority})"

Rich parses [base] and [project-overlay] as style tags, so the bracketed tier is swallowed. This needs no untrusted input; the column has simply never worked:

  •  project:ov1 (priority=10)     <- tier label missing
  •  base (priority=n/a)           <- tier label missing

2. Step IDs reach Rich as markup.

Step IDs come from base-workflow / overlay YAML and are validated only against : (_parse_edit in overlays/schema.py) — brackets pass validation. Two failure modes:

  • Balanced [stuff] is silently swallowed, so new[stuff] prints as new and the step appears to vanish.
  • Unbalanced [/red] raises rich.errors.MarkupError → uncaught traceback, exit 1. The workflow can't be inspected at all:
$ specify workflow resolve wf
...
Step attribution:
  • a: base
MarkupError: closing tag '[/red]' at position 7 doesn't match any open tag

Fix

Route the interpolated fields through rich.markup.escape and escape the literal tier bracket as \[. This matches the pattern already used by workflow info's step graph and workflow_list's \[disabled].

Display-only: the returned payload was already unescaped and is unchanged, so machine-readable callers see no difference.

Tests

Three regression tests in TestOverlayCli, all verified to fail without the fix:

  • test_workflow_resolve_prints_tier_labels — asserts [base] and [project-overlay] appear in output
  • test_workflow_resolve_escapes_rich_markup_in_step_id — parametrized over new[stuff] (swallowed) and new[/red] (crashes)

tests/workflows/test_overlay_commands.py passes 23/23. The wider tests/workflows/ suite shows 10 pre-existing failures, all symlink-permission tests that fail identically on a clean tree on Windows without elevation.

🤖 Generated with Claude Code

`workflow resolve` printed two lines through `console.print`, which has
Rich markup enabled, without escaping:

1. The layer tier was wrapped in literal brackets:
   `f"  • [{layer.tier}] {layer.source} ..."`. Rich parsed `[base]`
   and `[project-overlay]` as style tags, so the tier label was swallowed
   on *every* invocation -- no untrusted input required. The column has
   never rendered.

2. Step attribution interpolated `composed.step_id` raw. Step IDs come
   from base-workflow / overlay YAML and are only validated against `:`
   (see `_parse_edit`), so brackets pass validation. A balanced
   `[stuff]` is silently swallowed; an unbalanced `[/red]` raises
   `rich.errors.MarkupError`, producing an uncaught traceback and exit 1
   -- the workflow cannot be inspected at all.

Route the interpolated fields through `rich.markup.escape` and escape
the literal tier bracket as `\[`, matching the existing pattern in
`workflow info`'s step graph and `workflow_list`'s `\[disabled]`.

Only display is affected; the returned payload was already unescaped and
is unchanged.

Adds 3 regression tests, all of which fail without the fix: the tier
label renders, and a step ID survives both the swallowing and the
crashing markup cases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Assisted-by: Claude Opus 5 (1M context)

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

Fixes Rich markup handling in workflow resolve output.

Changes:

  • Escapes tier, source, and step-attribution values.
  • Adds regression tests for tier labels and bracket-containing step IDs.
Show a summary per file
File Description
src/specify_cli/workflows/overlays/_commands.py Escapes Rich markup in resolution summaries.
tests/workflows/test_overlay_commands.py Tests literal tiers and markup-like step IDs.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

@mnriem
mnriem merged commit 184de79 into github:main Jul 31, 2026
14 checks passed
@mnriem

mnriem commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Thank you!

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.

3 participants