Skip to content

fix(actions): resolve the declared nameField for record_label, unify the log_call/log_meeting twins - #569

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-514-global-actions-323dje
Jul 31, 2026
Merged

fix(actions): resolve the declared nameField for record_label, unify the log_call/log_meeting twins#569
yinlianghui merged 1 commit into
mainfrom
claude/issue-514-global-actions-323dje

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Description

Two items from #514, both confined to src/actions/global.actions.ts. Each was re-verified against current main before being touched — both still reproduce.

Item 2 — record_label is null. The activity writers stamped record_label: ctx.record?.name, but name is not the display field on almost anything in this app. Verified against the current object definitions: 14 of the 15 objects declare a nameField other than name (display_title, full_name, subject, contract_number, member_number), and most have no name column at all — crm_case included, which is the object both actions are scoped to today. Every logged call and meeting therefore landed on the unified timeline with a null label. The bodies now resolve the object's declared nameField through a map derived from the object definitions themselves, so it cannot drift when an object retargets its nameField, and it keeps working if these actions are restored to the global design their own comments describe. Formula nameFields resolve fine — the data engine materialises formula fields on read (applyFormulaPlan), so the loaded ctx.record carries display_title alongside the stored columns.

Item 15 (the global.actions.ts half) — the twins. log_call and log_meeting were near-verbatim copies differing only in a summary prefix and a metadata key, and had quietly stopped agreeing on whether duration is required (yes for calls, no for meetings, undocumented either way). Everything they share now comes from one builder, and duration is optional on both — the direction that keeps both forms submittable and the one the shared body was already written for, since its duration ? … : subject summary branch was unreachable while the field was mandatory.

The opportunity_line_item / quote_line_item hook half of item 15, and every other item in #514, are untouched.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • CI/CD update

Related Issues

Related to #514 (items 2 and 15-half only — this PR deliberately does not close the issue)

Changes Made

  • record_label now reads the object's declared nameField via NAME_FIELD_BY_OBJECT, derived from src/objects rather than hand-listed, instead of the hardcoded .name column.
  • objectName resolution in the body also checks ctx.object (the name the sandbox context actually carries) — the label lookup is only as good as that value.
  • log_call / log_meeting are built from one logActivityAction(spec) factory; a LogActivitySpec type is the complete list of what a twin may still differ on (icon, labels, summary prefix, metadata.kind + per-kind extras, extra params).
  • duration is required: false on both actions. Params, locations, capabilities, timeoutMs and refreshAfter are now single-sourced.
  • New test/global-actions.test.ts (a new file rather than an append to the high-traffic test/metadata-references.test.ts).
  • Changeset added: .changeset/activity-actions-record-label-and-twins.md.

Testing

  • Unit tests pass (pnpm test) — 22 files, 400 passed / 2 skipped
  • Linting passes (pnpm lint)
  • Build succeeds (pnpm build)
  • Manual testing completed
  • New tests added

pnpm verify (validate → typecheck → lint → hygiene → build → test) exits 0.

The new tests execute the action bodies against a recording ctx rather than regex-matching the source, so they pin behavior rather than the fix's spelling — #514 item 17 notes that actions were only ever regex-checked. Five of the 18 assertions fail against the pre-fix source (confirmed by stashing only src/actions/global.actions.ts and re-running):

  • record_label resolves to the declared nameField for every object that declares one, plus a meta-assertion that most nameFields are not name so the guard cannot go vacuous.
  • crm_case is labelled by display_title (the pre-fix path returned null).
  • Missing label field, and an unregistered object, yield null instead of throwing.
  • The twins agree on duration requiredness, on the subject/notes core, and on every dispatch-level declaration; attendees is the only param the meeting adds.
  • Both emit an identical activity row apart from the summary prefix and per-kind metadata, and both drop the (N min) suffix when duration is omitted — a branch that was dead code for log_call.

Not a sandbox-accurate harness: the real runtime executes the source under QuickJS, this is new Function over the same string. That gap is #514 item 17 and is left open.

Screenshots

n/a — no UI surface changed. The visible effect is that timeline entries for logged calls/meetings now show the record's title instead of a blank label.

Checklist

  • I have added a changeset (pnpm changeset)
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

No translation changes were needed: param labels are unchanged, and the locale packs guard only label / confirmText / successMessage, all of which keep their existing values.

Choosing optional for duration rather than required is the one judgement call here. Tightening meetings to required would be a UX regression on a form that has shipped; loosening calls matches the body's own fallback and is non-breaking in both directions.


Generated by Claude Code

…the log twins

`log_call` / `log_meeting` stamped `record_label: ctx.record?.name`, but `name`
is not the display field on almost anything here: 14 of 15 objects declare a
different `nameField` (`display_title`, `full_name`, `subject`,
`contract_number`, …) and most have no `name` column at all — including
`crm_case`, the object both actions are scoped to. Every logged call and
meeting therefore landed on the timeline with a null label. The bodies now
resolve the object's declared `nameField` through a map derived from the object
definitions, so it cannot drift and it survives a restore of the global design
these actions document.

The two actions were also near-verbatim copies that had quietly stopped
agreeing on whether `duration` is required (yes for calls, no for meetings,
undocumented either way). Everything they share — body, dispatch declarations,
the subject/duration/notes param core — now comes from one builder, and
`duration` is optional on both, which is what the shared body was already
written for: its `duration ? … : subject` summary branch was unreachable while
the field was mandatory.

Adds `test/global-actions.test.ts`, which EXECUTES the bodies instead of
regex-matching them (a new file rather than an append to the high-traffic
`test/metadata-references.test.ts`). It asserts the label resolves for every
object declaring a `nameField`, and that the twins emit the same activity row
apart from the summary prefix and per-kind metadata. Five of its assertions
fail against the pre-fix source.

Refs #514.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016YKtPTGAZEycQ2bt4BmtpK
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Jul 31, 2026 8:37am

Request Review

@yinlianghui
yinlianghui marked this pull request as ready for review July 31, 2026 08:47
@yinlianghui
yinlianghui merged commit e2611db into main Jul 31, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants