Skip to content

Namespace field IDs by entity type to prevent naming collisions#2171

Merged
myieye merged 4 commits intodevelopfrom
claude/investigate-field-id-conflicts-RfYJq
Feb 19, 2026
Merged

Namespace field IDs by entity type to prevent naming collisions#2171
myieye merged 4 commits intodevelopfrom
claude/investigate-field-id-conflicts-RfYJq

Conversation

@myieye
Copy link
Collaborator

@myieye myieye commented Feb 16, 2026

This PR namespaces field IDs by entity type to prevent naming collisions.
This puts us in a better place to safely persist custom views that handle future naming collisions.

Split the flat FieldId union into EntryFieldId, SenseFieldId, and
ExampleFieldId, keeping FieldId as the backward-compatible union.
Restructure ViewFields from a flat Record<FieldId, FieldView> to a
nested { entry, sense, example } structure so field IDs are scoped
per entity type. This prevents naming collisions when persisting
custom view configurations and prepares for the CustomView backend
model with separate field arrays per entity type.

https://claude.ai/code/session_01NVUuxxWYXoQym9zB9A1UM7
These were only used by FW_CLASSIC_VIEW which now uses showAllFields.
recursiveSpread is kept for future custom view definitions.

https://claude.ai/code/session_01NVUuxxWYXoQym9zB9A1UM7
@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR refactors the field type system from a flat structure in field-data.ts to a nested entity-based structure in views/fields.ts. Multiple editor components are updated to import from the new location, use entity-specific field types (EntryFieldId, SenseFieldId, ExampleFieldId), and leverage a derived fields pattern for accessing field configurations per entity.

Changes

Cohort / File(s) Summary
Field Type System Refactoring
frontend/viewer/src/lib/entry-editor/field-data.ts, frontend/viewer/src/lib/views/fields.ts
Deleted flat field-data.ts and introduced new nested views/fields.ts with entity-specific field types and structured fieldData (entry, sense, example categories).
Editor Component Updates
frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte, ExampleEditorPrimitive.svelte, SenseEditorPrimitive.svelte
Updated to use entity-specific field types (EntryFieldId, ExampleFieldId, SenseFieldId), added derived fields pattern ($derived($currentView.fields.entry/sense/example)), and refactored field references to use nested fieldData structure.
View System Updates
frontend/viewer/src/lib/views/OverrideFields.svelte, view-data.ts, view-service.ts
Changed from flat Record<FieldId, FieldView> to nested ViewFields structure (entry, sense, example). Updated objectTemplateAreas signature and field override logic to work with EntityViewFields.
Import Path Updates
frontend/viewer/src/lib/components/editor/field/field-root.svelte, frontend/viewer/src/lib/sandbox/EditorSandbox.svelte, Sandbox.svelte, frontend/viewer/src/project/tasks/tasks-service.ts, frontend/viewer/src/stories/editor/fields/FieldDecorator.svelte
Updated FieldId and fieldData imports from entry-editor/field-data to views/fields; updated helpId access paths to reflect nested fieldData structure (e.g., fieldData.sense.definition.helpId).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • hahn-kev

Poem

🐰 Fields reorganized, nested and clean,
From flat to structured, a better scene,
Entity types now have their own space,
Each editor component finds its place! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: field IDs are now namespaced by entity type (entry, sense, example) to prevent naming collisions, which is the primary focus of this refactoring PR.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of namespacing field IDs by entity type to prevent naming collisions and enable safe custom view persistence.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/investigate-field-id-conflicts-RfYJq

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label Feb 16, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

UI unit Tests

 1 files  ±  0   3 suites   - 47   0s ⏱️ -23s
10 tests  - 128  10 ✅  - 128  0 💤 ±0  0 ❌ ±0 
10 runs   - 193  10 ✅  - 193  0 💤 ±0  0 ❌ ±0 

Results for commit d4b9f37. ± Comparison against base commit b04aee5.

