Skip to content

AI support copilot Phase 3: content edits on Nova-managed records#3582

Merged
bernardhanna merged 1 commit into
ai-support-copilot-phase2from
ai-support-copilot-phase3
Jun 23, 2026
Merged

AI support copilot Phase 3: content edits on Nova-managed records#3582
bernardhanna merged 1 commit into
ai-support-copilot-phase2from
ai-support-copilot-phase3

Conversation

@bernardhanna

Copy link
Copy Markdown
Collaborator

Summary

Stacked on #3578 (Phase 2). Adds Phase 3: the copilot can make editorial text changes to allowlisted content records (Nova resources) through the same dry-run → APPROVE → execute → report pipeline. Because they're Nova resources, a reviewer can also tweak them by hand. Disabled by default (SUPPORT_AI_CONTENT_ENABLED=false).

  • Model allowlist (ContentActionRegistry): pages, homepage slides, FAQ items, menus, events, podcasts, partners, etc. Page singletons resolve automatically; other records by id or a unique field.
  • Text fields only (ContentFieldResolver): editable columns resolved at runtime to string/text columns minus a structural deny-list (URLs, slugs, flags, relations, identifiers, SEO/keyword/category) and minus non-string casts (bool/array/date/int). No hand-maintained per-model column list.
  • Value guards (ContentUpdateService): rejects URLs, www. refs, HTML/markup, and over-length; protects Laravel translation-key fields (e.g. hackathons.hero.title).
  • Exact diff + re-validation: diagnostics computes a before→after diff (shown in the approval email); execution re-runs the full plan/validation before saving — never trusts the stored payload. Completion email shows the applied before→after.
  • Triage gains the content_update case type (only offered when enabled). setup-check reports content status; allowed_write_actions includes content_update.

Review notes

Test plan

  • vendor/bin/phpunit tests/Unit/Support/ContentUpdateServiceTest.php (9 tests) green
  • With SUPPORT_AI_CONTENT_ENABLED=true: a copy-fix ticket triages as content_update; dry-run email shows the field-level before→after
  • APPROVE applies the change; completion email shows before→after; record reflects it in Nova
  • URLs / HTML / translation-key fields / non-text columns are rejected
  • With the flag off, content_update is never offered and the service fails safe

Made with Cursor

Lets the support copilot make editorial text changes to allowlisted content
records through the same dry-run -> APPROVE -> execute -> report pipeline.
Records are Nova resources, so a human can also review/tweak them there.
Disabled by default (SUPPORT_AI_CONTENT_ENABLED=false).

- ContentActionRegistry: allowlist of editable content models (pages, slides,
  FAQ items, menus, events, podcasts, partners, ...). Page singletons resolve
  automatically; other records by id or a unique lookup field.
- ContentFieldResolver: editable columns resolved at runtime to string/text
  columns minus a structural deny-list (URLs, slugs, flags, relations,
  identifiers, SEO/keyword/category) and minus non-string casts. No per-model
  column list to maintain.
- ContentUpdateService: text-only value guards (rejects URLs, www refs, HTML/
  markup, over-length), protects Laravel translation-key fields, computes an
  exact before/after diff for the approval email, and re-validates at execution
  time rather than trusting the stored payload.
- Triage gains the content_update case type (only offered when enabled) plus
  content_model/content_identifier/content_changes/content_summary.
- Wired into diagnostics (before/after preview), approval email (diff),
  execute job, and completion email; setup-check reports content status;
  allowed_write_actions includes content_update.
- Unit tests for value guards, registry, and pre-DB plan validation; docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bernardhanna bernardhanna merged commit 95e28df into ai-support-copilot-phase2 Jun 23, 2026
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.

1 participant