terminalhire 0.26.0 → 0.26.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -700,6 +700,13 @@ var init_rigor = __esm({
700
700
  }
701
701
  });
702
702
 
703
+ // ../../packages/core/src/gh-governor.ts
704
+ var init_gh_governor = __esm({
705
+ "../../packages/core/src/gh-governor.ts"() {
706
+ "use strict";
707
+ }
708
+ });
709
+
703
710
  // ../../packages/core/src/github.ts
704
711
  function bestAcceptanceDomain(cred, domains) {
705
712
  if (cred.status !== "ok") return null;
@@ -718,6 +725,7 @@ var init_github = __esm({
718
725
  init_contribution_gate();
719
726
  init_contribution_gate();
720
727
  init_rigor();
728
+ init_gh_governor();
721
729
  RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
722
730
  }
723
731
  });
@@ -799,34 +807,45 @@ function mergeSoftCoverage(covMap, softTags, cap) {
799
807
  }
800
808
  return covMap;
801
809
  }
810
+ function tagKernel(job, ctx) {
811
+ const { expanded, covMap, maxDevScore, skillTags } = ctx;
812
+ const details = [];
813
+ let jobMatchScore = 0;
814
+ let jobMaxScore = 0;
815
+ const devCovByTag = /* @__PURE__ */ new Map();
816
+ for (const tag of job.tags) {
817
+ const w = backgroundIdf(tag);
818
+ jobMaxScore += w;
819
+ const covHit = covMap.get(tag);
820
+ if (covHit) jobMatchScore += w * Math.pow(covHit.weight, SHARPEN);
821
+ const fpHit = expanded.get(tag);
822
+ if (fpHit) {
823
+ const credit = Math.pow(fpHit.weight, SHARPEN);
824
+ details.push({ tag, weight: fpHit.weight, via: fpHit.via });
825
+ if (credit > (devCovByTag.get(fpHit.via) ?? 0)) devCovByTag.set(fpHit.via, credit);
826
+ }
827
+ }
828
+ let devScore = 0;
829
+ for (const t of skillTags) devScore += backgroundIdf(t) * (devCovByTag.get(t) ?? 0);
830
+ const devCov = maxDevScore > 0 ? Math.min(1, devScore / maxDevScore) : 0;
831
+ const jobCov = jobMaxScore > 0 ? Math.min(1, jobMatchScore / jobMaxScore) : 0;
832
+ return { tagComponent: harmonicMean(devCov, jobCov), details };
833
+ }
834
+ function relevanceScore(fp, job, softTags = []) {
835
+ const expanded = expandWeighted(fp.skillTags);
836
+ const covMap = softTags.length > 0 ? mergeSoftCoverage(new Map(expanded), softTags, INTEREST_CAP) : expanded;
837
+ const maxDevScore = fp.skillTags.reduce((acc, t) => acc + backgroundIdf(t), 0);
838
+ return tagKernel(job, { expanded, covMap, maxDevScore, skillTags: fp.skillTags }).tagComponent;
839
+ }
802
840
  function match(fp, jobs, limit = 5, now = Date.now(), opts = {}) {
803
841
  const idfOf = backgroundIdf;
804
842
  const expanded = expandWeighted(fp.skillTags);
805
843
  const covMap = opts.softTags && opts.softTags.length > 0 ? mergeSoftCoverage(new Map(expanded), opts.softTags, INTEREST_CAP) : expanded;
806
844
  const maxDevScore = fp.skillTags.reduce((acc, t) => acc + idfOf(t), 0);
845
+ const ctx = { expanded, covMap, maxDevScore, skillTags: fp.skillTags };
807
846
  const candidates = jobs.filter((j) => passesFilters(fp, j));
808
847
  const scored = candidates.map((job) => {
809
- const details = [];
810
- let jobMatchScore = 0;
811
- let jobMaxScore = 0;
812
- const devCovByTag = /* @__PURE__ */ new Map();
813
- for (const tag of job.tags) {
814
- const w = idfOf(tag);
815
- jobMaxScore += w;
816
- const covHit = covMap.get(tag);
817
- if (covHit) jobMatchScore += w * Math.pow(covHit.weight, SHARPEN);
818
- const fpHit = expanded.get(tag);
819
- if (fpHit) {
820
- const credit = Math.pow(fpHit.weight, SHARPEN);
821
- details.push({ tag, weight: fpHit.weight, via: fpHit.via });
822
- if (credit > (devCovByTag.get(fpHit.via) ?? 0)) devCovByTag.set(fpHit.via, credit);
823
- }
824
- }
825
- let devScore = 0;
826
- for (const t of fp.skillTags) devScore += idfOf(t) * (devCovByTag.get(t) ?? 0);
827
- const devCov = maxDevScore > 0 ? Math.min(1, devScore / maxDevScore) : 0;
828
- const jobCov = jobMaxScore > 0 ? Math.min(1, jobMatchScore / jobMaxScore) : 0;
829
- const tagComponent = harmonicMean(devCov, jobCov);
848
+ const { tagComponent, details } = tagKernel(job, ctx);
830
849
  if (tagComponent === 0) return null;
831
850
  const coreTags = job.coreTags ?? coreTagsFromTitle(job.title);
832
851
  let coreComponent = tagComponent;
@@ -1147,9 +1166,20 @@ var init_feeds = __esm({
1147
1166
  });
1148
1167
 
1149
1168
  // ../../packages/core/src/feeds/contribution-classify.ts
1169
+ var CONTENT_NOUN_STRONG, CONTENT_NOUN_BROAD, CONTENT_ADD_RE, NUMBERED_SEED_RE;
1150
1170
  var init_contribution_classify = __esm({
1151
1171
  "../../packages/core/src/feeds/contribution-classify.ts"() {
1152
1172
  "use strict";
1173
+ CONTENT_NOUN_STRONG = String.raw`proverbs?|words?|phrases?|sayings?|quotes?|quotations?|translations?|entry|entries|definitions?|terms?|idioms?|synonyms?|antonyms?|acronyms?|abbreviations?`;
1174
+ CONTENT_NOUN_BROAD = String.raw`trivia\s+questions?|grammar\s+points?|trivia|facts?|quiz(?:zes)?|flash\s?cards?|vocab(?:ulary)?|lessons?|kanji`;
1175
+ CONTENT_ADD_RE = new RegExp(
1176
+ String.raw`\badd(?:ing|s)?\s+(?:\w+\s+){0,4}?(?:${CONTENT_NOUN_STRONG})\b`,
1177
+ "i"
1178
+ );
1179
+ NUMBERED_SEED_RE = new RegExp(
1180
+ String.raw`\badd(?:ing|s)?\s+(?:\w+\s+){0,4}?(?:${CONTENT_NOUN_STRONG}|${CONTENT_NOUN_BROAD})\s*#?\s*\d{1,3}\s*$`,
1181
+ "i"
1182
+ );
1153
1183
  }
1154
1184
  });
1155
1185
 
@@ -1165,6 +1195,7 @@ var init_contributions = __esm({
1165
1195
  init_contribution_classify();
1166
1196
  init_github_bounties();
1167
1197
  init_http();
1198
+ init_gh_governor();
1168
1199
  CONTRIB_LABEL_QUERIES = [
1169
1200
  'label:"good first issue" type:issue state:open',
1170
1201
  'label:"good-first-issue" type:issue state:open',
@@ -1227,6 +1258,7 @@ var init_indexer = __esm({
1227
1258
  init_contributions();
1228
1259
  init_partners();
1229
1260
  init_github();
1261
+ init_gh_governor();
1230
1262
  init_winnability();
1231
1263
  }
1232
1264
  });
@@ -1360,6 +1392,7 @@ var init_src = __esm({
1360
1392
  init_winnability();
1361
1393
  init_partners();
1362
1394
  init_github();
1395
+ init_gh_governor();
1363
1396
  init_credit();
1364
1397
  init_intro();
1365
1398
  init_directoryThreshold();
@@ -1380,9 +1413,9 @@ var init_keytar = __esm({
1380
1413
  }
1381
1414
  });
1382
1415
 
1383
- // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a4d8b1364e2f66adc/node_modules/keytar/build/Release/keytar.node
1416
+ // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1384
1417
  var require_keytar = __commonJS({
1385
- "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a4d8b1364e2f66adc/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1418
+ "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1386
1419
  "use strict";
1387
1420
  init_keytar();
1388
1421
  try {
@@ -1821,9 +1854,19 @@ function defaultPrompt(question) {
1821
1854
  });
1822
1855
  });
1823
1856
  }
1857
+ var STRONG_THRESHOLD = 0.5;
1858
+ if (STRONG_THRESHOLD <= 0) {
1859
+ throw new Error("STRONG_THRESHOLD must be > 0 or the contested-issue fail-safe breaks");
1860
+ }
1824
1861
  function rankContributions(fp, items) {
1825
1862
  if (!fp || !Array.isArray(items) || items.length === 0) return [];
1826
- return match(fp, items, items.length);
1863
+ const ranked = match(fp, items, items.length);
1864
+ const rel = new Map(ranked.map((r) => [r, relevanceScore(fp, r.job)]));
1865
+ ranked.sort((a, b) => (rel.get(b) ?? 0) - (rel.get(a) ?? 0));
1866
+ return ranked.filter((r) => {
1867
+ const contested = (r.job.contribution?.openPRsAtDiscovery ?? 0) > 0;
1868
+ return !contested || (rel.get(r) ?? 0) >= STRONG_THRESHOLD;
1869
+ });
1827
1870
  }
1828
1871
  async function rankLocally(items, injectedFp) {
1829
1872
  if (!Array.isArray(items) || items.length === 0) return [];