This pull request removes 138 and adds 10 tests. Note that renamed tests count towards both.
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > accepts parent values when not dirty
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > does NOT guard against stomping deep changes, because StompGuard can't detect them
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > ignores parent values when dirty
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > initializes with the parent value
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > keeps subscribers up to date when it becomes dirty
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > pushs changes to parent
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > reverts new parent values when ignored
src/lib/components/stomp/stomp-guard.svelte.test.ts ‑ StompGuard > starts accepting parent changes again after a flush
src/lib/components/ui/format/format-duration.test.ts ‑ formatDuration > formats durations
src/lib/components/ui/format/format-duration.test.ts ‑ formatDuration > formats durations with smallest unit
…
src/index.test.ts ‑ password hashing > can hash a pw using sha1
src/lib/i18n/i18n.test.ts ‑ buildRegionalLocaleRegex > should find all regional locales for available locales
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return en by default
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return en if no user locale is provided and acceptLanguageHeader does not have any supported locales
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return regional locale from acceptLanguageHeader if it has a higher quality rating than the regionless locale
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return supported locale from acceptLanguageHeader with highest quality rating if no user locale is provided
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return user locale if acceptLanguageHeader does not provide a regional/more specific locale
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return user locale if acceptLanguageHeader does not provide a regional/more specific locale with a higher quality rating
src/lib/i18n/i18n.test.ts ‑ pickBestLocale > should return user locale if acceptLanguageHeader is not provided
src/lib/user.test.ts ‑ jwtToUser > should convert a jwt token to a LexAuthUser

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

C# Unit Tests

160 tests  ±0   160 ✅ ±0   18s ⏱️ ±0s
 23 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 11a3a54. ± Comparison against base commit b04aee5.

♻️ This comment has been updated with latest results.

@argos-ci
Copy link

argos-ci bot commented Feb 16, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Feb 19, 2026, 12:46 PM

@myieye myieye force-pushed the claude/investigate-field-id-conflicts-RfYJq branch from c6bda6a to 11a3a54 Compare February 16, 2026 10:44
@myieye myieye marked this pull request as ready for review February 16, 2026 10:48
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@frontend/viewer/src/lib/entry-editor/object-editors/ExampleEditorPrimitive.svelte`:
- Line 18: The parameter name in the onchange callback is misleading: change the
first parameter name from sense to example in the signature "onchange?: (sense:
IExampleSentence, field: ExampleFieldId) => void;" so it reads something like
"onchange?: (example: IExampleSentence, field: ExampleFieldId) => void;" (update
any local references/usages in ExampleEditorPrimitive.svelte that refer to the
old name to match the new parameter name).
🧹 Nitpick comments (3)
frontend/viewer/src/lib/views/OverrideFields.svelte (2)

39-47: overrideEntityFields applies a flat FieldId[] across all entity types, partially undermining the namespacing goal.

shownFields is a mixed FieldId[] applied identically to entry, sense, and example fields. While this works because includes() simply returns false for non-matching keys, it means a sense-only field like 'gloss' is needlessly checked against entry fields, and vice versa. If a naming collision is ever introduced (the scenario this PR guards against), this function would incorrectly show/hide fields across entity boundaries.

Consider accepting per-entity shown fields to match the nested structure:

Suggested approach
  interface Props {
-   shownFields?: FieldId[];
+   shownFields?: {
+     entry?: EntryFieldId[];
+     sense?: SenseFieldId[];
+     example?: ExampleFieldId[];
+   };
    respectOrder?: boolean;
    overrides?: Overrides;
    children?: Snippet;
  }

This would make the override truly namespace-aware. If this is deferred, at minimum add a comment explaining why the flat list is safe today.


40-46: Unsafe as T cast on Object.fromEntries result.

Object.fromEntries(...) returns { [k: string]: ... }, which is then cast to T (the specific entity fields type). This silently erases type safety — if a key is missing or extra keys are introduced, TypeScript won't flag it. This is a known TypeScript limitation with Object.fromEntries, so the cast is pragmatic, but worth noting as a trade-off.

frontend/viewer/src/lib/views/view-data.ts (1)

72-79: mergeFields override parameter type is looser than necessary.

The overrides parameter accepts any FieldId key regardless of entity type, so you could accidentally pass e.g. {sentence: ...} when merging entry fields without a type error. Since this is a private helper and callers are well-typed, it's not a bug today, but tightening the signature would catch mistakes if usage expands.

Suggested tightening
-function mergeFields<T>(base: T, overrides?: Partial<Record<FieldId, Partial<FieldView>>>): T {
+function mergeFields<T extends EntityViewFields>(base: T, overrides?: Partial<Record<keyof T & string, Partial<FieldView>>>): T {

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@myieye myieye merged commit 3eefb78 into develop Feb 19, 2026
15 checks passed
@myieye myieye deleted the claude/investigate-field-id-conflicts-RfYJq branch February 19, 2026 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments