Class: Agentilda::Linear::Attribution
- Inherits:
-
Object
- Object
- Agentilda::Linear::Attribution
- Defined in:
- lib/agentilda/linear/attribution.rb
Overview
Which plan a pull request belongs to, when its title does not say.
resync prs puts an [NNN.MM] on every title it can resolve, and most
of them resolve. What is left is the tail: work that shipped before the
convention existed, or from a branch named after nothing in particular.
Those pull requests are real work with no home, and dropping them means
the issues that stand for a plan are missing pieces of it.
The rule is word overlap between the pull request's title and the
folder's name. It works here, where it did not work for matching plans
to projects, because the candidates are different: a folder slug is
ledger-carryforward-vintages, three specific words about one thing,
and there are twenty of them to choose between. A project is called
"US Tax Law: Self Contained Ruby Gem" and there are four.
It is still a guess, and it says so. A tie is refused rather than broken, because two folders matching equally well is evidence that neither is right rather than a reason to pick the first.
Defined Under Namespace
Classes: Placed
Constant Summary collapse
- FLOOR =
Words too common in this domain to carry a match on their own. Every plan in a tax engine says "tax"; a pull request that says it too has told you nothing. How much of a folder's name a title must cover to claim it.
0.5- WIDER_FLOOR =
And how much a description must cover, which is more.
A title is written to say what the change is. A description is written to get the change reviewed, and it opens with whatever this repository puts at the top of every one of them — a stacking note, a diff summary, a checklist. Read at the same bar as a title it produced two placements here and both were wrong, one of them on the word "documents" inside "diff includes nineteen documents".
0.75- MINIMUM_WORDS =
Words, not just a fraction. Half of a two-word folder name is one word, which is the case that was already established as too thin — "core" alone claiming
deterministic-core-and-as-of. 3- NOISE =
%w[the and for with from into that this add adds added fix fixes update updates use uses spec plan pull request pr tax app web api].freeze
- OPENING_WORDS =
How much of a pull request's description to read when its title was not enough. The opening sentence or two of a description says what the change is for; further down it turns into checklists, test plans and generated tables, which are the same words on every pull request in the repository and match everything equally.
20
Instance Method Summary collapse
- #call(pulls, bodies: {}) ⇒ Array<Agentilda::Linear::Attribution::Placed>
-
#initialize(tree:) ⇒ Attribution
constructor
A new instance of Attribution.
- #opening_words(body) ⇒ Array<String>
Constructor Details
#initialize(tree:) ⇒ Attribution
Returns a new instance of Attribution.
81 82 83 |
# File 'lib/agentilda/linear/attribution.rb', line 81 def initialize(tree:) @tree = tree end |
Instance Method Details
#call(pulls, bodies: {}) ⇒ Array<Agentilda::Linear::Attribution::Placed>
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/agentilda/linear/attribution.rb', line 95 def call(pulls, bodies: {}) pulls.map do |pull| found = place(pull, words(pull.title)) next found if found.placed? # Second pass. A title is a headline and sometimes says nothing # useful — "Add the Drake reference-return worklist" names a vendor # rather than the work. The description usually opens by saying what # the change is actually about. opening = opening_words(bodies[pull.number.to_s]) next found if opening.empty? wider = place(pull, words(pull.title) | opening, floor: WIDER_FLOOR) wider.placed? ? wider.with(widened: true) : found end end |
#opening_words(body) ⇒ Array<String>
114 115 116 117 118 119 120 |
# File 'lib/agentilda/linear/attribution.rb', line 114 def opening_words(body) text = body.to_s .gsub(/<!--.*?-->/m, "") .gsub(/```.*?```/m, "") .gsub(/^\s*[-*|#>]+/, " ") words(text.split(/\s+/).first(OPENING_WORDS * 3).join(" ")).first(OPENING_WORDS) end |