Maintainer Load and Port Lifecycle Policy

1. Why this exists

Nothing in the handbook currently stops a committer from taking on more ports than they can realistically maintain, and nothing forces a stale, unmaintained port to actually get dealt with instead of sitting in the tree indefinitely. Being listed as a port's maintainer is supposed to mean that bug reports get triaged, that security issues get addressed, that the port gets bumped when upstream moves. When that stops being true for a large share of someone's ports, the cost doesn't stay with that maintainer only. It lands on whoever else has to touch the tree. Committers running exp-runs for a compiler or crypto library transition, or doing multi-architecture QA, end up doing de facto maintenance on ports someone else's name is attached to, for free, on top of their own work. A maintainer list that doesn't reflect who's actually maintaining anything is worse than an honest "unmaintained" flag, because it hides the real state of the tree from everyone who has to plan around it.

2. Maintainer load threshold

A committer or maintainer becomes overloaded, and ineligible to add new ports or adopt orphaned ones, once all of the following are true:

Overloaded is a status, not a moment-to-moment calculation. Once the conditions above are met the maintainer remains overloaded until the status is cleared, whether or not each individual condition still holds.

Clearing overloaded status. The status is cleared once the maintainer's outdated ratio falls below 8% and remains below 8% for 30 continuous days. Entry and exit are deliberately not symmetric. Entry requires all three conditions; exit depends on the ratio alone. Two consequences follow, and both are intended:

The 30-day sustained window exists because a snapshot percentage is a bad trigger on its own. A batch of unrelated upstream releases landing the same week, or a short detection lag, can spike a ratio briefly with no real maintainer neglect behind it. What indicates an actual problem is a ratio that doesn't come back down i.e. when backlog accumulating rather than clearing. A maintainer who spikes and clears within a couple of weeks never trips this but one who sits above threshold for a month or more does.

Anti-gaming clause: The thresholds are meant to filter noise, not to provide a renewable reset. If a maintainer's ratio shows a repeating pattern of dropping below 8% just long enough to clear the status, followed by new port additions, followed by drift back toward or above 10%, that pattern is itself grounds for portmgr to decline to clear the status, or to reinstate it, regardless of the instantaneous number at any given check. A maintainer who actually caught up stays caught up.

Likewise, maintainers should not try to game these rules by obscuring maintainership, in particular by moving ports to a third party (“sock puppet”) that serves little purpose but to be a vehicle through which the overloaded maintainer can exert maintainership over ports without being the registered maintainer, or through the use of multiple e-mail addresses.

Overloaded maintainers are however encouraged to drop ports they feel unable to maintain further, including by reverting their maintainership to ports@FreeBSD.org.

2a. Taking on additional ports as an overloaded maintainer

While a maintainer is overloaded, taking on additional ports (new or adopted) requires explicit approval from portmgr to avoid further overload.  In the following cases, overloaded maintainers may do so with portmgr's approval:

Portmgr may approve or deny maintainership at the team’s own discretion for any reason.

The overloaded maintainer should strongly consider finding a volunteer to take over ports instead of requesting approval for maintainership.

2b. Pinned versions for dependency-locked ports

Some ports are outdated not from neglect but because a newer upstream version would break a dependency chain the maintainer doesn't control alone (e.g., a library bump that several downstream ports haven't caught up to yet). Where this applies, the maintainer should explicitly pin the version and document the reason in the port's Makefile or in an accompanying note or comment, rather than silently sitting outdated. A documented, justified pin does not count against the ratio in section 2 but an undocumented one does, since the whole point is distinguishing "waiting on a real constraint" from "hasn't been touched."

Setting PORTSCOUT=ignore does not, by itself, remove a port from consideration under section 2. It only suppresses portscout's own out-of-date flag for that port. It is not equivalent to a documented pin under this section and must not be used as a substitute for one. A maintainer cannot make a port disappear from the ratio calculation simply by silencing the tool that measures it. The port still needs an actual documented justification to be excluded, and portmgr may audit PORTSCOUT=ignore usage across a maintainer's ports for exactly this reason.

Separately, when calculating a maintainer's outdated ratio for section 2, portmgr should use the higher of the portscout and repology figures for a given port, not whichever number is more favorable to the maintainer. The two tools use different detection heuristics and don't always agree. Taking the higher figure avoids a maintainer's compliance status depending on which single tool happens to have missed something the other one caught.

2c. portmgr intervention once a maintainer is over threshold

Section 2 stops a maintainer from adding to their own pile once they're over threshold, but it doesn't by itself shrink the pile that's already there. Without a bridge to actual remediation, being "over threshold" just means the backlog sits frozen in place rather than getting worked down, which doesn't solve the underlying problem.

Once a maintainer is overloaded, portmgr may:

This is the mechanism that makes the rest of this policy actually operational. A threshold with no assigned path to remediation just produces a frozen backlog and a maintainer who's stuck but not helped, which isn't the goal.

3. Bug and PR handling expectations

4. New port acceptance

Before a new port is accepted, the submitter/maintainer should be able to answer:

Enforcement note: There is no dedicated reviewer checking every new port commit against these criteria before it lands; in practice, whether a commit was appropriate under this section is often only noticed after the fact, if at all. Given that, any committer who identifies a new port that was added in violation of this section i.e. over-threshold maintainer, no real use case, unmaintained upstream, unworkable on FreeBSD, or an unaddressed duplicate; has the standing right to revert that addition under blanket approval, without needing to first secure individual sign-off from portmgr. This mirrors the blanket approval in section 2c: since no one is positioned to catch every violation as it happens, the committer who does catch one should be able to act on it directly rather than the violation standing simply because no formal reviewer flagged it in time.

