Add readiness_score_feedback as externally stored markdown field on WorkItems::AgentPlan

What does this MR do and why?

Adds readiness_score_feedback as an externally stored markdown field on WorkItems::AgentPlan, sharing the same object-storage blob as the existing content field.

Part of #617982 (closed) — MR 1 of 3 (model and persistence). MR 2 (GraphQL read) and MR 3 (GraphQL write) are stacked on this branch and target it; they will be retargeted to master once this merges.

What changes

  • ee/app/models/work_items/agent_plan.rb: adds cache_markdown_field :readiness_score_feedback, storage: :external, issuable_reference_expansion_enabled: true beside the existing content line, and a length validation reusing CONTENT_LENGTH_MAX.
  • ee/app/models/work_items/widgets/agent_plan.rb: delegates :readiness_score_feedback and :readiness_score_feedback_html through the widget, mirroring content and content_html. The _html delegation is what makes the cached rendering reachable from GraphQL; MR 2 exposes it as a markdown_field.
  • ee/app/services/work_items/data_sync/widgets/agent_plan.rb: adds a second MarkdownContentRewriterService call for :readiness_score_feedback on work-item move. The service rewrites one field per call, so the new field needs its own call.

How it works (no migration needed)

cache_markdown_field :x, storage: :external registers both x and x_html as virtual ActiveRecord attributes via externally_stored_field. build_external_payload serializes all registered fields into one JSON blob whose filename is deterministic (#{work_item_id}.json). A second field therefore reuses the same blob and the existing file_store column. Existing blobs that predate this field read back as nil (the loader does payload[field.to_s], so a missing key is nil).

Risk note

The external storage mechanism may shift underneath this work (see #616229 (comment 3694614696) and !249644 (merged)). This MR should be coordinated with that work before landing.

Concurrent-write note

persist_external_payload does an unlocked read-merge-write. With two externally stored markdown fields, concurrent refresh_markdown_cache! calls touching different fields on the same record could clobber each other. This is only reachable from refresh_markdown_cache! and is a pre-existing concern for content + content_html; adding a second field makes it slightly more likely. Flagging for awareness — not a blocker for this MR.

References

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Naman Jagdish Gala

Merge request reports

Loading
Loading