Skip to content

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

Open
myieye wants to merge 3 commits intodevelopfrom
claude/investigate-field-id-conflicts-RfYJq
Open

Namespace field IDs by entity type to prevent naming collisions#2171
myieye wants to merge 3 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

📝 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 docstrings
🧪 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   50 suites  ±0   26s ⏱️ +3s
138 tests ±0  138 ✅ ±0  0 💤 ±0  0 ❌ ±0 
203 runs  ±0  203 ✅ ±0  0 💤 ±0  0 ❌ ±0 

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

♻️ 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 16, 2026, 10:46 AM

@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 {

example: IExampleSentence;
readonly?: boolean;
onchange?: (sense: IExampleSentence, field: FieldId) => void;
onchange?: (sense: IExampleSentence, field: ExampleFieldId) => void;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading parameter name: sense should be example.

The onchange callback parameter is named sense but its type is IExampleSentence. This appears to be a copy-paste artifact from the sense editor.

Proposed fix
-    onchange?: (sense: IExampleSentence, field: ExampleFieldId) => void;
+    onchange?: (example: IExampleSentence, field: ExampleFieldId) => void;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onchange?: (sense: IExampleSentence, field: ExampleFieldId) => void;
onchange?: (example: IExampleSentence, field: ExampleFieldId) => void;
🤖 Prompt for AI Agents
In
`@frontend/viewer/src/lib/entry-editor/object-editors/ExampleEditorPrimitive.svelte`
at 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).

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