fix(display-board): stop the organigram naming a nested post as a team - #382
Merged
Conversation
A personal role sitting under another personal role was printed on the band's « ÉQUIPES » line, so the sheet announced a post as if it were a team: « ÉQUIPE Responsable du programme des services ». A band's rows are not all teams. The settled model treats a child personal role as an adjoint arrangement, and the band already folds that child's titulaire into its ADJOINTS — so the person was on the sheet twice, once correctly as an adjoint and once as the name of a team that does not exist. Filtering the ÉQUIPES line to group roles loses nobody. Both halves of the rule move into organigram-layout as `teamRows` and `bandAdjoints`. The screen view and the PDF carried identical private copies of the adjoint fold, which is how a fix lands in one renderer and not the other; now neither can drift. Filtered at render time rather than in `toLayout`, because a collector band (`node: null`) prints the same rows as full lines, people and all — there a personal role belongs. Verified on the board viewer by nesting a personal role under Audio/Video: its name no longer appears among « Perches, Estrade, Sono » and its titulaire shows up in ADJOINTS instead.
From the review of #382. `BandBlock.rows` documented itself as "Rendered beneath, in order", which is true and says nothing about the one property a caller has to know: the list mixes group roles with personal roles, and treating them alike is exactly the bug this branch fixes. Documented rather than encoded in the type. Splitting the field would express the invariant properly, but a collector band prints the same list unfiltered as full lines, so the split would have to be undone at that call site — a worse trade for a two-caller helper. Left as a note here and a backlog item.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On the organigram board document, a personal role nested under another personal role was printed on the band's « ÉQUIPES » line, so the sheet announced a post as if it were a team:
Why it happened
A band's rows are not all teams, but
ServiceWithTeamsreceivedband.rowswholesale and named every one of them.The settled model treats a child personal role as an adjoint arrangement, and the band was already folding that child's titulaire into its
ADJOINTS. So the same person appeared twice on the row: once correctly as an adjoint, and once as the name of a team that does not exist. In the example above,ADJOINT Christian VARDONandÉQUIPE Responsable du programmes des servicesare the same post printed two ways.Filtering the ÉQUIPES line down to group roles therefore loses nobody.
The fix
Both halves of the rule move into
organigram-layout.ts:teamRows(rows)— the rows a band names as teams. Group roles only.bandAdjoints(node, rows)— its own deputies, then the leaders of everything beneath it: a team's préposé and a nested post's titulaire alike. This is the fold that makes the filter safe.The PDF had the identical bug.
OrganigramView.tsxandOrganigramDocument.tsxcarried separate private copies of the adjoint fold, so fixing only the screen would have left the printed sheet wrong. Both now call the shared helpers, and neither can drift from the other again.Filtered at render time rather than in
toLayout, because a collector band (node: null) prints the same rows as full lines, people and all — there a personal role does belong, and filtering upstream would have made posts vanish from those sections.Verification
TDD as the regression rule requires: 5 failing
teamRowstests, then 6 failingbandAdjointstests, each watched red before implementing. ThebandAdjointsset pins the invariant that makes the filter safe — a nested post's titulaire still reaches ADJOINTS — so nobody drops off the sheet. It also covers the fold's existing edges: the band's own deputies come first, someone already leading the band is not repeated, someone leading two teams is listed once, and plain members are ignored.End to end on the board viewer, by temporarily nesting a personal role under Audio/Video in a development database:
Full gate green: typecheck, lint, boundaries, aggregate-boundaries, tenant-scoping, server-barrel-exports, service-test-coverage, file-sizes, permission-coverage, unit, integration — plus
biome check, which the pre-commit hook enforces and CI does not run.One judgement call worth a second opinion
A nested post with nobody seated now prints nowhere: there is no adjoint to fold, and it is no longer named as a team. That follows the sheet's stated philosophy of naming who to ask for, and a wrongly-labelled name was arguably worse than none. If an unseated post should still print its name somewhere, that is a different change and a deliberate decision rather than a bug fix.