Skip to content

feat: replace dialogueStyle with notes on characters#261

Merged
mikkisguy merged 3 commits into
mainfrom
257-replace-dialoguestyle-with-notes
Jul 6, 2026
Merged

feat: replace dialogueStyle with notes on characters#261
mikkisguy merged 3 commits into
mainfrom
257-replace-dialoguestyle-with-notes

Conversation

@mikkisguy

@mikkisguy mikkisguy commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Closes #257

What changed

Replaced the underused dialogueStyle free-text field (100 chars, no clear purpose) with a larger notes textarea (10,000 chars) for arbitrary author notes per character.

Database

  • Schema: dialogue_stylenotes (text)
  • Migration 0051 generated via db:generate — uses RENAME COLUMN to preserve existing data

All layers updated

  • Shared types, Zod validation, backend service (CharacterSummary + CharacterDetail), frontend API types, hooks, form state
  • CharacterEditDialog: dialogueStyle input removed, notes textarea added (min-h 250px)
  • CharacterList + LabelPropertiesPanel: Style: badge removed
  • listCharacters endpoint now includes notes and conditionalPrefix (fixing a pre-existing bug where conditional prefix badge was always hidden)

How verified

  • All 2,099 tests pass (810 unit + 861 frontend + 428 integration)
  • Typecheck and lint green across all packages
  • Full-codebase grep confirms zero remaining dialogueStyle/dialogue_style references
  • Migration snapshot confirmed by Drizzle

@oracle review

Reviewed and approved. Two should-fix items (stale comments, leftover grid-cols-3) addressed before opening PR.

Summary by CodeRabbit

  • New Features

    • Characters now use Notes instead of Dialogue Style across the app.
    • The character editor now provides a Notes textarea, and lists/detail views show Notes.
  • Bug Fixes

    • Updated create, edit, import, and API responses to keep the Notes field consistent end-to-end.
    • Validation now supports longer Notes (up to 10,000 characters).
  • Documentation

    • Refreshed database schema documentation for the updated characters field list.

- Remove dialogue_style column from characters schema, add notes (text)
- Migration 0051: rename dialogue_style to notes (db:generate)
- Update Character shared type, validation, service, API types, hooks
- Replace dialogueStyle input with notes textarea in CharacterEditDialog
- Remove Style badge from CharacterList and LabelPropertiesPanel
- Update all test fixtures and DATABASE_SCHEMAS.md
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
branchforge-docs Ready Ready Preview, Comment Jul 6, 2026 7:38pm

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

React Doctor found 1 new issue in 1 file · 1 warning · score 90 / 100 (Great) · 0 fixed · vs main

1 warning

src/components/CharacterEditDialog.tsx

  • ⚠️ L563 Control missing accessible label control-has-associated-label

Reviewed by React Doctor for commit d95f72b. See inline comments for fixes.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mikkisguy, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d1cb7e3-76ee-4ee0-8d35-9473b3df7a43

📥 Commits

Reviewing files that changed from the base of the PR and between 1b49085 and d95f72b.

📒 Files selected for processing (1)
  • .changeset/strict-animals-judge.md
📝 Walkthrough

Walkthrough

The dialogueStyle character field is renamed to notes across the database, backend, frontend, and shared types. The edit form now uses a notes textarea, display components stop rendering the style text, and tests/docs/migration metadata are updated accordingly.

Changes

dialogueStyle to notes rename

