plugin enable fails on a project holding ONLY files the package claims — the package's own grant is minted while the build runs, so the gate admits nothing #233
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#233
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Measured on the current binary while building the
de.h-dv.timelinerelease asset job, and deliberately not fixed there — it is a product defect, not a workflow one.The symptom
A project containing only files a package claims fails activation:
generation_failuresconfirms the detail. Reproduced on the current binary, not inferred.The cause
A package's own
extraction_componentsrow is minted while the build runs. So:capabilities::project_generation_grants, called frombuild::request, writes no grant for that package — the row it would key on does not exist yet;build::gatethen countsadmittedovertemp.pool_admitand gets 0;The grant lands at promotion. So the condition self-heals after the first successful activation — but the first activation is the one that fails, and on a project of only claimed files there is no first successful activation to heal from.
Why nobody hit it before
The XAML packing job's scratch project happens to contain a
.csfile. That one builtin-claimed file is enough to admit something, so the gate passes and the package's grant lands at promotion as usual. The bug is invisible whenever the project contains at least one file some other extractor claims.That is luck, not design — and it means the failure is worst exactly where a package is most likely to be tried: an operator pointing a new package at a directory of only that package's file type, which is the obvious way to evaluate one.
The TimeLine job carries a two-line
Loader.csfor precisely this reason, with the measurement written into the comment at.forgejo/workflows/release.yml:3300-3318. That workaround should be deleted when this is fixed, and its removal is the regression test.What a fix has to do
Mint the package's grant so it is visible to
build::request, or makebuild::gateadmit on the pending generation's own components rather than only on grants written before the build began. Either way the invariant to restore is: a package that claims a file in the project must be able to admit it on its first activation.What a fix must prove
Loader.csworkaround from the TimeLine packing job leaves that job green.Related
Same family as several findings this week: a state reachable only through an ordering nobody designed against, hidden because every existing exercise of the path happened to contain the one extra input that masks it. See #227 for the inverse (a state believed unreachable that every first-party package traverses).
Fixed in
51d6029, onmaster. And this issue understated it: the "mixed project" case was never safe, only quiet.The escalation, measured
I filed this as an evaluation-time annoyance — loud on a claimed-files-only project, invisible elsewhere because some other extractor claims a file. The second half is wrong.
Reverting the fix and running the mixed-project arm:
It reaches
Readyand is promoted — with the package's own two contributions in no pool at all. Only the carried builtin file was admitted.So on every release that has shipped packages, the first activation of any package produced a generation whose package rows resolved nothing until a later pass rewrote them. Not just the pure-claim case: every case. The pure-claim project fails loudly (
gate_failed); the mixed project fails silently, and the silent one is both worse and far more common.Re-run independently before merge, not taken from the lane's report: same mutation, same numbers, source restored by
cpand verified by md5.Cause — reproduced twice before any code was touched
panicked at generation_build.rs:1399: the activation record named a claim language and no component was minted for it, so \project_generation_grants` had nothing to project onto`tests/packages/timelinepacked, signed, installed, approved and activated over oneSample.dataset→gate_failed: the pending generation's pools admit nothingextraction_componentsis minted bywriter::write_pending_contributionwhile the build runs;project_generation_grantsjoinsgeneration_packagesto it, and so wrote the package no grant atbuild::requesttime.The fix, and why not the other candidate
activation.rs:466-502— inwrite_generation, beside theensure_packageit already performed, mint each claim language's component viacontributions::component_of+ensure_component, carryingpackages::write_grants' reserved-key refusal across.The issue offered two shapes. Candidate 2 — teach
build::gateto admit on pending components — would have been wrong, not merely larger. The pending grant is what the resolver reads during the build, not just whatgatecounts. A gate-only fix would have activated the package and left every row it produced in no pool until the next pass: the silent defect above, preserved, with the loud symptom removed. That is the worst possible outcome and it was the tempting one.Candidate 1 is also the smaller change, because a component's identity derives from the claim languages, which only
ActivationInputscarries —generation_packagesdoes not hold them, so the projection could not mint them.Nothing is fabricated: only the row the grant is projected onto. A package claiming nothing still fails the gate.
Mutations — all RUN, no survivors
ensure_componentloop (revert the fix)Readywithadmitted: 1of 3is_reserved_keyarmbuild::gate'sif admitted == 0("always admit")an ungranted package activated over a project of only its own files: Ready(… admitted: 0 …)The
Loader.csworkaround is goneDeleted from the TimeLine packing job (
release.yml:3264), replaced by a comment recording why. Its local stand-in —the_shipped_timeline_package_activates_over_only_its_own_files— runs on every CI leg and goes RED without the fix, so the removal is graded rather than merely performed.A doc claim this retires
package_baseline.rs's Ruby-leg doc said the XAML package "requestsbridge_sourceonly and no pool capability at all, so a project of nothing but.xamlcould never activate it." That was one cause presented as two:capabilities::admit_selectdoes not filter on pool capabilities andgatecountsCOUNT(DISTINCT contribution_id), so abridge_sourcegrant that reaches the table is counted — it just never reached it. Corrected in place; theinerthalf now graded byan_ungranted_package_still_fails_the_gaterather than argued.Gates, isolated: fmt, clippy (host and windows-gnu),
cargo test --workspace(327 suites, 3524 passed, 0 failed), rustdoc-D warnings, corpus ratchet (6 passed in 22.37s — it really ran;baseline.jsonunmoved), precision gate 7/7 phantoms=0 with POPULATION lines read, andCOSI_E2E_LEG=daemon(746 passed) — all exit 0.