terminalhire 0.35.0 → 0.35.3

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.
Files changed (46) hide show
  1. package/dist/bin/claim-push-bg.js +10 -58
  2. package/dist/bin/jpi-bounties.js +124 -77
  3. package/dist/bin/jpi-chat-read.js +29 -60
  4. package/dist/bin/jpi-chat.js +31 -62
  5. package/dist/bin/jpi-claim.js +125 -78
  6. package/dist/bin/jpi-config.js +51 -1
  7. package/dist/bin/jpi-contribute.js +30 -61
  8. package/dist/bin/jpi-devs.js +124 -77
  9. package/dist/bin/jpi-dispatch.js +682 -6167
  10. package/dist/bin/jpi-hub.js +127 -79
  11. package/dist/bin/jpi-inbox.js +31 -62
  12. package/dist/bin/jpi-init.js +113 -18
  13. package/dist/bin/jpi-intro.js +28 -60
  14. package/dist/bin/jpi-jobs.js +126 -78
  15. package/dist/bin/jpi-learn.js +28 -60
  16. package/dist/bin/jpi-link.js +2 -1
  17. package/dist/bin/jpi-login.js +127 -79
  18. package/dist/bin/jpi-mcp.js +148 -5827
  19. package/dist/bin/jpi-profile.js +28 -60
  20. package/dist/bin/jpi-project.js +113 -18
  21. package/dist/bin/jpi-protocol.js +73 -5
  22. package/dist/bin/jpi-refresh.js +158 -83
  23. package/dist/bin/jpi-repo.js +27 -59
  24. package/dist/bin/jpi-save.js +28 -60
  25. package/dist/bin/jpi-spinner.js +14 -0
  26. package/dist/bin/jpi-sync.js +28 -60
  27. package/dist/bin/jpi-trajectory.js +28 -60
  28. package/dist/bin/jpi-update.js +487 -5
  29. package/dist/bin/peer-connect-prompt.js +2 -1
  30. package/dist/bin/pulse-prompt.js +2 -1
  31. package/dist/bin/spinner.js +18 -1
  32. package/dist/src/chat-client.js +24 -61
  33. package/dist/src/chat-keystore.js +24 -61
  34. package/dist/src/config.js +17 -1
  35. package/dist/src/crypto-store.js +11 -62
  36. package/dist/src/github-auth.js +10 -61
  37. package/dist/src/intro.js +28 -60
  38. package/dist/src/link.js +2 -1
  39. package/dist/src/profile.js +25 -62
  40. package/dist/src/protocol.js +72 -4
  41. package/dist/src/repo-experience.js +24 -61
  42. package/dist/src/reputation/fetch.js +14 -0
  43. package/dist/src/signal.js +14 -0
  44. package/dist/src/trajectory.js +28 -60
  45. package/package.json +1 -1
  46. package/dist/keytar-KOAAH267.node +0 -0
@@ -4,16 +4,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
- }) : x)(function(x) {
10
- if (typeof require !== "undefined") return require.apply(this, arguments);
11
- throw Error('Dynamic require of "' + x + '" is not supported');
12
- });
13
7
  var __esm = (fn, res) => function __init() {
14
8
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
9
  };
16
- var __commonJS = (cb, mod) => function __require2() {
10
+ var __commonJS = (cb, mod) => function __require() {
17
11
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
12
  };
19
13
  var __export = (target, all) => {
@@ -37,61 +31,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
31
  mod
38
32
  ));
39
33
 
40
- // ../../node_modules/keytar/build/Release/keytar.node
41
- var keytar_default;
42
- var init_keytar = __esm({
43
- "../../node_modules/keytar/build/Release/keytar.node"() {
44
- keytar_default = "../keytar-KOAAH267.node";
45
- }
46
- });
47
-
48
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node
49
- var require_keytar = __commonJS({
50
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node"(exports, module) {
51
- "use strict";
52
- init_keytar();
53
- try {
54
- module.exports = __require(keytar_default);
55
- } catch {
56
- }
57
- }
58
- });
59
-
60
34
  // ../../node_modules/keytar/lib/keytar.js
