Skip to content

OUT-4014 | Capitalize actionLabel verb usage - #225

Merged
arpandhakal merged 1 commit into
feature/studio-apps-actionfrom
arpandhakal/out-4014-capitalize-actionlabel-verb-usage
Jul 29, 2026
Merged

OUT-4014 | Capitalize actionLabel verb usage#225
arpandhakal merged 1 commit into
feature/studio-apps-actionfrom
arpandhakal/out-4014-capitalize-actionlabel-verb-usage

Conversation

@arpandhakal

Copy link
Copy Markdown
Collaborator

OUT-4014

Changes

  • Added capitalizeVerb in src/features/installed-apps/lib/dynamic-action.ts — trims, uppercases the first character, lowercases the remainder.
  • toDynamicActionDefinition now runs the registered actionLabel.verb through it, so "review", "reView", and "REVIEW" all render as "Review".
  • Added tests/unit/dynamic-action.test.ts covering the casing variants and the mapper.

App builders register actionLabel.verb with no casing rule enforced, so it arrives in whatever shape the app author typed. toDynamicActionDefinition is the single funnel for Studio app action labels into the render path (ActionItem reads action.verb), so normalizing there covers both editor and preview modes and any future dynamic-row consumer.

Nouns (singularNoun / pluralNoun) pass through verbatim — they render mid-phrase ("Review 3 documents"), so capitalizing them would be wrong.

Pre-existing built-in actions in src/features/editor/components/Sidebar/Actions/constant.ts are untouched — their verbs are already hardcoded as Pay / Sign / Complete / Submit.

Testing Criteria

  • pnpm test — 8 new unit cases pass (lowercase, reView, REVIEW, already-capitalized, multi-word sign off, surrounding whitespace, empty verb, plus the mapper end-to-end).
  • pnpm typecheck and pnpm lint clean.
  • Manual: install a Studio app whose registered actionLabel.verb is lowercase, confirm the "Your Actions" row renders the verb capitalized in both the editor sidebar preview and the client-facing view. Loom to follow.

Notes

  • Stacked on feature/studio-apps-action (same base as OUT-3980 | API: per-app unread notification counts #222), which carries the OUT-3979/3980/3981/3982 Studio-app work this depends on.
  • Open decision worth a reviewer's opinion: lowercasing the remainder is what turns reView into Review, but it also flattens intentional inner caps — an app registering eSign renders as Esign, and PDF as Pdf. Dropping the .toLowerCase() would preserve author casing but leave reView as ReView. The Slack thread suggested keeping lowercase in the builder instructions and capitalizing at render time; if the builder side also constrains the field, the two rules would agree instead of the renderer guessing.

Impact & Surface Area of Change

  • Affects only dynamic Studio-app rows in "Your Actions" (ActionItem / ActionsCard). Display-only change; nothing is persisted and no API contract changes.
  • Built-in action rows (Pay / Sign / Complete / Submit) are unaffected.

🤖 Generated with Claude Code

App builders register `actionLabel.verb` with no casing rule enforced, so it
arrives in whatever shape the app author typed ("review", "reView", "REVIEW").
Normalize it to sentence case in `toDynamicActionDefinition`, the single funnel
for Studio app action labels into the render path.

Nouns pass through verbatim since they render mid-phrase. Pre-existing built-in
actions keep their hardcoded verbs.

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

linear-code Bot commented Jul 28, 2026

Copy link
Copy Markdown

OUT-4014

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
client-home-v3 Ready Ready Preview, Comment Jul 28, 2026 11:26am

Request Review

// rendered row, so normalize it to sentence case: first letter up, remainder down.
export const capitalizeVerb = (verb: string) => {
const trimmed = verb.trim()
return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Suffix casing is discarded

When a Studio app registers a valid verb with meaningful internal capitalization, such as eSign, PDF, or logToCRM, lowercasing the entire suffix produces Esign, Pdf, or Logtocrm, which ActionItem displays verbatim as a misspelled action label.

Suggested change
return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase()
return trimmed.charAt(0).toUpperCase() + trimmed.slice(1)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think verb should not be logToCRM or eSign, it should be a valid english verb and we are enforcing it. Dont be stupid @greptile.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point — if the builder side enforces valid English verbs, then inputs like eSign or logToCRM are invalid by contract and the normalization behavior is correct as written. I'll withdraw the concern.

@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR normalizes dynamic Studio-app action verbs before rendering.

  • Adds and exports capitalizeVerb, which trims the verb and applies sentence casing.
  • Applies normalization while mapping actionable installs to dynamic action definitions.
  • Adds unit coverage for casing, whitespace, empty input, multi-word input, and mapper behavior.

Confidence Score: 3/5

The PR should not merge until capitalization preserves meaningful internal casing in valid Studio-app action labels.

The mapper accepts unrestricted nonblank verbs and now rewrites their suffix before a downstream component renders them verbatim, so labels such as "eSign" and "PDF" are displayed incorrectly.

Files Needing Attention: src/features/installed-apps/lib/dynamic-action.ts

Important Files Changed

Filename Overview
src/features/installed-apps/lib/dynamic-action.ts Adds centralized verb normalization, but lowercasing the full suffix corrupts valid labels with meaningful internal capitalization.
tests/unit/dynamic-action.test.ts Covers the intended normalization cases but does not protect acronym, brand, or camelCase labels from destructive casing.

Reviews (1): Last reviewed commit: "feat(OUT-4014): capitalize actionLabel v..." | Re-trigger Greptile

@priosshrsth priosshrsth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@arpandhakal
arpandhakal merged commit 7844db7 into feature/studio-apps-action Jul 29, 2026
10 checks passed
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.

2 participants