A dependency's marker never reaches run time, but your run-time consumer needs it — what are your real options?
answer
- the level is upstream of you
- meet the metadata where it still lives
- your own code, your own level
- raising is additive, lowering is silent
- a side mapping needs a guard test
basics
~20 sYou cannot raise another artifact's survival level from outside. The workable moves: read the metadata where it still exists and carry it forward, mark the code you own with your own marker, keep a guarded side mapping, or ask for a rebuild.
solid answer
~50 sStart from the constraint: the level is fixed when the dependency was compiled, so nothing on your side raises it. That leaves four honest moves. **Move your consumer to the phase where the metadata still exists** — if it reaches the artifact, read it while you build and carry forward whatever the run-time path needs in a form the run time can read. **Attach your own marker, at a level you choose, to the declarations you own** — which covers your code but not the dependency's. **Keep a side mapping** from declaration to the information the marker carried, accepting that it now drifts by hand. Or **ask the library to raise the level**, which is a safe request: raising takes visibility away from no existing reader. Pick by whether the declarations that need marking are yours.
go deeper
The takeaway is that you cannot turn on metadata a dependency did not ship. If your code needs a marker at run time, it has to be a marker your own code declares and carries.
Explain why the level is fixed upstream, and name at least two moves that work without changing the dependency — consuming at the phase where the metadata still exists, and marking your own declarations.
Demonstrate the asymmetry: raising takes nothing from existing readers, lowering silently removes work nobody is told about. Pick a move based on whose declarations need marking, and put a guard on any hand-kept bridge.
Decide whether the bridge is temporary or permanent, and say so in writing. A side mapping with no owner and no expiry becomes a second undocumented contract with a dependency you do not control.
## The constraint that decides everything A survival level is a property of the metadata type, applied when the code carrying the marker is compiled. That is upstream of you. No consumer-side configuration, no run-time flag and no repackaging step can conjure metadata that the dependency's artifact does not carry, and nothing you write can promote metadata the runtime was never asked to expose. Accepting that early is what separates a fifteen-minute decision from a day of trying settings. So the question is not "how do I raise it" but **"where can I still reach this information, and what do I do with it there?"** ## The four moves 1. **Consume at the surviving phase.** If the metadata reaches the dependency's artifact, then the artifact is readable at *your* build time. Read it there and carry forward what your run-time path actually needs — a generated lookup, a table, whatever shape your runtime can consume without a metadata query. This is the strongest option when it applies, because it uses the real metadata rather than a hand-kept copy of it. 2. **Declare and attach your own marker.** You control your own metadata type, so you control its level. This works cleanly for declarations you own, and not at all for the dependency's own declarations — you cannot attach metadata to somebody else's compiled code from outside. 3. **Keep a side mapping.** An explicit table from declaration to the information the marker conveyed, maintained in your code. It always works and it always drifts: the dependency adds or moves a marked declaration and your table silently no longer matches. Treat it as a bridge with an expiry date, and give it a test that fails when the two disagree. 4. **Ask for the level to be raised.** Cheap to request and safe to grant, for a reason worth stating precisely: **raising a level removes visibility from no existing reader.** Everyone who could read the marker before still can. It costs artifact metadata, it requires the marker's type to be resolvable at run time, and it converts the marker into a run-time contract the author cannot later lower without silently disabling consumers. | Move | Works for the dependency's declarations | Main cost | |---|---|---| | Consume at the surviving phase | Yes, if the metadata reaches the artifact | A build step of your own | | Your own marker | No — only declarations you own | Covers half the surface | | Side mapping | Yes | Drifts by hand; needs a guard test | | Ask for a rebuild at a higher level | Yes | Not your schedule | ## The direction that matters The two directions of a level change are not symmetric, and candidates state this backwards more often than any other claim in this material: - **Raising** (parse-only → artifact → run-time-readable) is additive. The set of readers grows. Nothing that worked stops working. The honest caveat is behavioural rather than about access: a run-time consumer that was matching nothing may now start matching, so a change nobody thought was observable can switch on work. - **Lowering** is subtractive and silent. The marker disappears from a phase where somebody was already reading it, and because consumers act *where the marker is present*, they simply stop acting. No error, no log, no failed build. That asymmetry is why the level belongs in the marker's published documentation and why lowering one deserves the review a breaking API change gets. ## Picking between the moves Ask, in order: - **Are the declarations that need marking mine?** If yes, your own marker at a level you choose is the simplest correct answer and you are done. - **Does the dependency's metadata reach its artifact?** If yes, read it at build time and carry it forward. If it was discarded after parsing, no tool can recover it from the shipped artifact and this option is gone. - **Is the dependency's author reachable on your timeline?** If yes, the request is worth making even while you build a bridge, because the bridge is the thing you will otherwise maintain forever. - **Is a hand-kept mapping acceptable for now?** Only with a guard that fails loudly when the dependency changes what it marks. One temptation to name and reject: re-deriving the information from names, packages or signatures instead of the metadata. It works on the day you write it and it is a second, undocumented contract with the dependency's naming conventions — harder to diagnose than the retention problem you started with.
- The dependency's marker is discarded after parsing. Which option disappears?Reading it at your build time. Metadata that never entered the artifact cannot be recovered from the shipped file by any tool, so the only routes left are your own marker on your own declarations, a hand-kept mapping, or a rebuild of the dependency at a surviving level.
- Is asking the author to raise the level a breaking change for their other consumers?Not for access: every reader that could see the marker keeps seeing it. The real caveats are that the artifact grows, the marker's type must resolve at run time, and a run-time consumer that previously matched nothing may now start acting on those declarations.
- Why is inferring the same information from naming conventions a poor substitute?It replaces an explicit contract with an implicit one. The metadata was a declaration the author chose to publish; a naming rule is a pattern they never promised to keep. It breaks on the first rename, and it breaks silently, in the same shape as the problem you were solving.
saying these in an interview costs you the question
- Thinks a consumer can raise a dependency's survival level in its own build.
- Believes you can attach metadata to another artifact's compiled declarations.
- Says lowering a level is safe because nothing errors.
- Claims metadata discarded after parsing can be recovered from the artifact.
- Treats a hand-kept side mapping as a permanent solution with no guard.