Class: Agentilda::Linear::Survey
- Inherits:
-
Object
- Object
- Agentilda::Linear::Survey
- Defined in:
- lib/agentilda/linear/survey.rb
Overview
What a team already has in Linear, set against what .plans holds.
This exists because the import cannot see Linear at all — that is the property that makes its dry run trustworthy — and the cost of that property is a blind spot: a plan whose project someone already made by hand looks, from disk, exactly like a plan that has none. Proposing to create it would quietly produce a second project beside the first.
So the reconciliation is its own read-only command rather than something smuggled into the import. It answers one question — is anything here already in Linear under a different name? — and answers it by showing both lists rather than by guessing.
Defined Under Namespace
Classes: Match
Instance Attribute Summary collapse
-
#projects ⇒ Array<Hash>
readonly
Every project, as Linear reports it.
Instance Method Summary collapse
- #described?(project) ⇒ Boolean
-
#guess(subject) ⇒ Array(Hash, Integer)?
The best guess at which project a plan belongs under, for
--auto-assign, with the number of words it agreed on. -
#initialize(tree:, projects:) ⇒ Survey
constructor
A new instance of Survey.
- #matches ⇒ Array<Agentilda::Linear::Survey::Match>
-
#near(subject) ⇒ Array<Hash>
Projects whose name shares the plan's words without matching either rule, best first.
-
#project(reference) ⇒ Hash
Find one project by whatever the user had to hand: its URL, its name, or its id.
-
#uncovered ⇒ Array<Agentilda::Subject>
Plans with no project.
-
#undescribed ⇒ Array<Hash>
Projects with nothing written about them.
-
#unmatched ⇒ Array<Hash>
Projects that correspond to no plan.
Constructor Details
#initialize(tree:, projects:) ⇒ Survey
Returns a new instance of Survey.
30 31 32 33 |
# File 'lib/agentilda/linear/survey.rb', line 30 def initialize(tree:, projects:) @tree = tree @projects = projects end |
Instance Attribute Details
#projects ⇒ Array<Hash> (readonly)
Returns every project, as Linear reports it.
36 37 38 |
# File 'lib/agentilda/linear/survey.rb', line 36 def projects @projects end |
Instance Method Details
#described?(project) ⇒ Boolean
89 |
# File 'lib/agentilda/linear/survey.rb', line 89 def described?(project) = !prose(project).strip.empty? |
#guess(subject) ⇒ Array(Hash, Integer)?
The best guess at which project a plan belongs under, for
--auto-assign, with the number of words it agreed on.
One shared word is not evidence — half these plans mention "tax" — so
a guess needs two. Even then it is reported as a guess wherever it
appears, because plaid-integration matching Plaid Connectivity is
obvious to a person and, to this, indistinguishable from
tax-engine-consolidation matching Tax Law Engine, which is wrong.
70 71 72 73 74 75 |
# File 'lib/agentilda/linear/survey.rb', line 70 def guess(subject) best, score = scored(subject).first return nil unless best && score >= 2 [best, score] end |
#matches ⇒ Array<Agentilda::Linear::Survey::Match>
39 |
# File 'lib/agentilda/linear/survey.rb', line 39 def matches = @matches ||= projects.filter_map { |project| match_for(project) } |
#near(subject) ⇒ Array<Hash>
Projects whose name shares the plan's words without matching either rule, best first.
57 |
# File 'lib/agentilda/linear/survey.rb', line 57 def near(subject) = scored(subject).map(&:first) |
#project(reference) ⇒ Hash
Find one project by whatever the user had to hand: its URL, its name, or its id. A URL is the thing you can actually copy out of Linear.
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/agentilda/linear/survey.rb', line 97 def project(reference) wanted = reference.to_s.strip found = projects.find { |p| p["url"].to_s.casecmp?(wanted) || p["name"].to_s.casecmp?(wanted) || p["id"] == wanted || p["url"].to_s.end_with?("/#{slugify(wanted)}") } return found if found raise Error, "no project matches #{reference.inspect}. This team has:\n" + projects.map { |p| " #{p["name"]}\n #{p["url"]}" }.join("\n") end |
#uncovered ⇒ Array<Agentilda::Subject>
Plans with no project. An import would create one for each.
50 |
# File 'lib/agentilda/linear/survey.rb', line 50 def uncovered = tree.subjects - matches.map(&:subject) |
#undescribed ⇒ Array<Hash>
Projects with nothing written about them.
A name is three or four words and half of them are the company's. What makes a plan recognisably one project's business rather than another's is the sentence saying what the project is for, and where that sentence is missing there is nothing to match a specification against.
85 |
# File 'lib/agentilda/linear/survey.rb', line 85 def undescribed = projects.reject { |p| described?(p) } |
#unmatched ⇒ Array<Hash>
Projects that correspond to no plan. Usually the team's real, hand-curated projects — the ones an import has no business touching.
45 |
# File 'lib/agentilda/linear/survey.rb', line 45 def unmatched = projects - matches.map(&:project) |