Layer / File(s) Summary
Database schema and migration
apps/backend/src/db/schema/tables/characters.ts, apps/backend/src/db/migrations/0051_same_blur.sql, apps/backend/src/db/migrations/meta/_journal.json, docs/DATABASE_SCHEMAS.md
The characters schema, migration, journal, and docs now use notes instead of dialogue_style.
Shared types and validation contracts
packages/shared/src/index.ts, apps/backend/src/lib/validation.ts, apps/backend/src/lib/__tests__/validation.unit.test.ts
Character, create/update schemas, and validation tests now use notes, with a 10,000-character limit.
Backend characters service and route tests
apps/backend/src/services/characters.service.ts, apps/backend/src/services/__tests__/characters.service.unit.test.ts, apps/backend/src/routes/__tests__/characters.*.test.ts
Service mappings, return shapes, fixtures, request bodies, and response assertions now use notes throughout list/detail/create/update flows.
Frontend API, hooks, UI, and tests
apps/frontend/src/lib/api/characters.ts, apps/frontend/src/hooks/useCharacters.ts, apps/frontend/src/components/CharacterEditDialog.tsx, apps/frontend/src/components/CharacterList.tsx, apps/frontend/src/components/write-mode/LabelPropertiesPanel.tsx, apps/frontend/src/components/__tests__/*, apps/frontend/src/components/script-mode/__tests__/*, apps/frontend/src/components/write-mode/__tests__/*, apps/frontend/src/hooks/__tests__/*
Frontend request types, hooks, form state, rendering, and test fixtures now use notes instead of dialogueStyle.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • mikkisguy/branchforge#105: The backend service and character route structure changed in ways this rename now updates.
  • mikkisguy/branchforge#168: The LabelPropertiesPanel rendering removed here overlaps with the component introduced in that PR.
  • mikkisguy/branchforge#178: The CharacterEditDialog field handling and payload wiring changed in the same area modified by that PR.

Suggested labels: priority:medium

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title concisely describes the main change: replacing character dialogueStyle with notes.
Linked Issues check ✅ Passed The PR removes dialogueStyle and adds nullable notes across schema, types, validation, services, UI, tests, and docs as requested in #257.
Out of Scope Changes check ✅ Passed The changes stay focused on the character notes migration and related UI, type, and test updates with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 257-replace-dialoguestyle-with-notes

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
apps/backend/src/lib/__tests__/validation.unit.test.ts (1)

1015-1030: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add boundary tests for the 10,000-char notes limit.

The rename is correct, but no test asserts the new max-length requirement itself (accepting exactly 10,000 chars, rejecting 10,001+). Since "support notes up to 10,000 characters" is an explicit PR requirement, a boundary test would guard the optionalString(10000) constraint.

✅ Suggested additional tests
     it("should accept valid full character payload", () => {
       ...
     });
+
+    it("should accept notes at the 10,000 character limit", () => {
+      const validData = {
+        projectId: "550e8400-e29b-41d4-a716-446655440000",
+        name: "Character Name",
+        displayName: "Display Name",
+        renpyTag: "char",
+        color: "`#FF5733`",
+        notes: "a".repeat(10000),
+      };
+      const result = createCharacterSchema.safeParse(validData);
+      expect(result.success).toBe(true);
+    });
+
+    it("should reject notes exceeding 10,000 characters", () => {
+      const invalidData = {
+        projectId: "550e8400-e29b-41d4-a716-446655440000",
+        name: "Character Name",
+        displayName: "Display Name",
+        renpyTag: "char",
+        color: "`#FF5733`",
+        notes: "a".repeat(10001),
+      };
+      const result = createCharacterSchema.safeParse(invalidData);
+      expect(result.success).toBe(false);
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/lib/__tests__/validation.unit.test.ts` around lines 1015 -
1030, The createCharacterSchema validation tests currently cover a valid payload
but do not verify the notes length boundary added by optionalString(10000). Add
focused tests in validation.unit.test.ts near the createCharacterSchema suite to
assert that notes with exactly 10,000 characters is accepted and 10,001
characters is rejected, keeping the existing valid full character payload test
intact.
apps/backend/src/services/characters.service.ts (1)

53-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

CharacterSummary and CharacterDetail are now identical.

After this rename both interfaces have the exact same fields (id, name, displayName, renpyTag, color, routeAffiliation, isLoveInterest, isNarrator, notes, conditionalPrefix, avatarUrl). Consider consolidating to avoid future drift.

♻️ Suggested consolidation
-export interface CharacterDetail {
-  id: string;
-  name: string;
-  displayName: string;
-  renpyTag: string;
-  color: string;
-  routeAffiliation: string | null;
-  isLoveInterest: boolean;
-  isNarrator: boolean;
-  notes: string | null;
-  conditionalPrefix: string | null;
-  avatarUrl: string | null;
-}
+export type CharacterDetail = CharacterSummary;

Also applies to: 68-80

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/services/characters.service.ts` around lines 53 - 65,
`CharacterSummary` and `CharacterDetail` now have the same shape, so the service
should be consolidated to avoid duplicated definitions and future drift. Update
`characters.service.ts` to use a single shared type (or derive one from the
other) for the identical fields, and adjust any references in
`CharacterSummary`/`CharacterDetail` usage so both names no longer carry
separate field lists.
apps/frontend/src/components/CharacterEditDialog.tsx (1)

140-163: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

No client-side length guard for the 10,000-char notes limit.

The notes textarea and validateForm don't enforce the 10,000-character limit mentioned in the PR objectives. Users can type past the backend limit and only find out via a generic save-failure toast, with no inline indication of which field/why.

♻️ Suggested guard
+const NOTES_MAX_LENGTH = 10000;
+
 function validateForm(state: CharacterFormState): {
   valid: boolean;
   errors: Record<string, string>;
 } {
   const errors: Record<string, string> = {};
   ...
+  if (state.notes.length > NOTES_MAX_LENGTH) {
+    errors.notes = `Notes must be ${NOTES_MAX_LENGTH} characters or fewer`;
+  }
   return { valid: Object.keys(errors).length === 0, errors };
 }
             <textarea
               id="edit-char-notes"
               rows={4}
+              maxLength={NOTES_MAX_LENGTH}
               className="..."
               placeholder="Backstory, personality notes, voice references..."
               value={form.notes}
               onChange={(e) => handleFieldChange("notes", e.target.value)}
               disabled={isSaving}
             />

Also applies to: 548-561

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/frontend/src/components/CharacterEditDialog.tsx` around lines 140 - 163,
Add a client-side length check for the notes field in CharacterEditDialog so the
form enforces the 10,000-character limit before save. Update validateForm to
validate the notes value in CharacterFormState and set an inline errors.notes
message when it exceeds the limit, and ensure the notes textarea in the dialog
reflects that constraint so users get immediate feedback instead of a generic
save failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/backend/src/lib/__tests__/validation.unit.test.ts`:
- Around line 1015-1030: The createCharacterSchema validation tests currently
cover a valid payload but do not verify the notes length boundary added by
optionalString(10000). Add focused tests in validation.unit.test.ts near the
createCharacterSchema suite to assert that notes with exactly 10,000 characters
is accepted and 10,001 characters is rejected, keeping the existing valid full
character payload test intact.

In `@apps/backend/src/services/characters.service.ts`:
- Around line 53-65: `CharacterSummary` and `CharacterDetail` now have the same
shape, so the service should be consolidated to avoid duplicated definitions and
future drift. Update `characters.service.ts` to use a single shared type (or
derive one from the other) for the identical fields, and adjust any references
in `CharacterSummary`/`CharacterDetail` usage so both names no longer carry
separate field lists.

In `@apps/frontend/src/components/CharacterEditDialog.tsx`:
- Around line 140-163: Add a client-side length check for the notes field in
CharacterEditDialog so the form enforces the 10,000-character limit before save.
Update validateForm to validate the notes value in CharacterFormState and set an
inline errors.notes message when it exceeds the limit, and ensure the notes
textarea in the dialog reflects that constraint so users get immediate feedback
instead of a generic save failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c09bc54-4127-4881-974e-0c3fee283398

📥 Commits

Reviewing files that changed from the base of the PR and between 0462f1f and 83b5729.

📒 Files selected for processing (23)
  • apps/backend/src/db/migrations/0051_same_blur.sql
  • apps/backend/src/db/migrations/meta/0051_snapshot.json
  • apps/backend/src/db/migrations/meta/_journal.json
  • apps/backend/src/db/schema/tables/characters.ts
  • apps/backend/src/lib/__tests__/validation.unit.test.ts
  • apps/backend/src/lib/validation.ts
  • apps/backend/src/routes/__tests__/characters.avatar.integration.test.ts
  • apps/backend/src/routes/__tests__/characters.routes.integration.test.ts
  • apps/backend/src/services/__tests__/characters.service.unit.test.ts
  • apps/backend/src/services/characters.service.ts
  • apps/frontend/src/components/CharacterEditDialog.tsx
  • apps/frontend/src/components/CharacterList.tsx
  • apps/frontend/src/components/__tests__/CharacterDialog.test.tsx
  • apps/frontend/src/components/__tests__/CharacterImportWizard.test.tsx
  • apps/frontend/src/components/__tests__/CharacterList.test.tsx
  • apps/frontend/src/components/script-mode/__tests__/ScriptReferencePanel.test.tsx
  • apps/frontend/src/components/write-mode/LabelPropertiesPanel.tsx
  • apps/frontend/src/components/write-mode/__tests__/DialogueLine.test.tsx
  • apps/frontend/src/hooks/__tests__/useCharacters.test.tsx
  • apps/frontend/src/hooks/useCharacters.ts
  • apps/frontend/src/lib/api/characters.ts
  • docs/DATABASE_SCHEMAS.md
  • packages/shared/src/index.ts
💤 Files with no reviewable changes (1)
  • apps/frontend/src/components/write-mode/LabelPropertiesPanel.tsx

@mikkisguy mikkisguy merged commit 6bdb6e1 into main Jul 6, 2026
3 checks passed
@mikkisguy mikkisguy deleted the 257-replace-dialoguestyle-with-notes branch July 6, 2026 19:38
<Label htmlFor="edit-char-notes" className="text-xs">
Notes
</Label>
<textarea

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

React Doctor · react-doctor/control-has-associated-label (warning)

Blind users can't tell what this control does because screen readers find no label, so add visible text, aria-label, or aria-labelledby.

Fix → Give every interactive control a label screen readers can read.

Docs

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.

feat: Replace dialogueStyle with notes textarea on characters

1 participant