61
- var require_keytar2 = __commonJS({
35
+ var require_keytar = __commonJS({
62
36
  "../../node_modules/keytar/lib/keytar.js"(exports, module) {
63
37
  "use strict";
64
- var keytar = require_keytar();
65
- function checkRequired(val, name) {
66
- if (!val || val.length <= 0) {
67
- throw new Error(name + " is required.");
68
- }
38
+ function disabled() {
39
+ throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
69
40
  }
70
41
  module.exports = {
71
- getPassword: function(service, account) {
72
- checkRequired(service, "Service");
73
- checkRequired(account, "Account");
74
- return keytar.getPassword(service, account);
75
- },
76
- setPassword: function(service, account, password) {
77
- checkRequired(service, "Service");
78
- checkRequired(account, "Account");
79
- checkRequired(password, "Password");
80
- return keytar.setPassword(service, account, password);
81
- },
82
- deletePassword: function(service, account) {
83
- checkRequired(service, "Service");
84
- checkRequired(account, "Account");
85
- return keytar.deletePassword(service, account);
86
- },
87
- findPassword: function(service) {
88
- checkRequired(service, "Service");
89
- return keytar.findPassword(service);
90
- },
91
- findCredentials: function(service) {
92
- checkRequired(service, "Service");
93
- return keytar.findCredentials(service);
94
- }
42
+ getPassword: disabled,
43
+ setPassword: disabled,
44
+ deletePassword: disabled,
45
+ findPassword: disabled,
46
+ findCredentials: disabled
95
47
  };
96
48
  }
97
49
  });
@@ -313,7 +265,7 @@ function skipKeychain() {
313
265
  async function loadKey() {
314
266
  if (!skipKeychain()) {
315
267
  try {
316
- const kt = await Promise.resolve().then(() => __toESM(require_keytar2(), 1));
268
+ const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
317
269
  const stored = await kt.getPassword("terminalhire", "profile-key");
318
270
  if (stored) return Buffer.from(stored, "hex");
319
271
  const key2 = randomBytes(KEY_BYTES);
@@ -5,16 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
- }) : x)(function(x) {
11
- if (typeof require !== "undefined") return require.apply(this, arguments);
12
- throw Error('Dynamic require of "' + x + '" is not supported');
13
- });
14
8
  var __esm = (fn, res) => function __init() {
15
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
10
  };
17
- var __commonJS = (cb, mod2) => function __require2() {
11
+ var __commonJS = (cb, mod2) => function __require() {
18
12
  return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
19
13
  };
20
14
  var __export = (target, all) => {
@@ -1735,6 +1729,25 @@ async function resolveClosingIssues(owner, name, number, body, token, signal, go
1735
1729
  while ((m = re.exec(body)) !== null) nums.add(parseInt(m[1], 10));
1736
1730
  return { closesIssues: [...nums], linkageSource: nums.size ? "body-keyword" : "none" };
1737
1731
  }
1732
+ async function openPRClosingRefs(owner, name, token, signal, governor) {
1733
+ const q = `query($o:String!,$n:String!){repository(owner:$o,name:$n){pullRequests(states:OPEN,first:100){totalCount nodes{number closingIssuesReferences(first:20){nodes{number}}}}}rateLimit{cost remaining}}`;
1734
+ try {
1735
+ const r = await ghGraphQL(q, { o: owner, n: name }, token, signal, governor);
1736
+ if (r === null) return null;
1737
+ if (!r.data?.repository) return null;
1738
+ const prs = r.data.repository.pullRequests;
1739
+ if (prs && prs.nodes !== void 0 && !Array.isArray(prs.nodes)) return null;
1740
+ const nodes = prs?.nodes ?? [];
1741
+ const refs = /* @__PURE__ */ new Set();
1742
+ for (const node of nodes) {
1743
+ for (const ref of node.closingIssuesReferences?.nodes ?? []) refs.add(ref.number);
1744
+ }
1745
+ const totalCount = prs?.totalCount ?? nodes.length;
1746
+ return { refs, capHit: totalCount > nodes.length, totalCount };
1747
+ } catch {
1748
+ return null;
1749
+ }
1750
+ }
1738
1751
  function makeScoringGovernor(governor) {
1739
1752
  return governor ?? makeGitHubGovernor(
1740
1753
  ((url, init) => fetch(url, init)),
@@ -3487,7 +3500,7 @@ function firstNumber(xs) {
3487
3500
  function isWinnableIssue(issue) {
3488
3501
  const contested = (issue.contribution.openPRsAtDiscovery ?? 0) > 0;
3489
3502
  if (contested) return false;
3490
- if (issue.winnabilityScore !== void 0 && issue.winnabilityScore <= 0) return false;
3503
+ if (issue.winnabilityScore != null && issue.winnabilityScore <= 0) return false;
3491
3504
  return true;
3492
3505
  }
3493
3506
  function issueRecency(postedAt, now) {
@@ -3504,6 +3517,7 @@ function issueRecency(postedAt, now) {
3504
3517
  function curateProjects(issues, opts = {}) {
3505
3518
  const now = opts.now ?? Date.now();
3506
3519
  const vocabSet = new Set(opts.vocabTerms ?? []);
3520
+ const applyFloor = opts.applySkillFloor ?? SKILL_FLOOR_ENABLED;
3507
3521
  const groups = /* @__PURE__ */ new Map();
3508
3522
  for (const issue of issues) {
3509
3523
  const key = repoKeyOf(issue.contribution.repoFullName);
@@ -3531,15 +3545,21 @@ function curateProjects(issues, opts = {}) {
3531
3545
  }
3532
3546
  if (topTags.length >= 4) break;
3533
3547
  }
3548
+ const repoLanguageRaw = firstNonEmptyString(
3549
+ winnableIssues.map((i) => i.contribution.language ?? "")
3550
+ );
3551
+ const languageIds = new Set(repoLanguageRaw ? normalize(tokenize(repoLanguageRaw)) : []);
3552
+ const skillTagUnion = /* @__PURE__ */ new Set();
3553
+ for (const iss of winnableIssues) for (const t of iss.tags ?? []) skillTagUnion.add(t);
3554
+ let distinctNonLanguageSkillTags = 0;
3555
+ for (const t of skillTagUnion) if (!languageIds.has(t)) distinctNonLanguageSkillTags++;
3556
+ if (applyFloor && distinctNonLanguageSkillTags < SKILL_FLOOR_MIN) continue;
3557
+ const skillDensity = clamp012(distinctNonLanguageSkillTags / SKILL_DENSITY_SATURATION);
3534
3558
  let vocabRelevance = 0;
3535
- if (vocabSet.size > 0) {
3536
- const repoTags = /* @__PURE__ */ new Set();
3537
- for (const iss of winnableIssues) for (const t of iss.tags ?? []) repoTags.add(t);
3538
- if (repoTags.size > 0) {
3539
- let matched = 0;
3540
- for (const t of repoTags) if (vocabSet.has(t)) matched++;
3541
- vocabRelevance = matched / repoTags.size;
3542
- }
3559
+ if (vocabSet.size > 0 && skillTagUnion.size > 0) {
3560
+ let matched = 0;
3561
+ for (const t of skillTagUnion) if (vocabSet.has(t)) matched++;
3562
+ vocabRelevance = matched / skillTagUnion.size;
3543
3563
  }
3544
3564
  const cadence = clamp012((commitCadence ?? 0) / CURATION_NORM.commitCadence);
3545
3565
  let recency = 0;
@@ -3558,6 +3578,8 @@ function curateProjects(issues, opts = {}) {
3558
3578
  repoContributors: repoContributors ?? null,
3559
3579
  topTags,
3560
3580
  vocabRelevance,
3581
+ distinctNonLanguageSkillTags,
3582
+ skillDensity,
3561
3583
  freshness,
3562
3584
  mergeVelocity,
3563
3585
  popularity
@@ -3567,7 +3589,7 @@ function curateProjects(issues, opts = {}) {
3567
3589
  const cards = partials.map((p) => {
3568
3590
  const winnableCount = p.winnableIssues.length;
3569
3591
  const winnableCountNorm = maxCount > 0 ? winnableCount / maxCount : 0;
3570
- const score = CURATION_WEIGHTS.winnableCount * winnableCountNorm + CURATION_WEIGHTS.vocabRelevance * p.vocabRelevance + CURATION_WEIGHTS.freshness * p.freshness + CURATION_WEIGHTS.mergeVelocity * p.mergeVelocity + CURATION_WEIGHTS.popularity * p.popularity;
3592
+ const score = CURATION_WEIGHTS.winnableCount * winnableCountNorm + CURATION_WEIGHTS.vocabRelevance * p.vocabRelevance + CURATION_WEIGHTS.skillDensity * p.skillDensity + CURATION_WEIGHTS.freshness * p.freshness + CURATION_WEIGHTS.mergeVelocity * p.mergeVelocity + CURATION_WEIGHTS.popularity * p.popularity;
3571
3593
  return {
3572
3594
  repoKey: p.repoKey,
3573
3595
  description: p.description,
@@ -3580,6 +3602,8 @@ function curateProjects(issues, opts = {}) {
3580
3602
  winnableCount,
3581
3603
  winnableCountNorm,
3582
3604
  vocabRelevance: p.vocabRelevance,
3605
+ distinctNonLanguageSkillTags: p.distinctNonLanguageSkillTags,
3606
+ skillDensity: p.skillDensity,
3583
3607
  freshness: p.freshness,
3584
3608
  mergeVelocity: p.mergeVelocity,
3585
3609
  popularity: p.popularity
@@ -3591,18 +3615,32 @@ function curateProjects(issues, opts = {}) {
3591
3615
  );
3592
3616
  return cards;
3593
3617
  }
3594
- var CURATION_WEIGHTS, CURATION_NORM, repoKeyOf;
3618
+ function rosterActiveFromContribution(issues) {
3619
+ return curateProjects(issues).map((c) => ({ repoKey: c.repoKey, topTags: c.topTags }));
3620
+ }
3621
+ var CURATION_WEIGHTS, SKILL_DENSITY_SATURATION, SKILL_FLOOR_ENABLED, SKILL_FLOOR_MIN, CURATION_NORM, repoKeyOf;
3595
3622
  var init_projectCuration = __esm({
3596
3623
  "../../packages/core/src/feeds/projectCuration.ts"() {
3597
3624
  "use strict";
3625
+ init_vocab();
3598
3626
  init_winnability();
3599
3627
  CURATION_WEIGHTS = {
3600
3628
  winnableCount: 0.45,
3601
- vocabRelevance: 0.2,
3629
+ vocabRelevance: 0.05,
3630
+ skillDensity: 0.15,
3602
3631
  freshness: 0.15,
3603
3632
  mergeVelocity: 0.15,
3604
3633
  popularity: 0.05
3605
3634
  };
3635
+ SKILL_DENSITY_SATURATION = 3;
3636
+ SKILL_FLOOR_ENABLED = false;
3637
+ SKILL_FLOOR_MIN = 1;
3638
+ {
3639
+ const _sum = Object.values(CURATION_WEIGHTS).reduce((a, b) => a + b, 0);
3640
+ if (Math.abs(_sum - 1) > 1e-9) {
3641
+ throw new Error(`CURATION_WEIGHTS must sum to 1.0, got ${_sum}`);
3642
+ }
3643
+ }
3606
3644
  CURATION_NORM = {
3607
3645
  /** ~60 commits in the last ~30d is treated as "maxed" commit-cadence freshness. */
3608
3646
  commitCadence: 60,
@@ -3877,7 +3915,7 @@ var init_feeds = __esm({
3877
3915
  DEFAULT_ASHBY_SLUGS = flattenTiers(ASHBY_SLUGS_BY_TIER);
3878
3916
  DEFAULT_LEVER_SLUGS = flattenTiers(LEVER_SLUGS_BY_TIER);
3879
3917
  DEFAULT_WORKABLE_SLUGS = ["zego", "workmotion"];
3880
- MAX_JOBS_PER_COMPANY = 3;
3918
+ MAX_JOBS_PER_COMPANY = 10;
3881
3919
  BIGCO_SLUGS_BY_SOURCE = {
3882
3920
  greenhouse: new Set(GREENHOUSE_SLUGS_BY_TIER.bigco.map((s) => s.toLowerCase())),
3883
3921
  ashby: new Set(ASHBY_SLUGS_BY_TIER.bigco.map((s) => s.toLowerCase())),
@@ -3926,7 +3964,7 @@ function makeClient(fetchImpl, cfg) {
3926
3964
  async function probe(path) {
3927
3965
  return gov.probe(`${GITHUB_API2}${path}`, { headers: authHeaders2() });
3928
3966
  }
3929
- return { raw, json, probe, setSecondaryHint: gov.setSecondaryHint, getStats: gov.getStats };
3967
+ return { raw, json, probe, governor: gov, setSecondaryHint: gov.setSecondaryHint, getStats: gov.getStats };
3930
3968
  }
3931
3969
  async function contributorCount(client, fullName) {
3932
3970
  const res = await client.raw(`/repos/${fullName}/contributors?per_page=1&anon=false`);
@@ -3942,14 +3980,27 @@ async function contributorCount(client, fullName) {
3942
3980
  }
3943
3981
  }
3944
3982
  async function openPRIssueRefs(client, fullName) {
3983
+ const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
3984
+ const [owner, name] = fullName.split("/");
3985
+ if (token && owner && name) {
3986
+ const res = await openPRClosingRefs(owner, name, token, void 0, client.governor);
3987
+ if (res === null) return null;
3988
+ if (res.capHit) {
3989
+ console.warn(
3990
+ `[contribute] open-PR closing-ref scan capped at 100/${res.totalCount} open PRs for ${fullName} (closing refs beyond the first 100 open PRs not scanned)`
3991
+ );
3992
+ }
3993
+ return res.refs;
3994
+ }
3945
3995
  const prs = await client.json(
3946
3996
  `/repos/${fullName}/pulls?state=open&per_page=100`
3947
3997
  );
3948
3998
  if (!Array.isArray(prs)) return null;
3949
3999
  const refs = /* @__PURE__ */ new Set();
3950
4000
  for (const pr of prs) {
3951
- for (const m of `${pr.title ?? ""}
3952
- ${pr.body ?? ""}`.matchAll(/#(\d+)\b/g)) {
4001
+ const text = `${pr.title ?? ""}
4002
+ ${pr.body ?? ""}`;
4003
+ for (const m of text.matchAll(/\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi)) {
3953
4004
  refs.add(Number(m[1]));
3954
4005
  }
3955
4006
  }
@@ -3999,7 +4050,11 @@ function buildContributionJob(a) {
3999
4050
  // verified-empty/non-matching set; a failed check leaves it undefined (never a
4000
4051
  // fabricated 0), so the claim path falls through to a live re-count.
4001
4052
  openPRsAtDiscovery: a.openPRsAtDiscovery,
4002
- repoDescription: a.repo.description || null
4053
+ repoDescription: a.repo.description || null,
4054
+ // TERM-27: persist the repo's primary language so project curation can
4055
+ // exclude the repo's OWN language id (folded into every issue's tags) from
4056
+ // the distinct-skill signal. Same `repo` used by the tokenize() tag build.
4057
+ language: a.repo.language ?? null
4003
4058
  },
4004
4059
  // Provenance: repo-first discovered items only (label-first omits the field).
4005
4060
  ...a.discovered ? { discovered: true } : {},
@@ -4323,6 +4378,7 @@ var init_contributions = __esm({
4323
4378
  init_contribution_gate();
4324
4379
  init_contribution_classify();
4325
4380
  init_github_bounties();
4381
+ init_github();
4326
4382
  init_http();
4327
4383
  init_gh_governor();
4328
4384
  GITHUB_API2 = "https://api.github.com";
@@ -8171,11 +8227,35 @@ import { createHash as createHash2 } from "crypto";
8171
8227
  function opportunityShortToken(id) {
8172
8228
  return createHash2("sha256").update(id, "utf8").digest("base64url").slice(0, 8);
8173
8229
  }
8174
- var contributeShortToken;
8230
+ function jobShortToken(id) {
8231
+ return createHash2("sha256").update(`job:${id}`, "utf8").digest("base64url").slice(0, 8);
8232
+ }
8233
+ function jobTokenMap(index) {
8234
+ const cached = jobTokenMaps.get(index);
8235
+ if (cached) return cached;
8236
+ const map = /* @__PURE__ */ new Map();
8237
+ for (const job of index.jobs) {
8238
+ const token = jobShortToken(job.id);
8239
+ map.set(token, map.has(token) ? AMBIGUOUS_JOB_TOKEN : job);
8240
+ }
8241
+ jobTokenMaps.set(index, map);
8242
+ return map;
8243
+ }
8244
+ function resolveJobToken(index, token) {
8245
+ const hit = jobTokenMap(index).get(token);
8246
+ return hit && hit !== AMBIGUOUS_JOB_TOKEN ? hit : null;
8247
+ }
8248
+ function _jobTokenMapForTests(index) {
8249
+ return jobTokenMap(index);
8250
+ }
8251
+ var contributeShortToken, AMBIGUOUS_JOB_TOKEN, jobTokenMaps, _AMBIGUOUS_JOB_TOKEN_FOR_TESTS;
8175
8252
  var init_short_token = __esm({
8176
8253
  "../../packages/core/src/short-token.ts"() {
8177
8254
  "use strict";
8178
8255
  contributeShortToken = opportunityShortToken;
8256
+ AMBIGUOUS_JOB_TOKEN = /* @__PURE__ */ Symbol("ambiguous-job-token");
8257
+ jobTokenMaps = /* @__PURE__ */ new WeakMap();
8258
+ _AMBIGUOUS_JOB_TOKEN_FOR_TESTS = AMBIGUOUS_JOB_TOKEN;
8179
8259
  }
8180
8260
  });
8181
8261
 
@@ -8214,12 +8294,17 @@ __export(src_exports, {
8214
8294
  MIN_STARS: () => MIN_STARS,
8215
8295
  PROBE_TIMEOUT_MS: () => PROBE_TIMEOUT_MS,
8216
8296
  RIGOR: () => RIGOR,
8297
+ SKILL_DENSITY_SATURATION: () => SKILL_DENSITY_SATURATION,
8298
+ SKILL_FLOOR_ENABLED: () => SKILL_FLOOR_ENABLED,
8299
+ SKILL_FLOOR_MIN: () => SKILL_FLOOR_MIN,
8217
8300
  STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
8218
8301
  SYNONYMS: () => SYNONYMS,
8219
8302
  TRIVIAL_PR_TITLE: () => TRIVIAL_PR_TITLE,
8220
8303
  VOCABULARY: () => VOCABULARY,
8221
8304
  VOCAB_NODES: () => VOCAB_NODES,
8222
8305
  WINNABILITY_NORM: () => WINNABILITY_NORM,
8306
+ _AMBIGUOUS_JOB_TOKEN_FOR_TESTS: () => _AMBIGUOUS_JOB_TOKEN_FOR_TESTS,
8307
+ _jobTokenMapForTests: () => _jobTokenMapForTests,
8223
8308
  acceptanceCountForDomains: () => acceptanceCountForDomains,
8224
8309
  aggregate: () => aggregate,
8225
8310
  aggregateBounties: () => aggregateBounties,
@@ -8286,6 +8371,7 @@ __export(src_exports, {
8286
8371
  isOverIntroLimit: () => isOverIntroLimit,
8287
8372
  isTrivialPRTitle: () => isTrivialPRTitle,
8288
8373
  isWinnableIssue: () => isWinnableIssue,
8374
+ jobShortToken: () => jobShortToken,
8289
8375
  joinLabels: () => joinLabels,
8290
8376
  labelFor: () => labelFor,
8291
8377
  lever: () => lever,
@@ -8299,6 +8385,7 @@ __export(src_exports, {
8299
8385
  mergeProbability: () => mergeProbability,
8300
8386
  mmrRerank: () => mmrRerank,
8301
8387
  normalize: () => normalize,
8388
+ openPRClosingRefs: () => openPRClosingRefs,
8302
8389
  opire: () => opire,
8303
8390
  opportunityShortToken: () => opportunityShortToken,
8304
8391
  pageMatches: () => pageMatches,
@@ -8313,7 +8400,9 @@ __export(src_exports, {
8313
8400
  recordClick: () => recordClick,
8314
8401
  rejectExtraIntroFields: () => rejectExtraIntroFields,
8315
8402
  relevanceScore: () => relevanceScore,
8403
+ resolveJobToken: () => resolveJobToken,
8316
8404
  revealIntroContacts: () => revealIntroContacts,
8405
+ rosterActiveFromContribution: () => rosterActiveFromContribution,
8317
8406
  safetyNumber: () => safetyNumber,
8318
8407
  sameLogin: () => sameLogin,
8319
8408
  setStatus: () => setStatus,
@@ -8353,61 +8442,19 @@ var init_src = __esm({
8353
8442
  }
8354
8443
  });
8355
8444
 
8356
- // ../../node_modules/keytar/build/Release/keytar.node
8357
- var keytar_default;
8358
- var init_keytar = __esm({
8359
- "../../node_modules/keytar/build/Release/keytar.node"() {
8360
- keytar_default = "../keytar-KOAAH267.node";
8361
- }
8362
- });
8363
-
8364
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node
8365
- var require_keytar = __commonJS({
8366
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node"(exports, module) {
8367
- "use strict";
8368
- init_keytar();
8369
- try {
8370
- module.exports = __require(keytar_default);
8371
- } catch {
8372
- }
8373
- }
8374
- });
8375
-
8376
8445
  // ../../node_modules/keytar/lib/keytar.js
8377
- var require_keytar2 = __commonJS({
8446
+ var require_keytar = __commonJS({
8378
8447
  "../../node_modules/keytar/lib/keytar.js"(exports, module) {
8379
8448
  "use strict";
8380
- var keytar = require_keytar();
8381
- function checkRequired(val, name) {
8382
- if (!val || val.length <= 0) {
8383
- throw new Error(name + " is required.");
8384
- }
8449
+ function disabled() {
8450
+ throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
8385
8451
  }
8386
8452
  module.exports = {
8387
- getPassword: function(service, account) {
8388
- checkRequired(service, "Service");
8389
- checkRequired(account, "Account");
8390
- return keytar.getPassword(service, account);
8391
- },
8392
- setPassword: function(service, account, password) {
8393
- checkRequired(service, "Service");
8394
- checkRequired(account, "Account");
8395
- checkRequired(password, "Password");
8396
- return keytar.setPassword(service, account, password);
8397
- },
8398
- deletePassword: function(service, account) {
8399
- checkRequired(service, "Service");
8400
- checkRequired(account, "Account");
8401
- return keytar.deletePassword(service, account);
8402
- },
8403
- findPassword: function(service) {
8404
- checkRequired(service, "Service");
8405
- return keytar.findPassword(service);
8406
- },
8407
- findCredentials: function(service) {
8408
- checkRequired(service, "Service");
8409
- return keytar.findCredentials(service);
8410
- }
8453
+ getPassword: disabled,
8454
+ setPassword: disabled,
8455
+ deletePassword: disabled,
8456
+ findPassword: disabled,
8457
+ findCredentials: disabled
8411
8458
  };
8412
8459
  }
8413
8460
  });
@@ -8459,7 +8506,7 @@ function skipKeychain() {
8459
8506
  async function tryLoadFromKeytar(policy) {
8460
8507
  if (forceKeytarUnavailableForTests || skipKeychain()) return null;
8461
8508
  try {
8462
- const kt = policy === "keychain-required" ? createRequire(import.meta.url)("keytar") : await Promise.resolve().then(() => __toESM(require_keytar2(), 1));
8509
+ const kt = policy === "keychain-required" ? createRequire(import.meta.url)("keytar") : await Promise.resolve().then(() => __toESM(require_keytar(), 1));
8463
8510
  const stored = await kt.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
8464
8511
  if (stored) {
8465
8512
  return Buffer.from(stored, "hex");
@@ -8500,7 +8547,7 @@ async function deleteKey() {
8500
8547
  }
8501
8548
  if (!forceKeytarUnavailableForTests && !skipKeychain()) {
8502
8549
  try {
8503
- const kt = await Promise.resolve().then(() => __toESM(require_keytar2(), 1));
8550
+ const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
8504
8551
  await kt.deletePassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
8505
8552
  } catch {
8506
8553
  }
@@ -5,16 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
- }) : x)(function(x) {
11
- if (typeof require !== "undefined") return require.apply(this, arguments);
12
- throw Error('Dynamic require of "' + x + '" is not supported');
13
- });
14
8
  var __esm = (fn, res) => function __init() {
15
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
10
  };
17
- var __commonJS = (cb, mod2) => function __require2() {
11
+ var __commonJS = (cb, mod2) => function __require() {
18
12
  return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
19
13
  };
20
14
  var __copyProps = (to, from, except, desc) => {
@@ -707,11 +701,26 @@ var init_winnability = __esm({
707
701
  });
708
702
 
709
703
  // ../../packages/core/src/feeds/projectCuration.ts
710
- var CURATION_NORM;
704
+ var CURATION_WEIGHTS, CURATION_NORM;
711
705
  var init_projectCuration = __esm({
712
706
  "../../packages/core/src/feeds/projectCuration.ts"() {
713
707
  "use strict";
708
+ init_vocab();
714
709
  init_winnability();
710
+ CURATION_WEIGHTS = {
711
+ winnableCount: 0.45,
712
+ vocabRelevance: 0.05,
713
+ skillDensity: 0.15,
714
+ freshness: 0.15,
715
+ mergeVelocity: 0.15,
716
+ popularity: 0.05
717
+ };
718
+ {
719
+ const _sum = Object.values(CURATION_WEIGHTS).reduce((a, b) => a + b, 0);
720
+ if (Math.abs(_sum - 1) > 1e-9) {
721
+ throw new Error(`CURATION_WEIGHTS must sum to 1.0, got ${_sum}`);
722
+ }
723
+ }
715
724
  CURATION_NORM = {
716
725
  /** ~60 commits in the last ~30d is treated as "maxed" commit-cadence freshness. */
717
726
  commitCadence: 60,
@@ -875,6 +884,7 @@ var init_contributions = __esm({
875
884
  init_contribution_gate();
876
885
  init_contribution_classify();
877
886
  init_github_bounties();
887
+ init_github();
878
888
  init_http();
879
889
  init_gh_governor();
880
890
  CONTRIB_LABEL_QUERIES = [
@@ -4097,61 +4107,19 @@ var init_src = __esm({
4097
4107
  }
4098
4108
  });
4099
4109
 
4100
- // ../../node_modules/keytar/build/Release/keytar.node
4101
- var keytar_default;
4102
- var init_keytar = __esm({
4103
- "../../node_modules/keytar/build/Release/keytar.node"() {
4104
- keytar_default = "../keytar-KOAAH267.node";
4105
- }
4106
- });
4107
-
4108
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node
4109
- var require_keytar = __commonJS({
4110
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/9716ff9c-0531-4844-adf4-286763cf8ab8/scratchpad/wt-cli-update/node_modules/keytar/build/Release/keytar.node"(exports, module) {
4111
- "use strict";
4112
- init_keytar();
4113
- try {
4114
- module.exports = __require(keytar_default);
4115
- } catch {
4116
- }
4117
- }
4118
- });
4119
-
4120
4110
  // ../../node_modules/keytar/lib/keytar.js
4121
- var require_keytar2 = __commonJS({
4111
+ var require_keytar = __commonJS({
4122
4112
  "../../node_modules/keytar/lib/keytar.js"(exports, module) {
4123
4113
  "use strict";
4124
- var keytar = require_keytar();
4125
- function checkRequired(val, name) {
4126
- if (!val || val.length <= 0) {
4127
- throw new Error(name + " is required.");
4128
- }
4114
+ function disabled() {
4115
+ throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
4129
4116
  }
4130
4117
  module.exports = {
4131
- getPassword: function(service, account) {
4132
- checkRequired(service, "Service");
4133
- checkRequired(account, "Account");
4134
- return keytar.getPassword(service, account);
4135
- },
4136
- setPassword: function(service, account, password) {
4137
- checkRequired(service, "Service");
4138
- checkRequired(account, "Account");
4139
- checkRequired(password, "Password");
4140
- return keytar.setPassword(service, account, password);
4141
- },
4142
- deletePassword: function(service, account) {
4143
- checkRequired(service, "Service");
4144
- checkRequired(account, "Account");
4145
- return keytar.deletePassword(service, account);
4146
- },
4147
- findPassword: function(service) {
4148
- checkRequired(service, "Service");
4149
- return keytar.findPassword(service);
4150
- },
4151
- findCredentials: function(service) {
4152
- checkRequired(service, "Service");
4153
- return keytar.findCredentials(service);
4154
- }
4118
+ getPassword: disabled,
4119
+ setPassword: disabled,
4120
+ deletePassword: disabled,
4121
+ findPassword: disabled,
4122
+ findCredentials: disabled
4155
4123
  };
4156
4124
  }
4157
4125
  });
@@ -4178,7 +4146,7 @@ function skipKeychain() {
4178
4146
  async function loadKey() {
4179
4147
  if (!skipKeychain()) {
4180
4148
  try {
4181
- const kt = await Promise.resolve().then(() => __toESM(require_keytar2(), 1));
4149
+ const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
4182
4150
  const stored = await kt.getPassword("terminalhire", "profile-key");
4183
4151
  if (stored) return Buffer.from(stored, "hex");
4184
4152
  const key2 = randomBytes3(KEY_BYTES);
@@ -4570,7 +4538,8 @@ var init_config = __esm({
4570
4538
  betaOptIn: false,
4571
4539
  lastFullFeedbackAt: null,
4572
4540
  lastPulseAskAt: null,
4573
- pulseDisclosed: false
4541
+ pulseDisclosed: false,
4542
+ mix: "balanced"
4574
4543
  };
4575
4544
  }
4576
4545
  });