What's missing here is who this breakdown should be shared with. There are three levels of breakdown and the details of lower levels should never be revealed to higher levels:
1. The "business" level. There are no "tasks". There are only needs and desires. Things like "a user can log in and press a button". These should not be broken down further than the smallest unit of deliverable value. In this example, there's no point estimating "user can log in" because it delivers no value on its own. A good rule of thumb is these should be described using descriptive language, not imperative, so not e.g. "implement log in procedure".
2. The "team" level. It's OK here to break down those things into "user can log in" and "logged in user can press button". That's because you know they can be implemented independently. But there's still no point delivering them independently. Don't tell the upper level about this breakdown. They are always really eager to know, but they don't need to know. Use this to calculate your estimate for level 1, but said estimate should be a single aggregate. Implementing these in parallel with multiple devs adds no extra overhead because they are completely independent.
3. The "developer" level. This is where you finally have "tasks" and imperative language. Things like "add button to form", "implement 2FA" etc. These tasks are naturally heavily dependent on each other and it's highly likely they'll be done in a completely different order to whatever you write them down in.
If you decide to distribute these tasks among developers then you increase the coordination overhead between devs. Think of it like a multi-threaded application. It's always more efficient for a single developer to do everything if possible (less overhead), but it might nevertheless be necessary to split it up due to time constraints, differing skillsets etc. It's just like we'd like to have one single 80GHz general purpose CPU, but in reality we have to make do with 16 5GHz cores split between performance and efficiency cores etc.
Given that the tasks are highly likely to change and evolve, there is not much point putting in loads of effort to break things down. Do it only when it's necessary, or when it helps you. It's necessary when you need to split up the work between developers. It's helpful when you think of more tasks during your work and you don't want to break your stack. Every developer should have a way to quickly take notes in a way that doesn't break flow, things like "ensure API accepts float input". This is stuff you'd never think of before you get your teeth into it.
Can you elaborate on why we wouldn't share the carefully estimated project plan breakdown with Level 1? I'm not disagreeing, just curious - one would think that with doing all the work to achieve a solid project plan breakdown and Gantt charts and such, it would behoove you to express this to management who is salivating over tangible examples of progress... I understand we don't want to show technical to non-technical, but part of the good project plan is the fact that we can show a roll-up of the tasks, so the abstraction is visible. It's hierarchical.
Reporting on progress up to level 1 is a waste of everyone's time. It's either done or it's not. It ships when it ships. If the team has committed to delivering by a date then just let them get on with doing that. Blockers and setbacks should be actively communicated up the stack if they will affect the deliverable, but otherwise it should be assumed things are on track.
Management are always salivating for details, but we know what always happens: we drop a technical term one time and management goes around repeating that like they know what they're talking about. They use these like weapons to keep other people off their back: basically say something that nobody understands and they'll leave you to it. Some managers will push for more fodder, but it's not your job to provide this. It's your job to deliver.
1. The "business" level. There are no "tasks". There are only needs and desires. Things like "a user can log in and press a button". These should not be broken down further than the smallest unit of deliverable value. In this example, there's no point estimating "user can log in" because it delivers no value on its own. A good rule of thumb is these should be described using descriptive language, not imperative, so not e.g. "implement log in procedure".
2. The "team" level. It's OK here to break down those things into "user can log in" and "logged in user can press button". That's because you know they can be implemented independently. But there's still no point delivering them independently. Don't tell the upper level about this breakdown. They are always really eager to know, but they don't need to know. Use this to calculate your estimate for level 1, but said estimate should be a single aggregate. Implementing these in parallel with multiple devs adds no extra overhead because they are completely independent.
3. The "developer" level. This is where you finally have "tasks" and imperative language. Things like "add button to form", "implement 2FA" etc. These tasks are naturally heavily dependent on each other and it's highly likely they'll be done in a completely different order to whatever you write them down in.
If you decide to distribute these tasks among developers then you increase the coordination overhead between devs. Think of it like a multi-threaded application. It's always more efficient for a single developer to do everything if possible (less overhead), but it might nevertheless be necessary to split it up due to time constraints, differing skillsets etc. It's just like we'd like to have one single 80GHz general purpose CPU, but in reality we have to make do with 16 5GHz cores split between performance and efficiency cores etc.
Given that the tasks are highly likely to change and evolve, there is not much point putting in loads of effort to break things down. Do it only when it's necessary, or when it helps you. It's necessary when you need to split up the work between developers. It's helpful when you think of more tasks during your work and you don't want to break your stack. Every developer should have a way to quickly take notes in a way that doesn't break flow, things like "ensure API accepts float input". This is stuff you'd never think of before you get your teeth into it.