46c8a2513939ee38fbf6318d51efe5c0fe96ca67
A bridge is a contiguous span, but every operation that filtered teeth out of a group kept the `connected` kind as long as two teeth remained. Reduce a 12-13-14 span to 12 and 14 and you get a "bridge" with no pontic — and worse, both teeth keep one selectionGroupId, so the lab receives them as a single unit and task generation builds work that cannot be made. linkedEdgesFromGroups already guarded the drawn marks with areArchNeighbors, so the chart looked right while the data was wrong. Adds splitDisconnectedRuns, which breaks what remains into contiguous runs: a run of two or more stays connected, a run of one becomes a single. The first run keeps the original groupId so lab rows pointing at it stay valid, and pruneToothProsthesisForGroups re-maps the rest. Applied at all three sites that filter a group's teeth, which each carried their own copy of the length check: - groupsFromFlatTeeth, when teeth are no longer selected - applyShiftRange, when a shift-range takes teeth from an existing group - removeTeethFromGroups, the path pruneDetailTeethToJobs uses toggleToothInGroups already split into runs by hand for the single-removal case; this is the same rule, shared. Tests: a new toothSelectionGroups.spec.ts (13) plus two for removeTeethFromGroups. The middle-tooth cases fail without the fix; the end-tooth and contiguous cases pass either way and exist to prove it does not over-reach. CLAUDE.md updated for the third Vitest file. Not fixed: a pre-existing unused `leftIdx` warning in unlinkAdjacentTeeth, unrelated to this change. Gates: 52 Vitest tests, tsc --noEmit clean, next build clean, ESLint unchanged at 1 pre-existing warning. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dyolink
Monorepo: NestJS backend (backend/), Next.js frontend (frontend/), Docker stack under infrastructure/..
Local development: see backend/README.md and frontend/README.md.
Cursor AI: project conventions for agents are in AGENTS.md, .cursor/rules/, and .cursor/skills/.
Production deploy (https://nudentic.ir)
Full guide: infrastructure/DEPLOY.md
Git tag v1.0.1 → Gitea workflow .gitea/workflows/prod-tag-deploy.yml builds images (URLs baked for nudentic.ir), pushes to Gitea registry, SSH-deploys the Linux stack.
First-time SSL / Hub fallback: same DEPLOY.md.
Staging deploy (https://wixur.ir)
Full guide: infrastructure/STAGING-DEPLOY.md
Merge or push to master → Gitea Actions builds images → deploys to https://wixur.ir (Gitea: http://wixur.ir:3000).
Workflow: .gitea/workflows/registry-build-deploy.yml
Related paths
| Path | Role |
|---|---|
backend/Dockerfile |
API image |
frontend/Dockerfile |
Web image |
infrastructure/STAGING-DEPLOY.md |
Staging setup, CI variables, testing |
infrastructure/docker-compose.registry.yml |
Pull-only staging stack (registry images + nginx + postgres) |
infrastructure/deploy.registry.env.example |
Template for deploy.registry.env |
Description
Languages
TypeScript
97.4%
Shell
1.1%
CSS
0.8%
JavaScript
0.3%
Dockerfile
0.3%
Other
0.1%