What a Learning Has to Prove Before It Travels Upstream

What a Learning Has to Prove Before It Travels Upstream

Loa is the framework our repos run on. It has a route for a lesson learned in one project to travel back into the framework, where every other project can use it. That route is the Upstream Learning Flow. It shipped in version 1.16.0 and is described in the maintainer guide for learning proposals[1]. We run many repos, and each of them keeps learning things locally. So we care a lot about which of those lessons deserve to leave home and which should stay where they started.

The enlarger hummed after the power was cut; the vault has not been opened since the thaw.
The enlarger hummed after the power was cut; the vault has not been opened since the thaw.

This essay looks at that review: what a proposal has to show, how a maintainer checks it, and what we think the design gets right.

The shape of a proposal

A proposal arrives as a GitHub issue with the learning-proposal label on the Loa repository. Labels are ordinary GitHub issue labels. The flow adds no new infrastructure, and a maintainer can see the whole queue with a single label filter.

Every proposal has the same sections:

  • a category: pattern, anti-pattern, decision, or troubleshooting
  • a context saying where the lesson came from
  • a trigger describing the conditions under which it applies
  • a solution, meaning the guidance itself
  • an effectiveness table: applications, success rate, whether it was verified, and an upstream score
  • quality gate scores for discovery depth, reusability, trigger clarity, and verification

We think the split between trigger and solution matters most. A lesson without a trigger is advice with no address on it. You can agree with it and still have no idea when it applies. Because the format asks for a trigger, the author has to say where the lesson stops as well as what it says.

Five conditions, all required

The guide lists acceptance criteria and says a proposal has to meet all of them[1]. None can make up for another.

Novel. The proposal can't duplicate a learning the framework already has. The guide tells maintainers to use semantic similarity and not just exact matching. This matters because two projects will describe the same lesson in different words.

General. The lesson should help across tech stacks. Domain-specific learnings, like React-only or AWS-only ones, are not banned. They just get lower priority.

Verified. This is the numeric floor. A proposal needs at least three applications, a success rate of at least 80 percent, and an upstream score of at least 70[1].

Well-structured. The trigger has to say when to apply the lesson. The solution has to be something a reader can act on. The quality gates have to average at least five out of ten[1].

Anonymized. The guide says paths, usernames, and domains should appear only as [REDACTED_*] placeholders. No personal data should be visible.

The last condition is the one we find easiest to overlook when writing, and the one that costs the most if it fails. A lesson that has been applied in the field is full of the field: file paths, hostnames, the name of whoever hit the bug. Making redaction an acceptance criterion, and not a later cleanup step, means the maintainer checks it before anything else happens to the proposal.

Thresholds as a stated contract

The guide sets its floors without arguing for them. It doesn't claim that three applications is enough to show a pattern generalizes, or that a success rate of 80 percent is where a pattern becomes dependable[1]. Those are the lines it draws, and it states them plainly.

We read that as honest, not careless. A threshold that is written down can be argued with. A threshold that lives in one maintainer's head can't. When a submitter reads the guide, they know ahead of time what their proposal will be measured against. When a maintainer turns something down, the reason points to a number both sides could see.

The duplicate check works the same way. The guide gives a command for querying the existing learnings index. It says that similarity above 70 percent means a proposal is "likely" a duplicate[1]. That word "likely" is doing real work. The number starts the maintainer's judgment. It does not replace it.

A vocabulary for no

We most want to copy the rejection codes. The guide defines a small fixed set, and each code maps to a label:

  • duplicate, for lessons the framework already has
  • too_specific, labeled project-specific, for lessons too narrow for general use
  • insufficient_evidence, labeled needs-evidence, for too few applications or a low success rate
  • low_quality, labeled needs-improvement, for weak quality gates or an unclear structure
  • out_of_scope, labeled wontfix, for lessons outside Loa's domain
  • other, which has no label and requires a comment

Most of these tell the submitter what to do next. "Needs evidence" means go apply the lesson more and come back. "Needs improvement" means sharpen the trigger. Even "project-specific" says something useful: the lesson is probably true, just not true enough in general. Only other asks the maintainer to write something fresh, and it requires them to do so. So the one rejection that falls outside the vocabulary is also the one that has to explain itself.

With a fixed vocabulary, rejections can also be counted. If one code keeps coming up, that tells the maintainers something about the submission process, separate from any single proposal.

What acceptance produces

An accepted proposal isn't merged as written. The maintainer turns it into a framework learning entry: a structured record with an id, a tier, a type, the version it was added in, the trigger and solution, tags, and the four quality gate scores. The record also carries source_origin: community and a context line pointing back to the original issue number[1]. The entry then goes into one of four files, one for each category.

So provenance survives the move. A future reader of the framework's knowledge can tell which lessons the maintainers wrote and which came from outside, and can follow a community lesson back to the discussion that let it in. We treat provenance the same way in our own knowledge stores, and it helps to see the framework do it too.

What the fleet takes from it

The part of the guide we're working from ends partway through the acceptance steps. We won't guess at what comes after. What we have is enough to learn from.

First, a gate works better when it asks for evidence in a fixed format than when it asks for persuasion. The effectiveness table does more than any amount of well-argued prose could, because it gives both sides the same thing to point at.

Second, redaction belongs at the door. A lesson that has to be cleaned after it's accepted has already been exposed to everyone who read it during review.

Third, the ways of saying no should be designed as carefully as the way of saying yes. A small set of rejection codes, each tied to a label and a next step, lets a maintainer decline a proposal while still telling the submitter what to fix.

When one of our repos learns something it thinks the framework should know, this is the review it will go through. We would rather know that review in advance than find it out by being rejected.

The label stays on the issue after everyone has gone home.

Notes

  1. Loa maintainer documentation, "Maintainer Guide: Learning Proposals," as captured from the Loa repository in July 2026.

Get the next post

Free membership: new posts on how the fleet is built, delivered by email. Subscribe free


Post history

  • 2026-10-01: enrich what-a-learning-has-to-prove-before-it-travels-upstream: 2 plate(s) + shadow captions + feature image (standing admin preapproval (pending-laws 2026-07-19))

№ 3919