5. Deprecation and removal criteria

A port should be considered for deprecation followed by removal after the standard deprecation window under the following conditions, unless someone steps up to fix the underlying issue:

  1. Upstream is gone entirely: Site down, repo deleted or archived, no actively maintained fork.

  2. Upstream is dead (code/site still exists, no activity). Before dropping, check:

    • Is this a service port? Something that opens a listening socket, accepts remote connections, or otherwise has a network-facing attack surface? Dead upstream plus network exposure should be treated as a live CVE risk, not just staleness, and escalated accordingly.
    • Are there multiple versions of this port in the tree where a specific version is EOL upstream even though a newer sibling is still alive? EOL'd versions get deprecated and removed on their own timeline, independent of the newer version's status.
  3. Upstream is a rebrand/fork of a commercial product where the license requires it (e.g. an AGPL fork of a project whose license or trademark terms forbid reuse of the original name). These get renamed or removed, not left under the original name. This is a legal exposure issue as much as a maintenance one.

  4. Additional criteria:

    • Known unpatched severe vulnerabilities with no maintainer response within 30 days: Deprecate regardless of upstream's general activity level.

    • Blocks a tree-wide transition (toolchain, crypto library, etc.) and the maintainer is unresponsive or refuses the required refactor after direct contact: becomes a portmgr-level override rather than something the transition owner has to personally absorb. If possible consider transitioning the port under infrastructure blanket approval instead.

    • License is incompatible or changed to something incompatible with what we can ship. Same urgency tier as the rebrand/license case above.

    • Superseded by a duplicate: Where two ports serve the same purpose and one is actively maintained while the other isn't, the unmaintained one is a deprecation candidate in favor of consolidating on the maintained one.

    • Depends on a deprecated or end-of-life library or language runtime: a port can build cleanly and still be a supply-chain risk if its dependency chain sits on something the ecosystem has moved past: Python 2 (and Python-2-only compatibility shims like py-future), GTK2, PCRE1, and similar cases are the common examples here. These don't stop working overnight, but they accumulate runtime failures, don't receive security fixes upstream, and increasingly can't be built against current toolchains at all. If a port hasn't moved to the current supported dependency (e.g. GTK3/GTK4, PCRE2, Python 3) after a defined grace period once the underlying dependency itself is deprecated in the tree, it becomes a removal candidate on that basis alone, independent of whether the port's own upstream is otherwise active. This treats "runs on a dead foundation" as its own category, separate from "upstream is dead". A port can have a perfectly alive upstream and still be a problem if it never migrates off something we're trying to get out of the tree.

A note on low-risk, low-activity ports: Absence of activity or reverse dependencies is not, by itself, sufficient grounds for removal. A single-purpose game, a desktop utility, or similar software with no network-facing surface and no dependency on anything being phased out isn't causing anyone harm by sitting quietly unchanged; "nobody's filed a bug in two years" is not the same signal as "this is a security or supply-chain risk." The criteria above are about risk and cost (network exposure, CVEs, license conflicts, blocking tree-wide work, dependence on dying infrastructure) not about popularity.

Low-activity ports that don't meet any of the risk-based criteria in this section should be left alone even if their maintainer is otherwise over threshold; the point of sections 2c and 6 is to clear real risk and real backlog and not to prune harmless software for being quiet.

6. Deprecation mechanics and best practice

7. Closing note

We can't write a rule for every workaround someone might try. Somebody will eventually find an angle none of the sections above named specifically. Structuring a port so the version-tracking tools can't see it's actually stale, adding a batch of new ports fast before the backlog has had time to show up in the numbers, or something nobody in this discussion thought of. Trying to patch the document every time someone finds a new gap isn't a real strategy.

So, portmgr isn't limited to only the mechanisms spelled out above. If someone's clearly working against the point of this policy (i.e. less overload, ports that are actually maintained, not dumping unmaintained software on everyone else) portmgr can act on that even if it's not one of the specific clauses here, and doesn't need to wait for this document to be rewritten first. The numbers and windows above exist so there's something solid to point to in the normal case, not to box portmgr in when something abnormal shows up.

If portmgr comes to a maintainer with help, a plan, or straightforward advice, take it. Don't turn it into a fight. The anti-gaming clauses in this document are aimed at someone gaming the rules while ignoring the point of them; they're not meant to be a rulebook you argue over once portmgr is actually trying to help you. Someone who takes the help, works honestly toward getting caught up, and is straight about what they can and can't manage will be treated that way in return.

That's different from disagreeing. If a maintainer thinks a decision was wrong, thinks a ratio was miscalculated, or wants someone else to look at it; that's a normal thing to do, and it's not resistance. Nobody should be penalized for pushing back in good faith. What this is actually about is the other thing: agreeing to a plan and then not doing it, quietly re-adding a port that was removed for cause, going quiet instead of engaging, or hiding behind procedure instead of actually doing the work. That kind of pattern is its own problem, separate from wherever the outdated ratio happens to sit, and can end with a commit bit being pulled. The line isn't whether you disagree but whether you're still working with the process while you do.


CategoryPorts

Ports/MaintainerLoadAndPortLifecyclePolicy (last edited 2026-08-20T17:16:52+0000 by MuhammadMoinurRahman)