Skip to content

Add case-insensitive label name resolution for jump targets#183

Merged
mikkisguy merged 2 commits into
mainfrom
173-parser-resolve-jump-targets-to-label-ids
Jun 1, 2026
Merged

Add case-insensitive label name resolution for jump targets#183
mikkisguy merged 2 commits into
mainfrom
173-parser-resolve-jump-targets-to-label-ids

Conversation

@mikkisguy

@mikkisguy mikkisguy commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Menu/choice options now include and display target label names alongside IDs for clearer navigation.
    • Menu choices support condition flags and optional effects for richer branching.
  • Tests

    • Added tests for label-name-to-ID resolution and jump-target resolution.
    • Login test expanded to verify disabled inputs and loading state during submission.
  • Data / Seed

    • Test seed data now includes created target labels referenced by name.

@mikkisguy mikkisguy self-assigned this Jun 1, 2026
@mikkisguy mikkisguy linked an issue Jun 1, 2026 that may be closed by this pull request
4 tasks
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3a6faaf0-24a3-4a3b-860c-244a0593588f

📥 Commits

Reviewing files that changed from the base of the PR and between 6aa6d77 and a174a6d.

📒 Files selected for processing (4)
  • apps/backend/src/services/labels.service.ts
  • apps/frontend/src/hooks/useTechnicalInfo.ts
  • apps/frontend/src/lib/prose-types.ts
  • packages/shared/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/shared/src/index.ts
  • apps/frontend/src/hooks/useTechnicalInfo.ts
  • apps/backend/src/services/labels.service.ts

📝 Walkthrough

Walkthrough

Adds a new targetLabelName field for menu choices, emits it from the parser, extends shared types and DB schema, adds server-side name→ID resolution (wired into getLabel), updates seed data, adjusts frontend consumption, and adds unit tests for resolution behavior.

Changes

Menu Choice Jump-Target Label Resolution

Layer / File(s) Summary
Shared type contract for menu options
packages/shared/src/index.ts
LabelLine interface adds optional menuOptions array with label, targetLabelId, targetLabelName, optional conditionFlags, and optional effects.
Database schema for menu options
apps/backend/src/db/schema/tables/label-lines.ts
labelLines table schema extends menuOptions JSONB column to include targetLabelName: string per option.
Label name resolution service
apps/backend/src/services/label-name-resolver.service.ts, apps/backend/src/services/__tests__/label-name-resolver.service.unit.test.ts
Adds resolveLabelNames performing case-insensitive labelName→id mapping with tests for matching, missing names, empty inputs, and case-insensitivity.
Jump target resolution in labels service
apps/backend/src/services/labels.service.ts, apps/backend/src/services/__tests__/resolve-jump-targets.service.unit.test.ts
Adds and exports resolveJumpTargets to rewrite menuOptions[].targetLabelId using resolveLabelNames; wired into getLabel so returned lines contain resolved IDs; unit tests cover resolved, undefined/empty, and case-insensitive cases.
Parser extraction of target label names
apps/backend/src/services/rpy-parser.service.ts
extractTechnicalConstructs now initializes and assigns choice.targetLabelName when parsing jump destinations in choice blocks.
Test data seeding and verification
apps/backend/scripts/seed-technical-badges.ts
Seed script inserts a fixed set of target labels, updates seeded lines (Line 2, 6, 9) to include targetLabelName in menu options, and extends post-seed verification instructions.
Frontend menu option rendering and types
apps/frontend/src/hooks/useTechnicalInfo.ts, apps/frontend/src/lib/prose-types.ts, apps/frontend/src/pages/auth/__tests__/login.test.tsx
useTechnicalInfo uses choice.targetLabelName and typed effects; DialogueEntry.technicalInfo adds conditionFlags?; login test now asserts inputs disabled while submitting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mikkisguy/branchforge#169: Both PRs modify parser extraction and frontend handling for menu/technical constructs; this PR extends menu option shapes with targetLabelName and adds server-side name resolution.

Poem

🐰 I hopped through code to make menus kind,
Names find their IDs, no case left behind,
Parser peeks, backend maps with care,
Frontend reads targets now aware,
Seeded fields planted — hooray, prepare!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title Check ✅ Passed Title check skipped as CodeRabbit has written the PR title.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 173-parser-resolve-jump-targets-to-label-ids

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.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Add case-insensitive label name resolution for jump targets Jun 1, 2026

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
apps/backend/src/services/labels.service.ts (3)

2515-2515: 💤 Low value

Simplify condition: redundant truthiness check.

Since choice.targetLabelId is typed as string (non-nullable), checking choice.targetLabelId && is redundant. The condition can be simplified to just check for empty string:

-        if (choice.targetLabelId && choice.targetLabelId !== "") {
+        if (choice.targetLabelId !== "") {
🤖 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/labels.service.ts` at line 2515, The condition
using `choice.targetLabelId && choice.targetLabelId !== ""` is redundant because
`choice.targetLabelId` is a non-nullable string; update the conditional (e.g.,
inside the function handling choices where `choice.targetLabelId` is checked) to
a single check like `if (choice.targetLabelId !== "")` (or `if
(choice.targetLabelId.length > 0)`) referencing `choice.targetLabelId` to
simplify the logic.

1670-1679: ⚖️ Poor tradeoff

Performance: Fetching all project labels may be inefficient for large projects.

The query fetches all non-deleted labels in the project to resolve jump targets. For projects with thousands of labels, this could impact response time in getLabel. Consider whether resolution could be optimized by:

  • Only fetching labels that match the target names found in menuOptions
  • Caching the label name→ID mapping at the project level

However, if typical projects have a reasonable number of labels and this read-time resolution is intentional per the PR design, this may be acceptable.

🤖 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/labels.service.ts` around lines 1670 - 1679, The
current implementation loads all non-deleted labels for a project into allLabels
and calls resolveJumpTargets(lines, allLabels), which is inefficient for large
projects; change it to first extract the set of jump target names from
lines/menuOptions (the parsed targets used by resolveJumpTargets) and then query
only matching labelName values (and projectId/isNull(deletedAt)) instead of
selecting every label, or alternatively wire in a project-level label name→ID
cache used by getLabel and resolveJumpTargets to avoid full scans; update the
code paths that build allLabels and the callsite of resolveJumpTargets
accordingly so they use the filtered query result or cached mapping.

2504-2504: Fix concern: resolveLabelNames safely handles labelName: null

  • In apps/backend/src/services/label-name-resolver.service.ts, resolveLabelNames guards with if (label.labelName) before calling toLowerCase(), so null label names are skipped without throwing.
  • Existing unit tests (apps/backend/src/services/__tests__/label-name-resolver.service.unit.test.ts) cover nonexistent labels and empty lists, but don’t include a case where an input label has labelName: null; adding that test would prevent regressions.
🤖 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/labels.service.ts` at line 2504, The resolver must
safely handle labels with labelName: null and we need a unit test to prevent
regressions: ensure resolveLabelNames (in label-name-resolver.service.ts) checks
label.labelName truthiness before calling toLowerCase() (preserve or add the if
(label.labelName) guard) and skip/null-map those entries, and add a new test
case in label-name-resolver.service.unit.test.ts that passes an input label with
labelName: null (and asserts the function returns without throwing and treats
that entry as unresolved/unchanged per existing behavior); reference the
resolveLabelNames function when making the check and the unit test file when
adding the new case.
🤖 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.

Inline comments:
In `@apps/frontend/src/hooks/useTechnicalInfo.ts`:
- Around line 105-117: The inline choice typing in useTechnicalInfo.ts (the
info.choices = line.menuOptions.map(...) block) diverges from the shared
LabelLine["menuOptions"] contract by introducing effects; either add effects
(and nested stats) to the shared type in packages/shared/src/index.ts so the
component can safely reference choice.effects, or remove/stop using effects here
and derive the choice type from LabelLine["menuOptions"][number] (instead of an
inline type) so the mapping aligns with the shared contract; update the
info.choices mapping and any callers to use the unified shared type (referencing
LabelLine and the info.choices assignment) accordingly.

---

Nitpick comments:
In `@apps/backend/src/services/labels.service.ts`:
- Line 2515: The condition using `choice.targetLabelId && choice.targetLabelId
!== ""` is redundant because `choice.targetLabelId` is a non-nullable string;
update the conditional (e.g., inside the function handling choices where
`choice.targetLabelId` is checked) to a single check like `if
(choice.targetLabelId !== "")` (or `if (choice.targetLabelId.length > 0)`)
referencing `choice.targetLabelId` to simplify the logic.
- Around line 1670-1679: The current implementation loads all non-deleted labels
for a project into allLabels and calls resolveJumpTargets(lines, allLabels),
which is inefficient for large projects; change it to first extract the set of
jump target names from lines/menuOptions (the parsed targets used by
resolveJumpTargets) and then query only matching labelName values (and
projectId/isNull(deletedAt)) instead of selecting every label, or alternatively
wire in a project-level label name→ID cache used by getLabel and
resolveJumpTargets to avoid full scans; update the code paths that build
allLabels and the callsite of resolveJumpTargets accordingly so they use the
filtered query result or cached mapping.
- Line 2504: The resolver must safely handle labels with labelName: null and we
need a unit test to prevent regressions: ensure resolveLabelNames (in
label-name-resolver.service.ts) checks label.labelName truthiness before calling
toLowerCase() (preserve or add the if (label.labelName) guard) and skip/null-map
those entries, and add a new test case in
label-name-resolver.service.unit.test.ts that passes an input label with
labelName: null (and asserts the function returns without throwing and treats
that entry as unresolved/unchanged per existing behavior); reference the
resolveLabelNames function when making the check and the unit test file when
adding the new case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 85a980e6-b878-4d91-b1f2-d333129fe142

📥 Commits

Reviewing files that changed from the base of the PR and between 2972c11 and 6aa6d77.

📒 Files selected for processing (10)
  • apps/backend/scripts/seed-technical-badges.ts
  • apps/backend/src/db/schema/tables/label-lines.ts
  • apps/backend/src/services/__tests__/label-name-resolver.service.unit.test.ts
  • apps/backend/src/services/__tests__/resolve-jump-targets.service.unit.test.ts
  • apps/backend/src/services/label-name-resolver.service.ts
  • apps/backend/src/services/labels.service.ts
  • apps/backend/src/services/rpy-parser.service.ts
  • apps/frontend/src/hooks/useTechnicalInfo.ts
  • apps/frontend/src/pages/auth/__tests__/login.test.tsx
  • packages/shared/src/index.ts

Comment thread apps/frontend/src/hooks/useTechnicalInfo.ts Outdated
…ptions and label lines; resolve jump targets to label IDs
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.

Parser: resolve jump targets to label IDs

1 participant